]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
0e988e172b4e82083125dcd6a47b713f915c1167
[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.relation.nuxeo;
25
26 import java.util.Iterator;
27
28 import org.collectionspace.services.client.PoxPayloadIn;
29 import org.collectionspace.services.client.PoxPayloadOut;
30 import org.collectionspace.services.common.ServiceMain;
31 import org.collectionspace.services.common.api.Tools;
32 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
33 import org.collectionspace.services.common.context.ServiceBindingUtils;
34 import org.collectionspace.services.common.document.InvalidDocumentException;
35 import org.collectionspace.services.common.relation.RelationJAXBSchema;
36 import org.collectionspace.services.common.relation.nuxeo.RelationConstants;
37 import org.collectionspace.services.common.context.ServiceContext;
38 import org.collectionspace.services.common.repository.RepositoryClient;
39 import org.collectionspace.services.common.repository.RepositoryClientFactory;
40 import org.collectionspace.services.common.service.ServiceBindingType;
41 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
42 import org.collectionspace.services.relation.RelationsCommon;
43 import org.collectionspace.services.relation.RelationsCommonList;
44 import org.collectionspace.services.relation.RelationsCommonList.RelationListItem;
45
46 import org.collectionspace.services.common.document.DocumentWrapper;
47 import org.collectionspace.services.jaxb.AbstractCommonList;
48 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
49 import org.collectionspace.services.relation.RelationsDocListItem;
50 import org.nuxeo.ecm.core.api.DocumentModel;
51 import org.nuxeo.ecm.core.api.DocumentModelList;
52 import org.nuxeo.ecm.core.api.model.PropertyException;
53 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 /**
58  * RelationDocumentModelHandler
59  *
60  * $LastChangedRevision: $
61  * $LastChangedDate: $
62  */
63 public class RelationDocumentModelHandler
64         extends RemoteDocumentModelHandlerImpl<RelationsCommon, RelationsCommonList> {
65
66     private final Logger logger = LoggerFactory.getLogger(RelationDocumentModelHandler.class);
67     /**
68      * relation is used to stash JAXB object to use when handle is called
69      * for Action.CREATE, Action.UPDATE or Action.GET
70      */
71     private RelationsCommon relation;
72     /**
73      * relationList is stashed when handle is called
74      * for ACTION.GET_ALL
75      */
76     private RelationsCommonList relationList;
77
78     @Override
79     public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
80
81         // Obtain document models for the subject and object of the relation.
82         DocumentModel relationDocModel = wrapDoc.getWrappedObject();
83         ServiceContext ctx = getServiceContext();
84         DocumentModel subjectDocModel = getSubjectDocModel(relationDocModel, ctx);
85         DocumentModel objectDocModel = getObjectDocModel(relationDocModel, ctx);
86
87         // Use values from the subject and object document models to populate the
88         // relevant fields of the relation's own document model.
89         if (subjectDocModel != null) {
90             relationDocModel = populateSubjectValues(relationDocModel, subjectDocModel);
91         }
92         if (objectDocModel != null) {
93             relationDocModel = populateObjectValues(relationDocModel, objectDocModel);
94         }
95
96         // FIXME: Verify the following:
97         // Do we call this method here, only after we've updated the relationDocModel?
98         // Has the wrapDoc instance itself been updated, in the process of updating the relationDocModel,
99         // or do we need to pass the updated relationDocModel back into that instance?
100         super.handleCreate(wrapDoc);
101
102     }
103
104     @Override
105     public void handleUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
106         super.handleUpdate(wrapDoc);
107     }
108
109     @Override
110     public RelationsCommon getCommonPart() {
111         return relation;
112     }
113
114     @Override
115     public void setCommonPart(RelationsCommon theRelation) {
116         this.relation = theRelation;
117     }
118
119     /**get associated Relation (for index/GET_ALL)
120      */
121     @Override
122     public RelationsCommonList getCommonPartList() {
123         return relationList;
124     }
125
126     @Override
127     public void setCommonPartList(RelationsCommonList theRelationList) {
128         this.relationList = theRelationList;
129     }
130
131     @Override
132     public RelationsCommon extractCommonPart(DocumentWrapper<DocumentModel> wrapDoc)
133             throws Exception {
134         throw new UnsupportedOperationException();
135     }
136
137     @Override
138     public void fillCommonPart(RelationsCommon theRelation, DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
139         throw new UnsupportedOperationException();
140     }
141
142     @Override
143     public RelationsCommonList extractCommonPartList(DocumentWrapper<DocumentModelList> wrapDoc) throws Exception {
144         RelationsCommonList relList = this.extractPagingInfo(new RelationsCommonList(), wrapDoc);
145         relList.setFieldsReturned("subjectCsid|relationshipType|predicateDisplayName|objectCsid|uri|csid|subject|object");
146         ServiceContext ctx = getServiceContext();
147         String serviceContextPath = getServiceContextPath();
148
149         TenantBindingConfigReaderImpl tReader = ServiceMain.getInstance().getTenantBindingConfigReader();
150         String serviceName = getServiceContext().getServiceName().toLowerCase();
151         ServiceBindingType sbt = tReader.getServiceBinding(ctx.getTenantId(), serviceName);
152
153         Iterator<DocumentModel> iter = wrapDoc.getWrappedObject().iterator();
154         while (iter.hasNext()) {
155             DocumentModel docModel = iter.next();
156             RelationListItem relListItem = getRelationListItem(ctx, sbt, tReader, docModel, serviceContextPath);
157             relList.getRelationListItem().add(relListItem);
158         }
159         return relList;
160     }
161
162     /** Gets the relation list item, looking up the subject and object documents, and getting summary
163      *  info via the objectName and objectNumber properties in tenant-bindings.
164      * @param ctx the ctx
165      * @param sbt the ServiceBindingType of Relations service
166      * @param tReader the tenant-bindings reader, for looking up docnumber and docname
167      * @param docModel the doc model
168      * @param serviceContextPath the service context path
169      * @return the relation list item, with nested subject and object summary info.
170      * @throws Exception the exception
171      */
172     private RelationListItem getRelationListItem(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
173             ServiceBindingType sbt,
174             TenantBindingConfigReaderImpl tReader,
175             DocumentModel docModel,
176             String serviceContextPath) throws Exception {
177         RelationListItem relationListItem = new RelationListItem();
178         String id = getCsid(docModel);
179         relationListItem.setCsid(id);
180
181         relationListItem.setSubjectCsid((String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_ID_1));
182
183         String predicate = (String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.RELATIONSHIP_TYPE);
184         relationListItem.setRelationshipType(predicate);
185         relationListItem.setPredicate(predicate); //predicate is new name for relationshipType.
186         relationListItem.setPredicateDisplayName((String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.RELATIONSHIP_TYPE_DISPLAYNAME));
187
188         relationListItem.setObjectCsid((String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_ID_2));
189
190         relationListItem.setUri(serviceContextPath + id);
191
192         //Now fill in summary info for the related docs: subject and object.
193         String subjectCsid = relationListItem.getSubjectCsid();
194         String documentType = (String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_TYPE_1);
195         RelationsDocListItem subject = createRelationsDocListItem(ctx, sbt, subjectCsid, tReader, documentType);
196
197         //Object o1 =  docModel.getProperty(ctx.getCommonPartLabel(), "subject");
198         //Object o2 =  docModel.getProperty(ctx.getCommonPartLabel(), "object");
199
200         String subjectUri = (String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.SUBJECT_URI);
201         subject.setUri(subjectUri);
202         relationListItem.setSubject(subject);
203
204         String objectCsid = relationListItem.getObjectCsid();
205         String documentType2 = (String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_TYPE_2);
206         RelationsDocListItem object = createRelationsDocListItem(ctx, sbt, objectCsid, tReader, documentType2);
207
208         String objectUri = (String) docModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.OBJECT_URI);
209         object.setUri(objectUri);
210         relationListItem.setObject(object);
211
212         return relationListItem;
213     }
214
215     // DocumentModel itemDocModel = docModelFromCSID(ctx, itemCsid);
216     protected RelationsDocListItem createRelationsDocListItem(ServiceContext ctx,
217             ServiceBindingType sbt,
218             String itemCsid,
219             TenantBindingConfigReaderImpl tReader,
220             String documentType) throws Exception {
221         RelationsDocListItem item = new RelationsDocListItem();
222         item.setDocumentType(documentType);//this one comes from the record, as documentType1, documentType2.
223         // CSPACE-4037 REMOVING: item.setService(documentType);//this one comes from the record, as documentType1, documentType2.   Current app seems to use servicename for this.
224         item.setCsid(itemCsid);
225
226         DocumentModel itemDocModel = NuxeoUtils.getDocFromCsid(getRepositorySession(), ctx, itemCsid);    //null if not found.
227         if (itemDocModel != null) {
228             String itemDocType = itemDocModel.getDocumentType().getName();
229             // CSPACE-4037 REMOVING: item.setDocumentTypeFromModel(itemDocType);           //this one comes from the nuxeo documentType
230
231             //DEBUG: System.out.println("\r\n******** AuthorityItemDocumentModelHandlder documentType **************\r\n\tdocModel: "+itemDocType+"\r\n\tpayload: "+documentType);
232             //boolean usedDocumentTypeFromPayload = true;
233             /*if ( ! Tools.isBlank(documentType)){
234             if (documentType.equals(itemDocType)){
235             //usedDocumentTypeFromPayload = true;
236             }  else {
237             // Laramie20110510 CSPACE-3739  throw the exception for 3739, otherwise, don't throw it.
238             //throw new Exception("documentType supplied was wrong.  supplied: "+documentType+" required: "+itemDocType+ " itemCsid: "+itemCsid );
239             }
240             } else {
241             //usedDocumentTypeFromPayload = false;
242             item.setDocumentType(itemDocType);
243             }   */
244             if (Tools.isBlank(documentType)) {
245                 item.setDocumentType(itemDocType);
246             }
247
248             // TODO: clean all the output statements out of here when CSPACE-4037 is done.
249             //TODO: ensure that itemDocType is really the entry point, i.e. servicename==doctype
250             //ServiceBindingType itemSbt2 = tReader.getServiceBinding(ctx.getTenantId(), itemDocType);
251             String propName = "ERROR-FINDING-PROP-VALUE";
252             ServiceBindingType itemSbt = tReader.getServiceBindingForDocType(ctx.getTenantId(), itemDocType);
253             try {
254                 propName = ServiceBindingUtils.getPropertyValue(itemSbt, ServiceBindingUtils.OBJ_NAME_PROP);
255                 String itemDocname = ServiceBindingUtils.getMappedFieldInDoc(itemSbt, ServiceBindingUtils.OBJ_NAME_PROP, itemDocModel);
256                 if (propName == null || itemDocname == null) {
257                     //System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType);
258                 } else {
259                     item.setName(itemDocname);
260                     //System.out.println("=== found prop : "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType);
261                 }
262             } catch (Throwable t) {
263                 System.out.println("====Error finding objectNameProperty: " + itemDocModel + " field " + ServiceBindingUtils.OBJ_NAME_PROP + "=" + propName
264                         + " not found in itemDocType: " + itemDocType + " inner: " + t.getMessage());
265             }
266             propName = "ERROR-FINDING-PROP-VALUE";
267             try {
268                 propName = ServiceBindingUtils.getPropertyValue(itemSbt, ServiceBindingUtils.OBJ_NUMBER_PROP);
269                 String itemDocnumber = ServiceBindingUtils.getMappedFieldInDoc(itemSbt, ServiceBindingUtils.OBJ_NUMBER_PROP, itemDocModel);
270
271                 if (propName == null || itemDocnumber == null) {
272                     //System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber
273                     //                          +" documentType: "+documentType);
274                 } else {
275                     item.setNumber(itemDocnumber);
276                     //System.out.println("============ found prop : "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber
277                     //                          +" documentType: "+documentType);
278                 }
279             } catch (Throwable t) {
280                 logger.error("====Error finding objectNumberProperty: " + ServiceBindingUtils.OBJ_NUMBER_PROP + "=" + propName
281                         + " not found in itemDocType: " + itemDocType + " inner: " + t.getMessage());
282             }
283         } else {
284             item.setError("INVALID: related object is absent");
285             // Laramie20110510 CSPACE-3739  throw the exception for 3739, otherwise, don't throw it.
286             //throw new Exception("INVALID: related object is absent "+itemCsid);
287         }
288         return item;
289     }
290
291     @Override
292     public String getQProperty(String prop) {
293         return "/" + RelationConstants.NUXEO_SCHEMA_ROOT_ELEMENT + "/" + prop;
294     }
295
296     /**
297      * Obtains the subject resource and uses its values to populate
298      * subject-related fields in the relation resource.
299      */
300     private DocumentModel getSubjectDocModel(DocumentModel relationDocModel, ServiceContext ctx) throws Exception {
301         // Get the document model for the subject of the relation.
302         DocumentModel subjectDocModel = null;
303         String subjectCsid = "";
304         String subjectRefName = "";
305         // FIXME: Currently assumes that the object CSID is valid if present
306         // in the incoming payload.
307         try {
308             subjectCsid = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.SUBJECT_CSID);
309             // FIXME: Remove this entire 'if' statement when legacy fields are removed from the Relation record:
310             if (Tools.isBlank(subjectCsid)) {
311                 subjectCsid = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_ID_1);
312             }
313         } catch (PropertyException pe) {
314             // Per CSPACE-4468, ignore any property exception here.
315             // (See parallel comment below in getObjectDocModel.)
316         }
317         if (Tools.notBlank(subjectCsid)) {
318             // FIXME: Call a utility routine here that uses the CSID to retrieve the subject record's docModel.
319             // The following is a placeholder:
320             subjectDocModel = getDocModelFromCsid(subjectCsid);
321         }
322         if (Tools.isBlank(subjectCsid)) {
323             try {
324                 subjectRefName = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.SUBJECT_REFNAME);
325                 // FIXME: Call a utility routine here - for which the method below is currently a
326                 // placeholder - that uses the refName to retrieve the subject record's docModel.
327                 subjectDocModel = getDocModelFromRefname(subjectRefName);
328             } catch (Exception e) {
329                 throw new InvalidDocumentException(
330                         "Relation record must contain a CSID or refName to identify the subject of the relation.", e);
331             }
332         }
333         return subjectDocModel;
334     }
335
336     /**
337      * Obtains the object resource and uses its values to populate
338      * object-related fields in the relation resource.
339      */
340     private DocumentModel getObjectDocModel(DocumentModel relationDocModel, ServiceContext ctx) throws Exception {
341         // Get the document model for the object of the relation.
342         String objectCsid = "";
343         String objectRefName = "";
344         DocumentModel objectDocModel = null;
345         // FIXME: Currently assumes that the object CSID is valid if present
346         // in the incoming payload.
347         try {
348             objectCsid = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.OBJECT_CSID);
349             // FIXME: Remove this entire 'if' statement when legacy fields are removed from the Relation record:
350             if (Tools.isBlank(objectCsid)) {
351                 objectCsid = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.DOCUMENT_ID_2);
352             }
353         } catch (PropertyException pe) {
354             // Per CSPACE-4468, ignore any property exception here.
355             // The objectCsid and/or subjectCsid field in a relation record
356             // can now be null (missing), because a refName value can be
357             // provided as an alternate identifier.
358         }
359         if (Tools.isBlank(objectCsid)) {
360             try {
361                 objectRefName = (String) relationDocModel.getProperty(ctx.getCommonPartLabel(), RelationJAXBSchema.OBJECT_REFNAME);
362                 // FIXME: Call a utility routine here - for which the method below is currently a
363                 // placeholder - that uses the refName to retrieve the object record's docModel.
364                 objectDocModel = getDocModelFromRefname(objectRefName);
365             } catch (Exception e) {
366                 throw new InvalidDocumentException(
367                         "Relation record must have a CSID or refName to identify the object of the relation.", e);
368             }
369         }
370         return objectDocModel;
371     }
372
373     // CSPACE-4468 placeholder methods:
374     
375     // FIXME: Placeholder method.
376     private DocumentModel getDocModelFromCsid(String csid) {
377         return null;
378     }
379
380     // FIXME: Placeholder method.
381     // Patrick is providing a working replacement for this method, in a framework class.
382     private DocumentModel getDocModelFromRefname(String csid) {
383         return null;
384     }
385
386     // FIXME: Placeholder method.
387     private DocumentModel populateSubjectValues(DocumentModel relationDocModel, DocumentModel objectDocModel) {
388         throw new UnsupportedOperationException("Not yet implemented");
389     }
390
391     // FIXME: Placeholder method.
392     private DocumentModel populateObjectValues(DocumentModel relationDocModel, DocumentModel objectDocModel) {
393         throw new UnsupportedOperationException("Not yet implemented");
394     }
395 }