]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
72fa04f48a6ee2a386ab87b4ab6617436057ba06
[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.nuxeo.client.java;
25
26 import java.util.Collection;
27 import java.util.List;
28
29 import javax.ws.rs.core.MultivaluedMap;
30
31 import org.collectionspace.services.client.IQueryManager;
32 import org.collectionspace.services.client.PoxPayloadIn;
33 import org.collectionspace.services.client.PoxPayloadOut;
34 import org.collectionspace.services.client.RelationClient;
35 import org.collectionspace.services.common.authorityref.AuthorityRefList;
36 import org.collectionspace.services.common.context.ServiceContext;
37 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
38 import org.collectionspace.services.common.document.AbstractMultipartDocumentHandlerImpl;
39 import org.collectionspace.services.common.document.DocumentFilter;
40 import org.collectionspace.services.common.document.DocumentWrapper;
41 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
42 import org.collectionspace.services.common.profile.Profiler;
43 import org.collectionspace.services.common.repository.RepositoryClient;
44 import org.collectionspace.services.common.repository.RepositoryClientFactory;
45 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
46 import org.collectionspace.services.lifecycle.Lifecycle;
47 import org.collectionspace.services.lifecycle.State;
48 import org.collectionspace.services.lifecycle.StateList;
49 import org.collectionspace.services.lifecycle.TransitionDef;
50 import org.collectionspace.services.lifecycle.TransitionDefList;
51 import org.collectionspace.services.lifecycle.TransitionList;
52
53 import org.nuxeo.ecm.core.NXCore;
54 import org.nuxeo.ecm.core.api.ClientException;
55 import org.nuxeo.ecm.core.api.DocumentModel;
56 import org.nuxeo.ecm.core.api.DocumentModelList;
57 import org.nuxeo.ecm.core.api.model.PropertyException;
58 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
59 import org.nuxeo.ecm.core.lifecycle.LifeCycleService;
60
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 /**
65  * DocumentModelHandler is a base abstract Nuxeo document handler
66  * using Nuxeo Java Remote APIs for CollectionSpace services
67  *
68  * $LastChangedRevision: $
69  * $LastChangedDate: $
70  */
71 public abstract class DocumentModelHandler<T, TL>
72         extends AbstractMultipartDocumentHandlerImpl<T, TL, DocumentModel, DocumentModelList> {
73
74     private final Logger logger = LoggerFactory.getLogger(DocumentModelHandler.class);
75     private RepositoryInstance repositorySession;
76     //key=schema, value=documentpart
77
78     public final static String COLLECTIONSPACE_CORE_SCHEMA = "collectionspace_core";
79     public final static String COLLECTIONSPACE_CORE_TENANTID = "tenantId";
80     public final static String COLLECTIONSPACE_CORE_URI = "uri";
81     public final static String COLLECTIONSPACE_CORE_CREATED_AT = "createdAt";
82     public final static String COLLECTIONSPACE_CORE_UPDATED_AT = "updatedAt";
83     public final static String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy";
84     public final static String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy";
85     public final static String COLLECTIONSPACE_CORE_WORKFLOWSTATE = "workflowState";
86
87     /*
88      * Map Nuxeo's life cycle object to our JAX-B based life cycle object
89      */
90     private Lifecycle createCollectionSpaceLifecycle(org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle) {
91         Lifecycle result = null;
92         
93         if (nuxeoLifecyle != null) {
94                 //
95                 // Copy the life cycle's name
96                 result = new Lifecycle();
97                 result.setName(nuxeoLifecyle.getName());
98                 
99                 // We currently support only one initial state, so take the first one from Nuxeo
100                 Collection<String> initialStateNames = nuxeoLifecyle.getInitialStateNames();
101                 result.setDefaultInitial(initialStateNames.iterator().next());
102                 
103                 // Next, we copy the state and corresponding transition lists
104                 StateList stateList = new StateList();
105                 List<State> states = stateList.getState();
106                 Collection<org.nuxeo.ecm.core.lifecycle.LifeCycleState> nuxeoStates = nuxeoLifecyle.getStates();
107                 for (org.nuxeo.ecm.core.lifecycle.LifeCycleState nuxeoState : nuxeoStates) {
108                         State tempState = new State();
109                         tempState.setDescription(nuxeoState.getDescription());
110                         tempState.setInitial(nuxeoState.isInitial());
111                         tempState.setName(nuxeoState.getName());
112                         // Now get the list of transitions
113                         TransitionList transitionList = new TransitionList();
114                         List<String> transitions = transitionList.getTransition();
115                         Collection<String> nuxeoTransitions = nuxeoState.getAllowedStateTransitions();
116                         for (String nuxeoTransition : nuxeoTransitions) {
117                                 transitions.add(nuxeoTransition);
118                         }
119                         tempState.setTransitionList(transitionList);
120                         states.add(tempState);
121                 }
122                 result.setStateList(stateList);
123                 
124                 // Finally, we create the transition definitions
125                 TransitionDefList transitionDefList = new TransitionDefList();
126                 List<TransitionDef> transitionDefs = transitionDefList.getTransitionDef();
127                 Collection<org.nuxeo.ecm.core.lifecycle.LifeCycleTransition> nuxeoTransitionDefs = nuxeoLifecyle.getTransitions();
128                 for (org.nuxeo.ecm.core.lifecycle.LifeCycleTransition nuxeoTransitionDef : nuxeoTransitionDefs) {
129                         TransitionDef tempTransitionDef = new TransitionDef();
130                         tempTransitionDef.setDescription(nuxeoTransitionDef.getDescription());
131                         tempTransitionDef.setDestinationState(nuxeoTransitionDef.getDestinationStateName());
132                         tempTransitionDef.setName(nuxeoTransitionDef.getName());
133                         transitionDefs.add(tempTransitionDef);
134                 }
135                 result.setTransitionDefList(transitionDefList);
136         }
137         
138         return result;
139     }
140     
141     /*
142      * Returns the the life cycle definition of the related Nuxeo document type for this handler.
143      * (non-Javadoc)
144      * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle()
145      */
146     @Override
147     public Lifecycle getLifecycle() {
148         Lifecycle result = null;
149         
150         String docTypeName = null;
151         try {
152                 docTypeName = this.getServiceContext().getDocumentType();
153                 result = getLifecycle(docTypeName);
154         } catch (Exception e) {
155                 if (logger.isTraceEnabled() == true) {
156                         logger.trace("Could not retrieve lifecycle definition for Nuxeo doctype: " + docTypeName);
157                 }
158         }
159         
160         return result;
161     }
162     
163     /*
164      * Returns the the life cycle definition of the related Nuxeo document type for this handler.
165      * (non-Javadoc)
166      * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle(java.lang.String)
167      */
168     @Override
169     public Lifecycle getLifecycle(String docTypeName) {
170         org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle;
171         Lifecycle result = null;
172         
173         try {
174                 LifeCycleService lifeCycleService = null;
175                         try {
176                                 lifeCycleService = NXCore.getLifeCycleService();
177                         } catch (Exception e) {
178                                 e.printStackTrace();
179                         }
180                         
181                 String lifeCycleName; 
182                 lifeCycleName = lifeCycleService.getLifeCycleNameFor(docTypeName);
183                 nuxeoLifecyle = lifeCycleService.getLifeCycleByName(lifeCycleName);
184                 
185                 result = createCollectionSpaceLifecycle(nuxeoLifecyle); 
186 //                      result = (Lifecycle)FileTools.getJaxbObjectFromFile(Lifecycle.class, "default-lifecycle.xml");
187                 } catch (Exception e) {
188                         // TODO Auto-generated catch block
189                         logger.error("Could not retreive life cycle information for Nuxeo doctype: " + docTypeName, e);
190                 }
191         
192         return result;
193     }
194     
195     /*
196      * We're using the "name" field of Nuxeo's DocumentModel to store
197      * the CSID.
198      */
199     public String getCsid(DocumentModel docModel) {
200         return NuxeoUtils.getCsid(docModel);
201     }
202
203     public String getUri(DocumentModel docModel) {
204         return getServiceContextPath()+getCsid(docModel);
205     }
206         
207     public RepositoryClient<PoxPayloadIn, PoxPayloadOut> getRepositoryClient(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx) {
208         RepositoryClient<PoxPayloadIn, PoxPayloadOut> repositoryClient = RepositoryClientFactory.getInstance().getClient(ctx.getRepositoryClientName());
209         return repositoryClient;
210     }
211
212     /**
213      * getRepositorySession returns Nuxeo Repository Session
214      * @return
215      */
216     public RepositoryInstance getRepositorySession() {
217         
218         return repositorySession;
219     }
220
221     /**
222      * setRepositorySession sets repository session
223      * @param repoSession
224      */
225     public void setRepositorySession(RepositoryInstance repoSession) {
226         this.repositorySession = repoSession;
227     }
228
229     @Override
230     public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
231         // TODO for sub-docs - check to see if the current service context is a multipart input, 
232         // OR a docfragment, and call a variant to fill the DocModel.
233         fillAllParts(wrapDoc, Action.CREATE);
234         handleCoreValues(wrapDoc, Action.CREATE);
235     }
236     
237     // TODO for sub-docs - Add completeCreate in which we look for set-aside doc fragments 
238     // and create the subitems. We will create service contexts with the doc fragments
239     // and then call 
240
241
242     @Override
243     public void handleUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
244         // TODO for sub-docs - check to see if the current service context is a multipart input, 
245         // OR a docfragment, and call a variant to fill the DocModel.
246         fillAllParts(wrapDoc, Action.UPDATE);
247         handleCoreValues(wrapDoc, Action.UPDATE);
248     }
249
250     @Override
251     public void handleGet(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
252         extractAllParts(wrapDoc);
253     }
254
255     @Override
256     public void handleGetAll(DocumentWrapper<DocumentModelList> wrapDoc) throws Exception {
257         Profiler profiler = new Profiler(this, 2);
258         profiler.start();
259         setCommonPartList(extractCommonPartList(wrapDoc));
260         profiler.stop();
261     }
262
263     @Override
264     public abstract void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception;
265
266     @Override
267     public abstract void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc) throws Exception;
268
269     @Override
270     public abstract T extractCommonPart(DocumentWrapper<DocumentModel> wrapDoc) throws Exception;
271
272     @Override
273     public abstract void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception;
274
275     @Override
276     public abstract void fillCommonPart(T obj, DocumentWrapper<DocumentModel> wrapDoc) throws Exception;
277
278     @Override
279     public abstract TL extractCommonPartList(DocumentWrapper<DocumentModelList> wrapDoc) throws Exception;
280
281     @Override
282     public abstract T getCommonPart();
283
284     @Override
285     public abstract void setCommonPart(T obj);
286
287     @Override
288     public abstract TL getCommonPartList();
289
290     @Override
291     public abstract void setCommonPartList(TL obj);
292     
293     @Override
294     public DocumentFilter createDocumentFilter() {
295         DocumentFilter filter = new NuxeoDocumentFilter(this.getServiceContext());
296         return filter;
297     }
298     
299     /**
300      * Gets the authority refs.
301      *
302      * @param docWrapper the doc wrapper
303      * @param authRefFields the auth ref fields
304      * @return the authority refs
305      * @throws PropertyException the property exception
306      */
307     abstract public AuthorityRefList getAuthorityRefs(String csid,
308                 List<AuthRefConfigInfo> authRefsInfo) throws PropertyException;    
309
310     private void handleCoreValues(DocumentWrapper<DocumentModel> docWrapper, 
311                 Action action)  throws ClientException {
312         DocumentModel documentModel = docWrapper.getWrappedObject();
313         String now = GregorianCalendarDateTimeUtils.timestampUTC();
314         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = getServiceContext();
315         String userId = ctx.getUserId();
316         if(action==Action.CREATE) {
317             //
318             // Add the tenant ID value to the new entity
319             //
320                 String tenantId = ctx.getTenantId();
321             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
322                     COLLECTIONSPACE_CORE_TENANTID, tenantId);
323             //
324             // Add the uri value to the new entity
325             //
326             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
327                     COLLECTIONSPACE_CORE_URI, getUri(documentModel));
328                 //
329                 // Add the CSID to the DublinCore title so we can see the CSID in the default
330                 // Nuxeo webapp.
331                 //
332                 try {
333                 documentModel.setProperty("dublincore", "title",
334                         documentModel.getName());
335                 } catch (Exception x) {
336                         if (logger.isWarnEnabled() == true) {
337                                 logger.warn("Could not set the Dublin Core 'title' field on document CSID:" +
338                                                 documentModel.getName());
339                         }
340                 }
341             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
342                     COLLECTIONSPACE_CORE_CREATED_AT, now);
343             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
344                     COLLECTIONSPACE_CORE_CREATED_BY, userId);
345         }
346         if(action==Action.CREATE || action==Action.UPDATE) {
347             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
348                     COLLECTIONSPACE_CORE_UPDATED_AT, now);
349             documentModel.setProperty(COLLECTIONSPACE_CORE_SCHEMA,
350                     COLLECTIONSPACE_CORE_UPDATED_BY, userId);
351         }
352     }
353     
354     /*
355      * If we see the "rtSbj" query param then we need to perform a CMIS query.  Currently, we have only one
356      * CMIS query, but we could add more.  If we do, this method should look at the incoming request and corresponding
357      * query params to determine if we need to do a CMIS query
358      * (non-Javadoc)
359      * @see org.collectionspace.services.common.document.AbstractDocumentHandlerImpl#isCMISQuery()
360      */
361     public boolean isCMISQuery() {
362         boolean result = false;
363         
364         MultivaluedMap<String, String> queryParams = getServiceContext().getQueryParams();
365         //
366         // Look the query params to see if we need to make a CMSIS query.
367         //
368         String subjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT);        
369         if (subjectCsid != null) {
370                 result = true;
371         }
372         
373         return result;
374     }
375     
376     /**
377      * Creates the CMIS query from the service context.  Each document handler is responsible for returning a valid CMIS query using the
378      * information in the current service context -which includes things like the query parameters, etc.
379      */
380     @Override
381     public String getCMISQuery() {
382         String result = null;
383         
384         if (isCMISQuery() == true) {
385                 MultivaluedMap<String, String> queryParams = getServiceContext().getQueryParams();
386                 String subjectCsid = (String)queryParams.getFirst(IQueryManager.SEARCH_RELATED_TO_CSID_SUBJECT);
387                 String docType = this.getServiceContext().getDocumentType();
388                 
389                 String selectFields = IQueryManager.CMIS_TARGET_NAME + ", "
390                                 + IQueryManager.CMIS_TARGET_TITLE + ", "
391                                 + RelationClient.CMIS_CSPACE_RELATIONS_TITLE + ", "
392                                 + RelationClient.CMIS_CSPACE_RELATIONS_SUBJECT_ID;
393                 String targetTable = docType + " " + IQueryManager.CMIS_TARGET_PREFIX;
394                 String relationTable = RelationClient.SERVICE_DOC_TYPE + " " + IQueryManager.CMIS_RELATIONS_PREFIX;
395                 String relationObjectCsid = RelationClient.CMIS_CSPACE_RELATIONS_OBJECT_ID;
396                 String relationSubjectCsid = RelationClient.CMIS_CSPACE_RELATIONS_SUBJECT_ID;
397                 String targetCsid = IQueryManager.CMIS_TARGET_CSID;
398                 
399                 result = "SELECT " + selectFields
400                                 + " FROM "      + targetTable + " JOIN " + relationTable
401                                 + " ON " + relationObjectCsid + " = " + targetCsid
402                                 + " WHERE " + relationSubjectCsid + " = " + "'" + subjectCsid + "'";
403                 
404                 // SELECT D.cmis:name, D.dc:title, R.dc:title, R.relations_common:subjectCsid
405                 // FROM Dimension D JOIN Relation R
406                 // ON R.relations_common:objectCsid = D.cmis:name
407                 // WHERE R.relations_common:subjectCsid = '737527ec-a560-4776-99de'
408                 
409                 if (logger.isDebugEnabled() == true && result != null) {
410                         logger.debug("The CMIS query for the Movement service is: " + result);
411                 }
412         }
413         
414         return result;
415     }
416     
417 }