]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
8bbfd41cfd8690b335c9e29bf74d96f64b1043fd
[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.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.ListIterator;
32 import java.util.Map;
33
34 import org.collectionspace.services.client.AuthorityClient;
35 import org.collectionspace.services.client.PayloadInputPart;
36 import org.collectionspace.services.client.PayloadOutputPart;
37 import org.collectionspace.services.client.PoxPayloadIn;
38 import org.collectionspace.services.client.PoxPayloadOut;
39 import org.collectionspace.services.client.RelationClient;
40 //import org.collectionspace.services.common.authority.AuthorityItemRelations;
41 import org.collectionspace.services.common.api.CommonAPI;
42 import org.collectionspace.services.common.api.RefName;
43 import org.collectionspace.services.common.api.Tools;
44 import org.collectionspace.services.common.context.MultipartServiceContext;
45 import org.collectionspace.services.common.context.ServiceContext;
46 import org.collectionspace.services.common.document.DocumentWrapper;
47 import org.collectionspace.services.common.relation.IRelationsManager;
48 import org.collectionspace.services.common.service.ObjectPartType;
49 import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
50 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
51 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
52 import org.collectionspace.services.relation.RelationResource;
53 import org.collectionspace.services.relation.RelationsCommon;
54 import org.collectionspace.services.relation.RelationsCommonList;
55 import org.collectionspace.services.relation.RelationsDocListItem;
56 import org.collectionspace.services.relation.RelationshipType;
57 import org.nuxeo.ecm.core.api.DocumentModel;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 import javax.management.relation.Relation;
62 import javax.ws.rs.core.MultivaluedMap;
63 import javax.ws.rs.core.UriInfo;
64
65 /**
66  * AuthorityItemDocumentModelHandler
67  *
68  * $LastChangedRevision: $
69  * $LastChangedDate: $
70  */
71 public abstract class AuthorityItemDocumentModelHandler<AICommon, AICommonList>
72         extends RemoteDocumentModelHandlerImpl<AICommon, AICommonList> {
73
74     private final Logger logger = LoggerFactory.getLogger(AuthorityItemDocumentModelHandler.class);
75
76         private String authorityItemCommonSchemaName;
77         
78     //private final Logger logger = LoggerFactory.getLogger(AuthorityItemDocumentModelHandler.class);
79     /**
80      * item is used to stash JAXB object to use when handle is called
81      * for Action.CREATE, Action.UPDATE or Action.GET
82      */
83     protected AICommon item;
84     /**
85      * itemList is stashed when handle is called
86      * for ACTION.GET_ALL
87      */
88     protected AICommonList itemList;
89     
90     /**
91      * inVocabulary is the parent Authority for this context
92      */
93     protected String inAuthority;
94     protected String authorityRefNameBase;
95     
96     public AuthorityItemDocumentModelHandler(String authorityItemCommonSchemaName) {
97         this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
98     }
99
100     public String getInAuthority() {
101                 return inAuthority;
102         }
103
104         public void setInAuthority(String inAuthority) {
105                 this.inAuthority = inAuthority;
106         }
107
108    // Laramie20110510 CSPACE-3932
109    public static final String HACK_VOCABULARIES = "vocabularies"; //TODO: get rid of these.
110     //public static final String HACK_ORGANIZATIONS = "Organizations"; //TODO: get rid of these.
111     public static final String HACK_ORGAUTHORITIES = "orgauthorities";  //TODO: get rid of these.
112     public static final String HACK_PERSONAUTHORITIES = "personauthorities";  //TODO: get rid of these.
113     public static final String HACK_LOCATIONAUTHORITIES = "locationauthorities";  //TODO: get rid of these.
114     private final static Map<String,String> hackMap = new HashMap<String,String>();
115     static {
116         hackMap.put("persons", HACK_PERSONAUTHORITIES);
117         hackMap.put("organizations", HACK_ORGAUTHORITIES);
118         hackMap.put("vocabularies", HACK_VOCABULARIES);
119         hackMap.put("locations", HACK_LOCATIONAUTHORITIES);
120     }
121     @Override
122     public String getUri(DocumentModel docModel) {
123         // Laramie20110510 CSPACE-3932
124         String serviceContextName = getServiceContext().getServiceName().toLowerCase();
125         String displayContextPath = hackMap.get(serviceContextName);
126         if (Tools.isEmpty(displayContextPath)){
127             displayContextPath = serviceContextName;
128         }
129         return "/"+displayContextPath+'/'+inAuthority+'/'+ AuthorityClient.ITEMS+'/'+getCsid(docModel);
130     }
131
132
133     public String getAuthorityRefNameBase(){
134         return this.authorityRefNameBase;
135     }
136
137     public void setAuthorityRefNameBase(String value){
138         this.authorityRefNameBase = value;
139     }
140
141     /* (non-Javadoc)
142      * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#handleCreate(org.collectionspace.services.common.document.DocumentWrapper)
143      */
144     @Override
145     public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
146         // first fill all the parts of the document
147         super.handleCreate(wrapDoc);            
148         handleInAuthority(wrapDoc.getWrappedObject());
149         // Uncomment once debugged and App layer is read to integrate
150         //handleDisplayNameAsShortIdentifier(wrapDoc.getWrappedObject(), authorityItemCommonSchemaName);
151         //updateRefnameForAuthorityItem(wrapDoc, authorityItemCommonSchemaName, getAuthorityRefNameBase());  //CSPACE-3178
152     }
153     
154     private void handleDisplayNameAsShortIdentifier(DocumentModel docModel, String schemaName) throws Exception {
155         String shortIdentifier = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.SHORT_IDENTIFIER);
156         String displayName =     (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.DISPLAY_NAME);
157         if (Tools.isEmpty(shortIdentifier) && Tools.notEmpty(displayName)){
158             String cookedShortIdentifier = Tools.squeeze(displayName)+'-'+Tools.now().toString();
159             docModel.setProperty(schemaName , AuthorityItemJAXBSchema.SHORT_IDENTIFIER, cookedShortIdentifier);
160         }
161     }
162
163     protected void updateRefnameForAuthorityItem(DocumentWrapper<DocumentModel> wrapDoc,
164             String schemaName,
165             String authorityRefBaseName) throws Exception {
166         DocumentModel docModel = wrapDoc.getWrappedObject();
167         String shortIdentifier = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.SHORT_IDENTIFIER);
168         String displayName =     (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.DISPLAY_NAME);
169         if (Tools.isEmpty(authorityRefBaseName)){
170                 throw new Exception("updateRefnameForAuthorityItem requires an authorityRefBaseName, but none was supplied.");
171         }
172         RefName.Authority authority = RefName.Authority.parse(authorityRefBaseName);
173         String refName = RefName.buildAuthorityItem(authority, shortIdentifier, displayName).toString();
174         docModel.setProperty(schemaName , AuthorityItemJAXBSchema.REF_NAME, refName);
175     }
176
177     /**
178      * Check the logic around the parent pointer. Note that we only need do this on
179      * create, since we have logic to make this read-only on update. 
180      * 
181      * @param docModel
182      * 
183      * @throws Exception the exception
184      */
185     private void handleInAuthority(DocumentModel docModel) throws Exception {
186         docModel.setProperty(authorityItemCommonSchemaName, 
187                         AuthorityItemJAXBSchema.IN_AUTHORITY, inAuthority);
188     }
189
190
191     /**
192      * getCommonPart get associated item
193      * @return
194      */
195     @Override
196     public AICommon getCommonPart() {
197         return item;
198     }
199
200     @Override
201     public void setCommonPart(AICommon item) {
202         this.item = item;
203     }
204
205     /**
206      * getCommonPartList get associated item (for index/GET_ALL)
207      * @return
208      */
209     @Override
210     public AICommonList getCommonPartList() {
211         return itemList;
212     }
213
214     @Override
215     public void setCommonPartList(AICommonList itemList) {
216         this.itemList = itemList;
217     }
218
219     @Override
220     public AICommon extractCommonPart(DocumentWrapper<DocumentModel> wrapDoc)
221             throws Exception {
222         throw new UnsupportedOperationException();
223     }
224
225     @Override
226     public void fillCommonPart(AICommon itemObject, DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
227         throw new UnsupportedOperationException();
228     }
229     
230     /* (non-Javadoc)
231      * @see org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl#extractPart(org.nuxeo.ecm.core.api.DocumentModel, java.lang.String, org.collectionspace.services.common.service.ObjectPartType)
232      */
233     @Override
234     protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
235             throws Exception {
236         Map<String, Object> unQObjectProperties = super.extractPart(docModel, schema, partMeta);
237         
238         // Add the CSID to the common part
239         if (partMeta.getLabel().equalsIgnoreCase(authorityItemCommonSchemaName)) {
240                 String csid = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
241                 unQObjectProperties.put("csid", csid);
242         }
243         
244         return unQObjectProperties;
245     }
246     
247     /**
248      * Filters out AuthorityItemJAXBSchema.IN_AUTHORITY, to ensure that
249      * the parent link remains untouched.
250      * @param objectProps the properties parsed from the update payload
251      * @param partMeta metadata for the object to fill
252      */
253     @Override
254     public void filterReadOnlyPropertiesForPart(
255                 Map<String, Object> objectProps, ObjectPartType partMeta) {
256         super.filterReadOnlyPropertiesForPart(objectProps, partMeta);
257         objectProps.remove(AuthorityItemJAXBSchema.IN_AUTHORITY);
258         objectProps.remove(AuthorityItemJAXBSchema.CSID);
259     }
260
261     @Override
262     public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
263         MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
264         super.extractAllParts(wrapDoc);
265
266         String showSiblings = ctx.getQueryParams().getFirst(CommonAPI.showSiblings_QP);
267         if (Tools.isTrue(showSiblings)) {
268             showSiblings(wrapDoc, ctx);
269             return;   // actual result is returned on ctx.addOutputPart();
270         }
271
272         String showRelations = ctx.getQueryParams().getFirst(CommonAPI.showRelations_QP);
273         if (Tools.isTrue(showRelations)) {
274             showRelations(wrapDoc, ctx);
275             return;   // actual result is returned on ctx.addOutputPart();
276         }
277
278         String showAllRelations = ctx.getQueryParams().getFirst(CommonAPI.showAllRelations_QP);
279         if (Tools.isTrue(showAllRelations)) {
280             showAllRelations(wrapDoc, ctx);
281             return;   // actual result is returned on ctx.addOutputPart();
282         }
283     }
284
285     /** @return null on parent not found
286      */
287     protected String getParentCSID(String thisCSID) throws Exception {
288         String parentCSID = null;
289         try {
290             String predicate = RelationshipType.HAS_BROADER.value();
291             RelationsCommonList parentListOuter = getRelations(thisCSID, null, predicate);
292             List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
293             if (parentList != null) {
294                 RelationsCommonList.RelationListItem relationListItem = parentList.get(0);
295                 parentCSID = relationListItem.getObjectCsid();
296             }
297             return parentCSID;
298         } catch (Exception e) {
299             logger.error("Could not find parent for this: "+thisCSID, e);
300             return null;
301         }
302     }
303
304     public void showRelations(DocumentWrapper<DocumentModel> wrapDoc,
305                                               MultipartServiceContext ctx)   throws Exception {
306         String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
307
308          String predicate = RelationshipType.HAS_BROADER.value();
309          RelationsCommonList parentListOuter = getRelations(thisCSID, null, predicate);
310          List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
311
312          RelationsCommonList childrenListOuter = getRelations(null, thisCSID, predicate);
313          List<RelationsCommonList.RelationListItem> childrenList = childrenListOuter.getRelationListItem();
314
315          //Assume that there are more children than parents.  Will be true for parent/child, but maybe not for other relations.
316          //Now add all parents to our childrenList, to be able to return just one list of consolidated results.
317          //Not optimal, but that's the current design spec.
318         long added = 0;
319         for (RelationsCommonList.RelationListItem parent : parentList) {
320              childrenList.add(parent);
321              added++;
322         }
323         long childrenSize = childrenList.size();
324         childrenListOuter.setTotalItems(childrenSize);
325         childrenListOuter.setItemsInPage(childrenListOuter.getItemsInPage()+added);
326
327         PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, childrenListOuter);
328         ctx.addOutputPart(relationsPart);
329     }
330
331     public void showSiblings(DocumentWrapper<DocumentModel> wrapDoc,
332                                               MultipartServiceContext ctx)   throws Exception {
333         String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
334          String parentCSID = getParentCSID(thisCSID);
335         if (parentCSID == null){
336             logger.warn("~~~~~\r\n~~~~ Could not find parent for this: "+thisCSID);
337             return;
338         }
339
340          String predicate = RelationshipType.HAS_BROADER.value();
341          RelationsCommonList siblingListOuter = getRelations(null, parentCSID, predicate);
342          List<RelationsCommonList.RelationListItem> siblingList = siblingListOuter.getRelationListItem();
343
344         List<RelationsCommonList.RelationListItem> toRemoveList = newList();
345
346
347         RelationsCommonList.RelationListItem item = null;
348         for (RelationsCommonList.RelationListItem sibling : siblingList) {
349             if (thisCSID.equals(sibling.getSubjectCsid())){
350                 toRemoveList.add(sibling);   //IS_A copy of the main item, i.e. I have a parent that is my parent, so I'm in the list from the above query.
351             }
352         }
353         //rather than create an immutable iterator, I'm just putting the items to remove on a separate list, then looping over that list and removing.
354         for (RelationsCommonList.RelationListItem self : toRemoveList) {
355             removeFromList(siblingList, self);
356         }
357
358         long siblingSize = siblingList.size();
359         siblingListOuter.setTotalItems(siblingSize);
360         siblingListOuter.setItemsInPage(siblingSize);
361
362         PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME,siblingListOuter);
363         ctx.addOutputPart(relationsPart);
364     }
365
366     public void showAllRelations(DocumentWrapper<DocumentModel> wrapDoc, MultipartServiceContext ctx)   throws Exception {
367         String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
368
369         RelationsCommonList subjectListOuter = getRelations(thisCSID, null, null);   //  nulls are wildcards:  predicate=*, and object=*
370         List<RelationsCommonList.RelationListItem> subjectList = subjectListOuter.getRelationListItem();
371
372         RelationsCommonList objectListOuter = getRelations(null, thisCSID, null);   //  nulls are wildcards:  subject=*, and predicate=*
373         List<RelationsCommonList.RelationListItem> objectList = objectListOuter.getRelationListItem();
374
375         //  MERGE LISTS:
376         subjectList.addAll(objectList);
377
378         //now subjectList actually has records BOTH where thisCSID is subject and object.
379         long relatedSize = subjectList.size();
380         subjectListOuter.setTotalItems(relatedSize);
381         subjectListOuter.setItemsInPage(relatedSize);
382
383         PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME,subjectListOuter);
384         ctx.addOutputPart(relationsPart);
385     }
386
387     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
388         super.fillAllParts(wrapDoc, action);
389         ServiceContext ctx = getServiceContext();
390         PoxPayloadIn input = (PoxPayloadIn)ctx.getInput();
391         DocumentModel documentModel = (wrapDoc.getWrappedObject());
392         String itemCsid = documentModel.getName();
393
394         //UPDATE and CREATE will call.   Updates relations part
395         RelationsCommonList relationsCommonList = updateRelations(itemCsid, input, wrapDoc);
396
397         PayloadOutputPart payloadOutputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, relationsCommonList);
398         ctx.setProperty(RelationClient.SERVICE_COMMON_LIST_NAME, payloadOutputPart);
399     }
400
401     public void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
402         super.completeUpdate(wrapDoc);
403         //now we add part for relations list
404         ServiceContext ctx = getServiceContext();
405         PayloadOutputPart foo = (PayloadOutputPart)ctx.getProperty(RelationClient.SERVICE_COMMON_LIST_NAME);
406         ((PoxPayloadOut)ctx.getOutput()).addPart(foo);
407     }
408
409     public RelationsCommonList updateRelations(String itemCSID, PoxPayloadIn input, DocumentWrapper<DocumentModel> wrapDoc)
410      throws Exception {
411         PayloadInputPart part = input.getPart(RelationClient.SERVICE_COMMON_LIST_NAME);        //input.getPart("relations_common");
412         if (part == null) {
413             return null;  //nothing to do--they didn't send a list of relations.
414         }
415         RelationsCommonList relationsCommonListBody = (RelationsCommonList) part.getBody();
416
417         ServiceContext ctx = getServiceContext();
418         UriInfo uriInfo = ctx.getUriInfo();
419         MultivaluedMap queryParams = uriInfo.getQueryParameters();
420
421         String predicate = RelationshipType.HAS_BROADER.value();
422         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
423         queryParams.putSingle(IRelationsManager.SUBJECT_QP, null);
424         queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
425         queryParams.putSingle(IRelationsManager.OBJECT_QP, itemCSID);
426         queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
427
428         RelationsCommonList childListOuter = (new RelationResource()).getList(ctx.getUriInfo());    //magically knows all query params because they are in the context.
429
430         //Leave predicate, swap subject and object.
431         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
432         queryParams.putSingle(IRelationsManager.SUBJECT_QP, itemCSID);
433         queryParams.putSingle(IRelationsManager.OBJECT_QP, null);
434
435         RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo());
436         /*
437             go through inboundList, remove anything from childList that matches  from childList
438             go through inboundList, remove anything from parentList that matches  from parentList
439             go through parentList, delete all remaining
440             go through childList, delete all remaining
441             go through actionList, add all remaining.
442             check for duplicate children
443             check for more than one parent.
444
445         inboundList                           parentList                      childList          actionList
446         ----------------                          ---------------                  ----------------       ----------------
447         child-a                                   parent-c                        child-a             child-b
448         child-b                                   parent-d                        child-c
449          parent-a
450            */
451         String HAS_BROADER = RelationshipType.HAS_BROADER.value();
452
453         List<RelationsCommonList.RelationListItem> inboundList = relationsCommonListBody.getRelationListItem();
454         List<RelationsCommonList.RelationListItem> actionList = newList();
455         List<RelationsCommonList.RelationListItem> childList = childListOuter.getRelationListItem();
456         List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
457
458         DocumentModel docModel = wrapDoc.getWrappedObject();
459
460         for (RelationsCommonList.RelationListItem inboundItem : inboundList) {
461             if (inboundItem.getObject().getCsid().equalsIgnoreCase(CommonAPI.AuthorityItemCSID_REPLACE)){
462                 inboundItem.setObjectCsid(itemCSID);
463                 inboundItem.getObject().setCsid(itemCSID);
464                 inboundItem.getObject().setUri(getUri(docModel));
465             }
466             if (inboundItem.getSubject().getCsid().equalsIgnoreCase(CommonAPI.AuthorityItemCSID_REPLACE)){
467                 inboundItem.setSubjectCsid(itemCSID);
468                 inboundItem.getSubject().setCsid(itemCSID);
469                  inboundItem.getSubject().setUri(getUri(docModel));
470             }
471             if (inboundItem.getObject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) {
472                 //then this is an item that says we have a child.
473                 RelationsCommonList.RelationListItem childItem = findInList(childList, inboundItem);
474                 if (childItem != null){
475                     removeFromList(childList,  childItem);    //exists, just take it off delete list
476                 } else {
477                     actionList.add(inboundItem);   //doesn't exist as a child, but is a child.  Add to additions list
478                 }
479             } else if  (inboundItem.getSubject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) {
480                 //then this is an item that says we have a parent
481                 RelationsCommonList.RelationListItem parentItem = findInList(parentList, inboundItem);
482                 if (parentItem != null){
483                     removeFromList(parentList,  parentItem);    //exists, just take it off delete list
484                 } else {
485                     actionList.add(inboundItem);   //doesn't exist as a parent, but is a parent. Add to additions list
486                 }
487             }  else {
488
489                 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);
490                 //not dealing with: hasNarrower or any other predicate.
491             }
492         }
493         deleteRelations(parentList, ctx);               //todo: there are items appearing on both lists....april 20.
494         deleteRelations(childList, ctx);
495         createRelations(actionList, ctx);
496         //We return all elements on the inbound list, since we have just worked to make them exist in the system
497         // and be non-redundant, etc.  That list came from relationsCommonListBody, so it is still attached to it, just pass that back.
498         return relationsCommonListBody;
499     }
500
501     // this method calls the RelationResource to have it create the relations and persist them.
502     private void createRelations(List<RelationsCommonList.RelationListItem> inboundList, ServiceContext ctx){
503          for (RelationsCommonList.RelationListItem item : inboundList) {
504              RelationsCommon rc = new RelationsCommon();
505              //rc.setCsid(item.getCsid());
506              //todo: assignTo(item, rc);
507              RelationsDocListItem itemSubject = item.getSubject();
508              RelationsDocListItem itemObject = item.getObject();
509
510              String subjectCsid =  itemSubject.getCsid();
511              rc.setDocumentId1(subjectCsid);
512              rc.setSubjectCsid(subjectCsid);
513
514              String objCsid = item.getObject().getCsid();
515              rc.setDocumentId2(objCsid);
516              rc.setObjectCsid(objCsid);
517
518              rc.setRelationshipType(item.getPredicate());
519              //RelationshipType  foo = (RelationshipType.valueOf(item.getPredicate())) ;
520              //rc.setPredicate(foo);     //this must be one of the type found in the enum in  services/jaxb/src/main/resources/relations_common.xsd
521
522              rc.setDocumentType1(itemSubject.getDocumentType());
523              rc.setDocumentType2(itemObject.getDocumentType());
524
525              rc.setSubjectUri(itemSubject.getUri());
526              rc.setObjectUri(itemObject.getUri());
527
528
529             PoxPayloadOut payloadOut = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME);
530             PayloadOutputPart outputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMONPART_NAME, rc);
531             payloadOut.addPart(outputPart);
532             //System.out.println("\r\n==== TO CREATE: "+rc.getDocumentId1()+"==>"+rc.getPredicate()+"==>"+rc.getDocumentId2());
533             RelationResource relationResource = new RelationResource();
534             Object res = relationResource.create(ctx.getUriInfo(), payloadOut.toXML());    //NOTE ui recycled from above to pass in unknown query params.
535         }
536     }
537      private void deleteRelations(List<RelationsCommonList.RelationListItem> list,ServiceContext ctx){
538           try {
539               for (RelationsCommonList.RelationListItem inboundItem : list) {
540                   RelationResource relationResource = new RelationResource();
541                   //System.out.println("\r\n==== TO DELETE: "+inboundItem.getCsid());
542                   Object res = relationResource.delete(inboundItem.getCsid());
543               }
544           } catch (Throwable t){
545               String msg = "Unable to deleteRelations: "+ Tools.errorToString(t, true);
546               logger.error(msg);
547           }
548      }
549
550     private  List<RelationsCommonList.RelationListItem> newList(){
551         List<RelationsCommonList.RelationListItem> result = new ArrayList<RelationsCommonList.RelationListItem>();
552         return result;
553     }
554      protected List<RelationsCommonList.RelationListItem> cloneList(List<RelationsCommonList.RelationListItem> inboundList){
555         List<RelationsCommonList.RelationListItem> result = newList();
556         for (RelationsCommonList.RelationListItem item: inboundList){
557             result.add(item);
558         }
559         return result;
560     }
561      private RelationsCommonList.RelationListItem findInList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
562          for (RelationsCommonList.RelationListItem listItem : list) {
563              if (itemsEqual(listItem, item)){   //equals must be defined, else
564                 return listItem;
565              }
566          }
567          return null;
568      }
569
570     private boolean itemsEqual(RelationsCommonList.RelationListItem item, RelationsCommonList.RelationListItem item2){
571         if (item==null || item2==null){
572             return false;
573         }
574         RelationsDocListItem subj1 = item.getSubject();
575         RelationsDocListItem subj2 = item2.getSubject();
576         RelationsDocListItem obj1 = item.getObject();
577         RelationsDocListItem obj2 = item2.getObject();
578
579         return     (subj1.getCsid().equals(subj2.getCsid()))
580                 && (obj1.getCsid().equals(obj1.getCsid()))
581                 && ( (item.getPredicate().equals(item2.getPredicate()))
582                 && (item.getRelationshipType().equals(item2.getRelationshipType()))   )
583                 && (obj1.getDocumentType().equals(obj2.getDocumentType()))
584                 && (subj1.getDocumentType().equals(subj2.getDocumentType())) ;
585     }
586
587      private void removeFromList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
588         list.remove(item);
589     }
590     //================= TODO: move this to common, refactoring this and  CollectionObjectResource.java
591
592     public RelationsCommonList getRelations(String subjectCSID, String objectCSID, String predicate) throws Exception {
593         ServiceContext ctx = getServiceContext();
594         MultivaluedMap queryParams = ctx.getQueryParams();
595         queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
596         queryParams.putSingle(IRelationsManager.SUBJECT_QP, subjectCSID);
597         queryParams.putSingle(IRelationsManager.OBJECT_QP, objectCSID);
598
599         RelationResource relationResource = new RelationResource();
600         RelationsCommonList relationsCommonList = relationResource.getList(ctx.getUriInfo());
601         return relationsCommonList;
602     }
603
604     //============================= END refactor ==========================
605
606 }
607