]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
16c4350632791c06577326db3374c1a83c7f5b39
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.servicegroup.nuxeo;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32 import javax.ws.rs.core.MultivaluedMap;
33 import javax.ws.rs.core.Response;
34
35 import org.collectionspace.services.nuxeo.client.java.CommonList;
36 import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
37 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
38 import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
39 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
40 import org.collectionspace.services.jaxb.AbstractCommonList;
41 import org.collectionspace.services.client.CollectionSpaceClient;
42 import org.collectionspace.services.client.IQueryManager;
43 import org.collectionspace.services.client.IRelationsManager;
44 import org.collectionspace.services.client.PoxPayloadIn;
45 import org.collectionspace.services.client.PoxPayloadOut;
46 import org.collectionspace.services.common.NuxeoBasedResource;
47 import org.collectionspace.services.common.CSWebApplicationException;
48 import org.collectionspace.services.common.ServiceMain;
49 import org.collectionspace.services.common.ServiceMessages;
50 import org.collectionspace.services.common.StoredValuesUriTemplate;
51 import org.collectionspace.services.common.UriTemplateFactory;
52 import org.collectionspace.services.common.UriTemplateRegistry;
53 import org.collectionspace.services.common.UriTemplateRegistryKey;
54 import org.collectionspace.services.common.api.RefName;
55 import org.collectionspace.services.common.api.RefNameUtils;
56 import org.collectionspace.services.common.api.RefNameUtils.AuthorityTermInfo;
57 import org.collectionspace.services.common.api.Tools;
58 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
59 import org.collectionspace.services.common.context.AbstractServiceContextImpl;
60 import org.collectionspace.services.common.context.ServiceBindingUtils;
61 import org.collectionspace.services.common.context.ServiceContext;
62 import org.collectionspace.services.common.document.DocumentException;
63 import org.collectionspace.services.common.document.DocumentFilter;
64 import org.collectionspace.services.common.document.DocumentNotFoundException;
65 import org.collectionspace.services.common.document.DocumentWrapper;
66 import org.collectionspace.services.common.document.TransactionException;
67 import org.collectionspace.services.common.security.SecurityUtils;
68 import org.collectionspace.services.common.query.QueryContext;
69 import org.collectionspace.services.common.query.nuxeo.QueryManagerNuxeoImpl;
70 import org.collectionspace.services.common.relation.nuxeo.RelationsUtils;
71 import org.collectionspace.services.config.service.ListResultField;
72 import org.collectionspace.services.config.service.ServiceBindingType;
73 import org.collectionspace.services.config.service.ServiceObjectType;
74 import org.collectionspace.services.servicegroup.ServicegroupsCommon;
75 import org.collectionspace.services.common.vocabulary.AuthorityResource;
76 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
77 import org.nuxeo.ecm.core.api.DocumentModel;
78 import org.nuxeo.ecm.core.api.DocumentModelList;
79 import org.nuxeo.ecm.core.api.PropertyException;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
82
83 public class ServiceGroupDocumentModelHandler 
84         extends NuxeoDocumentModelHandler<ServicegroupsCommon> {
85         
86     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
87     
88     protected static final int NUM_META_FIELDS = 4; // the number of meta fields -i.e., DOC_TYPE_FIELD, DOC_NUMBER_FIELD, DOC_NAME_FIELD, STANDARD_LIST_MARK_RT_FIELD
89     protected static final String DOC_TYPE_FIELD = "docType";
90     protected static final String DOC_NUMBER_FIELD = "docNumber";
91     protected static final String DOC_NAME_FIELD = "docName";
92         protected static final String STANDARD_LIST_MARK_RT_FIELD = "related";
93     
94     //
95     // Returns a service payload for an authority item
96     //
97     private PoxPayloadOut getAuthorityItem(ServiceContext ctx, String termRefName) throws Exception {
98         PoxPayloadOut result = null;
99         
100         RefName.AuthorityItem item = RefName.AuthorityItem.parse(termRefName, true);
101         AuthorityResource authorityResource = (AuthorityResource) ctx.getResourceMap().get(item.inAuthority.resource);
102         
103         AuthorityTermInfo authorityTermInfo = RefNameUtils.parseAuthorityTermInfo(termRefName);
104         String parentIdentifier = Specifier.createShortIdURNValue(authorityTermInfo.inAuthority.name);
105         String itemIdentifier = Specifier.createShortIdURNValue(authorityTermInfo.name);
106         
107         result = authorityResource.getAuthorityItemWithExistingContext(ctx, parentIdentifier, itemIdentifier);
108         
109         return result;
110     }
111
112     public PoxPayloadOut getResourceItemForCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
113                 List<String> serviceGroupNames,
114                 String csid) throws DocumentException {
115         PoxPayloadOut result = null;
116         CoreSessionInterface repoSession = null;
117         boolean releaseRepoSession = false;
118         
119         try { 
120                 NuxeoRepositoryClientImpl repoClient = (NuxeoRepositoryClientImpl)this.getRepositoryClient(ctx);
121                 repoSession = this.getRepositorySession();
122                 if (repoSession == null) {
123                         repoSession = repoClient.getRepositorySession(ctx);
124                         releaseRepoSession = true;
125                 }
126                 try {
127                 Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();
128                 DocumentModelList docList = this.getDocListForGroup(ctx, serviceGroupNames, queriedServiceBindings,
129                                 repoSession, repoClient);
130                 if (docList == null || docList.isEmpty()) { // found no authRef fields - nothing to process
131                     throw new DocumentNotFoundException();
132                 }
133                 DocumentModel docModel = docList.get(0);
134                 //
135                 // Determine if the docModel is an authority term, object, or some other procedure record.
136                 //
137                 String termRefName = (String) NuxeoUtils.getProperyValue(docModel, CollectionSpaceClient.COLLECTIONSPACE_CORE_REFNAME);
138                 if (isAuthorityTermDocument(termRefName) == true) {
139                         result = getAuthorityItem(ctx, termRefName);
140                 } else {                
141                         TenantBindingConfigReaderImpl bindingReader = ServiceMain.getInstance().getTenantBindingConfigReader();
142                         String serviceName = ServiceBindingUtils.getServiceNameFromObjectName(bindingReader, ctx.getTenantId(),
143                                         docModel.getDocumentType().getName());
144                         NuxeoBasedResource resource = (NuxeoBasedResource) ctx.getResourceMap().get(serviceName);
145                         result = resource.getWithParentCtx(ctx, csid);
146                 }
147                 } catch (DocumentException de) {
148                         throw de;
149                 } catch (Exception e) {
150                         if (logger.isDebugEnabled()) {
151                                 logger.debug("Caught exception ", e);
152                         }
153                         throw new DocumentException(e);
154                 } finally {
155                         if (releaseRepoSession && repoSession != null) {
156                                 repoClient.releaseRepositorySession(ctx, repoSession);
157                         }
158                 }
159         } catch (Exception e) {
160                 if (logger.isDebugEnabled()) {
161                         logger.debug("Caught exception ", e);
162                 }
163                 throw new DocumentException(e);
164         }
165         
166         return result;
167     }
168     
169     private boolean isAuthorityTermDocument(String termRefName) {
170                 boolean result = true;
171                 
172                 try {
173                 //String inAuthorityCsid = (String) NuxeoUtils.getProperyValue(docModel, "inAuthority"); //docModel.getPropertyValue("inAuthority"); // AuthorityItemJAXBSchema.IN_AUTHORITY
174                 //String refName = (String) NuxeoUtils.getProperyValue(docModel, CollectionSpaceClient.COLLECTIONSPACE_CORE_REFNAME);
175                 RefName.AuthorityItem item = RefName.AuthorityItem.parse(termRefName, true);
176                 } catch (IllegalArgumentException e) {
177                         result = false;
178                 }
179                 
180         return result;
181         }
182
183         private DocumentModelList getDocListForGroup(
184                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
185                 List<String> serviceGroupNames,
186                 Map<String, ServiceBindingType> queriedServiceBindings,
187                 CoreSessionInterface repoSession,
188                 NuxeoRepositoryClientImpl repoClient) throws Exception {
189         
190         NuxeoRepositoryClientImpl nuxeoRepoClient = (NuxeoRepositoryClientImpl)repoClient;
191         // Get the service bindings for this tenant
192         TenantBindingConfigReaderImpl tReader = ServiceMain.getInstance().getTenantBindingConfigReader();
193         // We need to get all the procedures, authorities, and objects.
194         List<ServiceBindingType> servicebindings = 
195                         tReader.getServiceBindingsByType(ctx.getTenantId(), serviceGroupNames);
196         if (servicebindings == null || servicebindings.isEmpty()) {
197             Response response = Response.status(Response.Status.NOT_FOUND).entity(
198                     ServiceMessages.READ_FAILED + 
199                     ServiceMessages.resourceNotFoundMsg(implode(serviceGroupNames, ","))).type("text/plain").build();
200             throw new CSWebApplicationException(response);
201         }
202         
203         servicebindings = SecurityUtils.getReadableServiceBindingsForCurrentUser(servicebindings);
204         // Build the list of docTypes for allowed serviceBindings
205         ArrayList<String> docTypes = new ArrayList<String>();
206         for(ServiceBindingType binding:servicebindings) {
207                 ServiceObjectType serviceObj = binding.getObject();
208                 if(serviceObj!=null) {
209                 String docType = serviceObj.getName();
210                         docTypes.add(docType);
211                 queriedServiceBindings.put(docType, binding);
212                 }
213         }
214         
215         // This should be type "Document" but CMIS is gagging on that right now.
216         ctx.getQueryParams().add(IQueryManager.SELECT_DOC_TYPE_FIELD, QueryManagerNuxeoImpl.COLLECTIONSPACE_DOCUMENT_TYPE);
217         
218         // Now we have to issue the search
219         // The findDocs() method will build a QueryContext, which wants to see a docType for our context
220         ctx.setDocumentType(QueryManagerNuxeoImpl.NUXEO_DOCUMENT_TYPE);
221         DocumentWrapper<DocumentModelList> docListWrapper = 
222                         nuxeoRepoClient.findDocs(ctx, this, repoSession, docTypes );
223         // Now we gather the info for each document into the list and return
224         DocumentModelList docList = docListWrapper.getWrappedObject();
225         
226         return docList;
227     }
228     
229     public AbstractCommonList getItemListForGroup(
230                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
231                 List<String> serviceGroupNames) throws Exception {
232         CommonList commonList = new CommonList();
233         AbstractCommonList list = (AbstractCommonList)commonList;
234         CoreSessionInterface repoSession = null;
235         boolean releaseRepoSession = false;
236         
237         try { 
238             DocumentFilter myFilter = getDocumentFilter();
239                 int pageSize = myFilter.getPageSize();
240                 int pageNum = myFilter.getStartPage();
241                 list.setPageNum(pageNum);
242                 list.setPageSize(pageSize);
243
244                 NuxeoRepositoryClientImpl repoClient = (NuxeoRepositoryClientImpl)this.getRepositoryClient(ctx);
245                 repoSession = this.getRepositorySession();
246                 if (repoSession == null) {
247                         repoSession = repoClient.getRepositorySession(ctx);
248                         releaseRepoSession = true;
249                 }
250                 try {
251                 Map<String, ServiceBindingType> queriedServiceBindings = new HashMap<String, ServiceBindingType>();
252                 DocumentModelList docList = this.getDocListForGroup(ctx, serviceGroupNames, queriedServiceBindings,
253                                 repoSession, repoClient);
254                 if (docList == null) { // found no authRef fields - nothing to process
255                     return list;
256                 }
257                 processDocList(ctx, docList, queriedServiceBindings, commonList);
258                 list.setItemsInPage(docList.size());
259                 list.setTotalItems(docList.totalSize());
260                 } catch (DocumentException de) {
261                         throw de;
262                 } catch (Exception e) {
263                         if (logger.isDebugEnabled()) {
264                                 logger.debug("Caught exception ", e);
265                         }
266                         throw new DocumentException(e);
267                 } finally {
268                         if (releaseRepoSession && repoSession != null) {
269                                 repoClient.releaseRepositorySession(ctx, repoSession);
270                         }
271                 }
272         } catch (Exception e) {
273                 if (logger.isDebugEnabled()) {
274                         logger.debug("Caught exception ", e);
275                 }
276                 throw new DocumentException(e);
277         }
278         
279         return list;
280     }
281     
282     // Move this to a Utils class!
283     public static String implode(List<String> stringList, String sep) {
284         StringBuilder sb = new StringBuilder();
285         
286         boolean fFirst = false;
287         for (String name:stringList) {
288                 if(fFirst) {
289                         fFirst = false;
290                 } else {
291                         sb.append(sep);
292                 }
293                 sb.append(name);
294         }
295         
296         return sb.toString();
297     }
298     
299     private String getUriFromServiceBinding(ServiceBindingType sb, String csid) {
300         return "/" + sb.getName().toLowerCase() + "/" + csid;
301     }
302     
303     private void processDocList(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
304                         DocumentModelList docList,
305                         Map<String, ServiceBindingType> queriedServiceBindings,
306                         CommonList list) throws DocumentException {
307         
308                 String tenantId = ctx.getTenantId();
309                 CoreSessionInterface repoSession = null;
310                 NuxeoRepositoryClientImpl repoClient = null;
311                 boolean releaseRepoSession = false;
312                 
313                 MultivaluedMap<String, String> queryParams = getServiceContext().getQueryParams();
314                 String markRtSbj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT);
315                 if (Tools.isBlank(markRtSbj)) {
316                         markRtSbj = null;
317                 }
318                 
319                 String markRtSbjOrObj = queryParams.getFirst(IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER);
320                 if (Tools.isBlank(markRtSbjOrObj)) {
321                         markRtSbjOrObj = null;
322                 } else {
323                         if (Tools.isBlank(markRtSbj) == false) {
324                                 logger.warn(String.format("Ignoring query param %s='%s' since overriding query param %s='%s' exists.",
325                                                 IQueryManager.MARK_RELATED_TO_CSID_AS_SUBJECT, markRtSbj, IQueryManager.MARK_RELATED_TO_CSID_AS_EITHER, markRtSbjOrObj));
326                         }
327                         markRtSbj = markRtSbjOrObj; // Mark the record as related independent of whether it is the subject or object of a relationship
328                 }
329                 
330                 try {
331                         if (markRtSbj != null) {
332                                 repoClient = (NuxeoRepositoryClientImpl) this.getRepositoryClient(ctx);
333                                 NuxeoRepositoryClientImpl nuxeoRepoClient = (NuxeoRepositoryClientImpl) repoClient;
334                                 repoSession = this.getRepositorySession();
335                                 if (repoSession == null) {
336                                         repoSession = repoClient.getRepositorySession(ctx);
337                                         releaseRepoSession = true;
338                                 }
339                         }
340                                         
341                 String fields[] = new String[NUM_META_FIELDS + NUM_STANDARD_LIST_RESULT_FIELDS];
342                 fields[0] = STANDARD_LIST_CSID_FIELD;
343                 fields[1] = STANDARD_LIST_URI_FIELD;
344                 fields[2] = STANDARD_LIST_UPDATED_AT_FIELD;
345                 fields[3] = STANDARD_LIST_WORKFLOW_FIELD;
346                 fields[4] = STANDARD_LIST_REFNAME_FIELD;
347                 fields[5] = DOC_NAME_FIELD;
348                 fields[6] = DOC_NUMBER_FIELD;
349                 fields[7] = DOC_TYPE_FIELD;             
350                         if (markRtSbj != null) {
351                         fields[8] = STANDARD_LIST_MARK_RT_FIELD;
352                         }
353
354                 list.setFieldsReturned(fields);
355                 
356                 Iterator<DocumentModel> iter = docList.iterator();
357                         HashMap<String, Object> item = new HashMap<String, Object>();
358                 while (iter.hasNext()) {
359                     DocumentModel docModel = iter.next();
360                     String docType = docModel.getDocumentType().getName();
361                     docType = ServiceBindingUtils.getUnqualifiedTenantDocType(docType);
362                     ServiceBindingType sb = queriedServiceBindings.get(docType);
363                     if (sb == null) {
364                         throw new RuntimeException("processDocList: No Service Binding for docType: " + docType);
365                     }
366                     
367                     String csid = NuxeoUtils.getCsid(docModel);
368                     item.put(STANDARD_LIST_CSID_FIELD, csid);
369
370                                 //
371                                 // If the mark-related query param was set, check to see if the doc we're processing
372                                 // is related to the value specified in the mark-related query param.
373                                 //                  
374                                 if (markRtSbj != null) {
375                                         String relationClause = RelationsUtils.buildWhereClause(markRtSbj, null, null, csid, null, markRtSbj == markRtSbjOrObj);
376                                         String whereClause = relationClause + IQueryManager.SEARCH_QUALIFIER_AND
377                                                         + NuxeoUtils.buildWorkflowNotDeletedWhereClause();
378                                         QueryContext queryContext = new QueryContext(ctx, whereClause);
379                                         queryContext.setDocType(IRelationsManager.DOC_TYPE);
380                                         String query = NuxeoUtils.buildNXQLQuery(queryContext);
381                                         // Search for 1 relation that matches. 1 is enough to fail
382                                         // the filter
383                                         DocumentModelList queryDocList = repoSession.query(query, null, 1, 0, false);
384                                         item.put(STANDARD_LIST_MARK_RT_FIELD, queryDocList.isEmpty() ? "false" : "true");
385                                 }
386
387                     UriTemplateRegistry uriTemplateRegistry = ServiceMain.getInstance().getUriTemplateRegistry();            
388                     StoredValuesUriTemplate storedValuesResourceTemplate = uriTemplateRegistry.get(new UriTemplateRegistryKey(tenantId, docType));
389                             Map<String, String> additionalValues = new HashMap<String, String>();
390                             if (storedValuesResourceTemplate.getUriTemplateType() == UriTemplateFactory.ITEM) {
391                         try {
392                             String inAuthorityCsid = (String) NuxeoUtils.getProperyValue(docModel, "inAuthority"); //docModel.getPropertyValue("inAuthority"); // AuthorityItemJAXBSchema.IN_AUTHORITY
393                             additionalValues.put(UriTemplateFactory.IDENTIFIER_VAR, inAuthorityCsid);
394                             additionalValues.put(UriTemplateFactory.ITEM_IDENTIFIER_VAR, csid);
395                         } catch (Exception e) {
396                                 String msg = String.format("Could not extract inAuthority property from authority item with CSID = ", docModel.getName());
397                             logger.warn(msg, e);
398                         }
399                             } else {
400                         additionalValues.put(UriTemplateFactory.IDENTIFIER_VAR, csid);
401                     }
402                             
403                     String uriStr = storedValuesResourceTemplate.buildUri(additionalValues);
404                     item.put(STANDARD_LIST_URI_FIELD, uriStr);
405                     try {
406                         item.put(STANDARD_LIST_UPDATED_AT_FIELD, getUpdatedAtAsString(docModel));
407                         item.put(STANDARD_LIST_WORKFLOW_FIELD, docModel.getCurrentLifeCycleState());
408                         item.put(STANDARD_LIST_REFNAME_FIELD, getRefname(docModel));
409                     } catch(Exception e) {
410                         logger.error("Error getting core values for doc ["+csid+"]: "+e.getLocalizedMessage());
411                     }
412         
413                     String value = ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NUMBER_PROP, docModel);
414                     if (value != null) {
415                         item.put(DOC_NUMBER_FIELD, value);
416                     }
417                     
418                     value = ServiceBindingUtils.getMappedFieldInDoc(sb, ServiceBindingUtils.OBJ_NAME_PROP, docModel);
419                     if (value != null) {
420                         item.put(DOC_NAME_FIELD, value);
421                     }
422                     
423                     item.put(DOC_TYPE_FIELD, docType);
424                     // add the item to the list
425                     list.addItem(item);
426                     item.clear();
427                 }
428             } catch (Exception e) {
429                         if (logger.isDebugEnabled()) {
430                                 logger.debug("Caught exception ", e);
431                         }
432                         throw new DocumentException(e);
433                 } finally {
434                         // If we got/acquired a new session then we're responsible for releasing it.
435                         if (releaseRepoSession && repoSession != null) {
436                                 repoClient.releaseRepositorySession(ctx, repoSession);
437                         }
438                 }
439     }
440 }
441