]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
eb5a0511c3a40bde042a140ca5c2159190b41c81
[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.common.vocabulary.nuxeo;
25
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.ListIterator;
31 import java.util.Map;
32
33 import org.collectionspace.services.client.PayloadInputPart;
34 import org.collectionspace.services.client.PayloadOutputPart;
35 import org.collectionspace.services.client.PoxPayloadIn;
36 import org.collectionspace.services.client.PoxPayloadOut;
37 import org.collectionspace.services.client.RelationClient;
38 //import org.collectionspace.services.common.authority.AuthorityItemRelations;
39 import org.collectionspace.services.common.api.Tools;
40 import org.collectionspace.services.common.context.MultipartServiceContext;
41 import org.collectionspace.services.common.context.ServiceContext;
42 import org.collectionspace.services.common.document.DocumentWrapper;
43 import org.collectionspace.services.common.relation.IRelationsManager;
44 import org.collectionspace.services.common.service.ObjectPartType;
45 import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
46 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
47 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
48 import org.collectionspace.services.relation.RelationResource;
49 import org.collectionspace.services.relation.RelationsCommon;
50 import org.collectionspace.services.relation.RelationsCommonList;
51 import org.collectionspace.services.relation.RelationsDocListItem;
52 import org.collectionspace.services.relation.RelationshipType;
53 import org.nuxeo.ecm.core.api.DocumentModel;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 import javax.ws.rs.core.MultivaluedMap;
58 import javax.ws.rs.core.UriInfo;
59
60 /**
61  * AuthorityItemDocumentModelHandler
62  *
63  * $LastChangedRevision: $
64  * $LastChangedDate: $
65  */
66 public abstract class AuthorityItemDocumentModelHandler<AICommon, AICommonList>
67         extends RemoteDocumentModelHandlerImpl<AICommon, AICommonList> {
68
69     private final Logger logger = LoggerFactory.getLogger(AuthorityItemDocumentModelHandler.class);
70
71         private String authorityItemCommonSchemaName;
72         
73     //private final Logger logger = LoggerFactory.getLogger(AuthorityItemDocumentModelHandler.class);
74     /**
75      * item is used to stash JAXB object to use when handle is called
76      * for Action.CREATE, Action.UPDATE or Action.GET
77      */
78     protected AICommon item;
79     /**
80      * itemList is stashed when handle is called
81      * for ACTION.GET_ALL
82      */
83     protected AICommonList itemList;
84     
85     /**
86      * inVocabulary is the parent Authority for this context
87      */
88     protected String inAuthority;
89     
90     public AuthorityItemDocumentModelHandler(String authorityItemCommonSchemaName) {
91         this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
92     }
93
94     public String getInAuthority() {
95                 return inAuthority;
96         }
97
98         public void setInAuthority(String inAuthority) {
99                 this.inAuthority = inAuthority;
100         }
101
102     /* (non-Javadoc)
103      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#handleCreate(org.collectionspace.services.common.document.DocumentWrapper)
104      */
105     @Override
106     public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
107         // first fill all the parts of the document
108         super.handleCreate(wrapDoc);            
109         handleInAuthority(wrapDoc.getWrappedObject());
110     }
111     
112     /**
113      * Check the logic around the parent pointer. Note that we only need do this on
114      * create, since we have logic to make this read-only on update. 
115      * 
116      * @param docModel
117      * 
118      * @throws Exception the exception
119      */
120     private void handleInAuthority(DocumentModel docModel) throws Exception {
121         docModel.setProperty(authorityItemCommonSchemaName, 
122                         AuthorityItemJAXBSchema.IN_AUTHORITY, inAuthority);
123     }
124
125
126     /**
127      * getCommonPart get associated item
128      * @return
129      */
130     @Override
131     public AICommon getCommonPart() {
132         return item;
133     }
134
135     @Override
136     public void setCommonPart(AICommon item) {
137         this.item = item;
138     }
139
140     /**
141      * getCommonPartList get associated item (for index/GET_ALL)
142      * @return
143      */
144     @Override
145     public AICommonList getCommonPartList() {
146         return itemList;
147     }
148
149     @Override
150     public void setCommonPartList(AICommonList itemList) {
151         this.itemList = itemList;
152     }
153
154     @Override
155     public AICommon extractCommonPart(DocumentWrapper<DocumentModel> wrapDoc)
156             throws Exception {
157         throw new UnsupportedOperationException();
158     }
159
160     @Override
161     public void fillCommonPart(AICommon itemObject, DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
162         throw new UnsupportedOperationException();
163     }
164     
165     /* (non-Javadoc)
166      * @see org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl#extractPart(org.nuxeo.ecm.core.api.DocumentModel, java.lang.String, org.collectionspace.services.common.service.ObjectPartType)
167      */
168     @Override
169     protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
170             throws Exception {
171         Map<String, Object> unQObjectProperties = super.extractPart(docModel, schema, partMeta);
172         
173         // Add the CSID to the common part
174         if (partMeta.getLabel().equalsIgnoreCase(authorityItemCommonSchemaName)) {
175                 String csid = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
176                 unQObjectProperties.put("csid", csid);
177         }
178         
179         return unQObjectProperties;
180     }
181     
182     /**
183      * Filters out AuthorityItemJAXBSchema.IN_AUTHORITY, to ensure that
184      * the parent link remains untouched.
185      * @param objectProps the properties parsed from the update payload
186      * @param partMeta metadata for the object to fill
187      */
188     @Override
189     public void filterReadOnlyPropertiesForPart(
190                 Map<String, Object> objectProps, ObjectPartType partMeta) {
191         super.filterReadOnlyPropertiesForPart(objectProps, partMeta);
192         objectProps.remove(AuthorityItemJAXBSchema.IN_AUTHORITY);
193         objectProps.remove(AuthorityItemJAXBSchema.CSID);
194     }
195
196      @Override
197     public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
198             throws Exception {
199         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
200         super.extractAllParts(wrapDoc);
201
202         String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
203
204         //TODO: add broader, etc. here.
205         String predicate = RelationshipType.HAS_BROADER.value();
206         RelationsCommonList relationsCommonList = getRelations(thisCSID, null, predicate);
207         if (relationsCommonList.getTotalItems() == 0){
208             relationsCommonList = getRelations(null, thisCSID, predicate);   //for development... try switching subject and object.  This is not correct, though.
209         }
210         PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, relationsCommonList);
211         ctx.addOutputPart(relationsPart);
212     }
213
214     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
215         super.fillAllParts(wrapDoc, action);
216         ServiceContext ctx = getServiceContext();
217         PoxPayloadIn input = (PoxPayloadIn)ctx.getInput();
218         DocumentModel documentModel = (wrapDoc.getWrappedObject());
219         String itemCsid = documentModel.getName();
220
221         //TODO: create all relations....  UPDATE and CREATE will call.   Updates AuthorityItem part
222         RelationsCommonList relationsCommonList = updateRelations(itemCsid, input);
223         PayloadOutputPart payloadOutputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, relationsCommonList);
224         ctx.setProperty(RelationClient.SERVICE_COMMON_LIST_NAME, payloadOutputPart);
225     }
226
227     public void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
228         super.completeUpdate(wrapDoc);
229         //now we add part for relations list
230         ServiceContext ctx = getServiceContext();
231         PayloadOutputPart foo = (PayloadOutputPart)ctx.getProperty(RelationClient.SERVICE_COMMON_LIST_NAME);
232         ((PoxPayloadOut)ctx.getOutput()).addPart(foo);
233     }
234
235     //===================================================================
236     /*
237         for (RelationsCommonList.RelationListItem parentListItem : parentList.getRelationListItem()) {
238             System.out.println("    parentListItems " + parentListItem);
239             //todo: if num-parents > 1 then complain.
240             //todo: if not found in update list, remove from system
241             //todo: if update list item not found in parent list, add to system.
242         }
243         for (RelationsCommonList.RelationListItem childListItem : childList.getRelationListItem()) {
244            System.out.println("    childListItem: " + childListItem);
245             //todo: if not found in update list, remove from system
246             //todo: if update list item not found in child list, add to system.
247         }
248
249
250
251      */
252     public RelationsCommonList updateRelations(String itemCSID, PoxPayloadIn input) throws Exception {
253         PayloadInputPart part = input.getPart(RelationClient.SERVICE_COMMON_LIST_NAME);        //input.getPart("relations_common");
254         if (part == null) {
255             System.out.println("Nothing to do in updateRelations: " + input);
256             return null;
257         }
258         RelationsCommonList relationsCommonListBody = (RelationsCommonList) part.getBody();
259
260         ServiceContext ctx = getServiceContext();
261         MultivaluedMap queryParams = ctx.getQueryParams();
262        String predicate = RelationshipType.HAS_BROADER.value();
263         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
264         queryParams.putSingle(IRelationsManager.SUBJECT_QP, null);
265         queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
266         queryParams.putSingle(IRelationsManager.OBJECT_QP, itemCSID);
267         queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
268
269         RelationsCommonList childListOuter = (new RelationResource()).getList(ctx.getUriInfo());    //magically knows all query params because they are in the context.
270
271         //Leave predicate, swap subject and object.
272         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
273         queryParams.putSingle(IRelationsManager.SUBJECT_QP, itemCSID);
274         queryParams.putSingle(IRelationsManager.OBJECT_QP, null);
275
276         RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo());
277         /*
278             go through inboundList, remove anything from childList that matches  from childList
279             go through inboundList, remove anything from parentList that matches  from parentList
280             go through parentList, delete all remaining
281             go through childList, delete all remaining
282             go through actionList, add all remaining.
283             check for duplicate children
284             check for more than one parent.
285
286         inboundList                           parentList                      childList          actionList
287         ----------------                          ---------------                  ----------------       ----------------
288         child-a                                   parent-c                        child-a             child-b
289         child-b                                   parent-d                        child-c
290          parent-a
291            */
292         String HAS_BROADER = RelationshipType.HAS_BROADER.value();
293
294         List<RelationsCommonList.RelationListItem> inboundList = relationsCommonListBody.getRelationListItem();
295         List<RelationsCommonList.RelationListItem> actionList = newList();
296         List<RelationsCommonList.RelationListItem> childList = childListOuter.getRelationListItem();
297         List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
298
299         for (RelationsCommonList.RelationListItem inboundItem : inboundList) {
300             if (inboundItem.getObjectCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)){
301                 //then this is an item that says we have a child.
302                 RelationsCommonList.RelationListItem childItem = findInList(childList, inboundItem);
303                 if (childItem != null){
304                     removeFromList(childList,  childItem);    //exists, just take it off delete list
305                 } else {
306                     actionList.add(inboundItem);   //doesn't exist as a child, but is a child.  Add to additions list
307                 }
308             } else if  (inboundItem.getSubjectCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) {
309                 //then this is an item that says we have a parent
310                 RelationsCommonList.RelationListItem parentItem = findInList(parentList, inboundItem);
311                 if (parentItem != null){
312                     removeFromList(parentList,  parentItem);    //exists, just take it off delete list
313                 } else {
314                     actionList.add(inboundItem);   //doesn't exist as a parent, but is a parent. Add to additions list
315                 }
316             }  else {
317                 System.out.println("\r\n\r\n================\r\n    Element didn't match parent or child, but may have partial fields that match. inboundItem: "+inboundItem);
318                 //not dealing with: hasNarrower or any other predicate.
319
320             }
321         }
322         deleteRelations(parentList, ctx);
323         deleteRelations(childList, ctx);
324         createRelations(actionList, ctx);
325
326         return relationsCommonListBody;
327     }
328
329     private void createRelations(List<RelationsCommonList.RelationListItem> inboundList, ServiceContext ctx){
330          for (RelationsCommonList.RelationListItem item : inboundList) {
331             RelationsCommon rc = new RelationsCommon();
332             //rc.setCsid(item.getCsid());
333             rc.setDocumentId1(item.getSubjectCsid());
334             rc.setDocumentId2(item.getObjectCsid());
335             rc.setRelationshipType(item.getPredicate());
336             //todo: is an enum:  rc.setPredicate(item.getPredicate());
337             rc.setDocumentType1(item.getSubject().getDocumentType());
338             rc.setDocumentType2(item.getObject().getDocumentType());
339
340             PoxPayloadOut payloadOut = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME);
341             PayloadOutputPart outputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMONPART_NAME, rc);
342             payloadOut.addPart(outputPart);
343             System.out.println("\r\n==== TO CREATE: "+rc.getDocumentId1()+"==>"+rc.getPredicate()+"==>"+rc.getDocumentId2());
344             RelationResource relationResource = new RelationResource();
345             Object res = relationResource.create(ctx.getUriInfo(), payloadOut.toXML());    //NOTE ui recycled from above to pass in unknown query params.
346         }
347     }
348      private void deleteRelations(List<RelationsCommonList.RelationListItem> list,ServiceContext ctx){
349           try {
350               for (RelationsCommonList.RelationListItem inboundItem : list) {
351                   RelationResource relationResource = new RelationResource();
352                   System.out.println("\r\n==== TO DELETE: "+inboundItem.getCsid());
353                   Object res = relationResource.delete(inboundItem.getCsid());
354               }
355           } catch (Throwable t){
356               String msg = "Unable to deleteRelations: "+ Tools.errorToString(t, true);
357               logger.error(msg);
358           }
359      }
360
361     private  List<RelationsCommonList.RelationListItem> newList(){
362         List<RelationsCommonList.RelationListItem> result = new ArrayList<RelationsCommonList.RelationListItem>();
363         return result;
364     }
365      protected List<RelationsCommonList.RelationListItem> cloneList(List<RelationsCommonList.RelationListItem> inboundList){
366         List<RelationsCommonList.RelationListItem> result = newList();
367         for (RelationsCommonList.RelationListItem item: inboundList){
368             result.add(item);
369         }
370         return result;
371     }
372      private RelationsCommonList.RelationListItem findInList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
373          for (RelationsCommonList.RelationListItem listItem : list) {
374              if (itemsEqual(listItem, item)){   //equals must be defined, else
375                 return listItem;
376              }
377          }
378          return null;
379      }
380
381     private boolean itemsEqual(RelationsCommonList.RelationListItem item, RelationsCommonList.RelationListItem item2){
382         if (item==null || item2==null){
383             return false;
384         }
385         return     (item.getSubjectCsid().equals(item2.getSubjectCsid()))
386                 && (item.getObjectCsid().equals(item2.getObjectCsid()))
387                 && ( (item.getPredicate().equals(item2.getPredicate()))
388                 && (item.getRelationshipType().equals(item2.getRelationshipType()))   )
389                 && (item.getObject().getDocumentType().equals(item2.getObject().getDocumentType()))
390                 && (item.getSubject().getDocumentType().equals(item2.getSubject().getDocumentType())) ;
391     }
392
393      private void removeFromList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
394         list.remove(item);
395     }
396     //================= TODO: move this to common, refactoring this and  CollectionObjectResource.java
397
398     public RelationsCommonList getRelations(String subjectCSID, String objectCSID, String predicate) throws Exception {
399         ServiceContext ctx = getServiceContext();
400         MultivaluedMap queryParams = ctx.getQueryParams();
401         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
402         queryParams.putSingle(IRelationsManager.SUBJECT_QP, subjectCSID);
403         queryParams.putSingle(IRelationsManager.OBJECT_QP, objectCSID);
404
405         RelationResource relationResource = new RelationResource();
406         RelationsCommonList relationsCommonList = relationResource.getList(ctx.getUriInfo());
407         return relationsCommonList;
408     }
409
410     //============================= END refactor ==========================
411
412 }
413