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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.common.vocabulary.nuxeo;
26 import org.collectionspace.services.client.AuthorityClient;
27 import org.collectionspace.services.client.PayloadInputPart;
28 import org.collectionspace.services.client.PayloadOutputPart;
29 import org.collectionspace.services.client.PoxPayloadIn;
30 import org.collectionspace.services.client.PoxPayloadOut;
31 import org.collectionspace.services.client.RelationClient;
32 import org.collectionspace.services.common.api.CommonAPI;
33 import org.collectionspace.services.common.api.RefName;
34 import org.collectionspace.services.common.api.Tools;
35 import org.collectionspace.services.common.context.MultipartServiceContext;
36 import org.collectionspace.services.common.context.ServiceContext;
37 import org.collectionspace.services.common.document.DocumentWrapper;
38 import org.collectionspace.services.common.document.DocumentWrapperImpl;
39 import org.collectionspace.services.common.relation.IRelationsManager;
40 import org.collectionspace.services.common.repository.RepositoryClient;
41 import org.collectionspace.services.common.repository.RepositoryClientFactory;
42 import org.collectionspace.services.common.service.ObjectPartType;
43 import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
44 import org.collectionspace.services.nuxeo.client.java.DocHandlerBase;
45 import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl;
46 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
47 import org.collectionspace.services.relation.RelationResource;
48 import org.collectionspace.services.relation.RelationsCommon;
49 import org.collectionspace.services.relation.RelationsCommonList;
50 import org.collectionspace.services.relation.RelationsDocListItem;
51 import org.collectionspace.services.relation.RelationshipType;
52 import org.nuxeo.ecm.core.api.DocumentModel;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 import javax.ws.rs.core.MultivaluedMap;
57 import javax.ws.rs.core.UriInfo;
58 import java.util.ArrayList;
59 import java.util.List;
61 import java.util.regex.Matcher;
62 import java.util.regex.Pattern;
64 //import org.collectionspace.services.common.authority.AuthorityItemRelations;
67 * AuthorityItemDocumentModelHandler
69 * $LastChangedRevision: $
72 public abstract class AuthorityItemDocumentModelHandler<AICommon>
73 extends DocHandlerBase<AICommon> {
75 private final Logger logger = LoggerFactory.getLogger(AuthorityItemDocumentModelHandler.class);
77 private String authorityItemCommonSchemaName;
80 * inVocabulary is the parent Authority for this context
82 protected String inAuthority;
83 protected String authorityRefNameBase;
85 public AuthorityItemDocumentModelHandler(String authorityItemCommonSchemaName) {
86 this.authorityItemCommonSchemaName = authorityItemCommonSchemaName;
89 public String getInAuthority() {
93 public void setInAuthority(String inAuthority) {
94 this.inAuthority = inAuthority;
97 /** Subclasses may override this to customize the URI segment. */
98 public String getAuthorityServicePath(){
99 return getServiceContext().getServiceName().toLowerCase(); // Laramie20110510 CSPACE-3932
103 public String getUri(DocumentModel docModel) {
104 // Laramie20110510 CSPACE-3932
105 String authorityServicePath = getAuthorityServicePath();
106 return "/"+authorityServicePath+'/'+inAuthority+'/'+ AuthorityClient.ITEMS+'/'+getCsid(docModel);
109 public String getAuthorityRefNameBase(){
110 return this.authorityRefNameBase;
113 public void setAuthorityRefNameBase(String value){
114 this.authorityRefNameBase = value;
118 * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#handleCreate(org.collectionspace.services.common.document.DocumentWrapper)
121 public void handleCreate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
122 // first fill all the parts of the document
123 super.handleCreate(wrapDoc);
124 handleInAuthority(wrapDoc.getWrappedObject());
125 // Uncomment once debugged and App layer is read to integrate
126 //handleDisplayNameAsShortIdentifier(wrapDoc.getWrappedObject(), authorityItemCommonSchemaName);
127 //updateRefnameForAuthorityItem(wrapDoc, authorityItemCommonSchemaName, getAuthorityRefNameBase()); //CSPACE-3178
130 private void handleDisplayNameAsShortIdentifier(DocumentModel docModel, String schemaName) throws Exception {
131 String shortIdentifier = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.SHORT_IDENTIFIER);
132 String displayName = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.DISPLAY_NAME);
133 if (Tools.isEmpty(shortIdentifier) && Tools.notEmpty(displayName)){
134 String cookedShortIdentifier = Tools.squeeze(displayName)+'-'+Tools.now().toString();
135 docModel.setProperty(schemaName , AuthorityItemJAXBSchema.SHORT_IDENTIFIER, cookedShortIdentifier);
139 protected void updateRefnameForAuthorityItem(DocumentWrapper<DocumentModel> wrapDoc,
141 String authorityRefBaseName) throws Exception {
142 DocumentModel docModel = wrapDoc.getWrappedObject();
143 String shortIdentifier = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.SHORT_IDENTIFIER);
144 String displayName = (String)docModel.getProperty(schemaName, AuthorityItemJAXBSchema.DISPLAY_NAME);
145 if (Tools.isEmpty(authorityRefBaseName)){
146 throw new Exception("updateRefnameForAuthorityItem requires an authorityRefBaseName, but none was supplied.");
148 RefName.Authority authority = RefName.Authority.parse(authorityRefBaseName);
149 String refName = RefName.buildAuthorityItem(authority, shortIdentifier, displayName).toString();
150 docModel.setProperty(schemaName , AuthorityItemJAXBSchema.REF_NAME, refName);
154 * Check the logic around the parent pointer. Note that we only need do this on
155 * create, since we have logic to make this read-only on update.
159 * @throws Exception the exception
161 private void handleInAuthority(DocumentModel docModel) throws Exception {
162 docModel.setProperty(authorityItemCommonSchemaName,
163 AuthorityItemJAXBSchema.IN_AUTHORITY, inAuthority);
168 * @see org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl#extractPart(org.nuxeo.ecm.core.api.DocumentModel, java.lang.String, org.collectionspace.services.common.service.ObjectPartType)
171 protected Map<String, Object> extractPart(DocumentModel docModel, String schema, ObjectPartType partMeta)
173 Map<String, Object> unQObjectProperties = super.extractPart(docModel, schema, partMeta);
175 // Add the CSID to the common part
176 if (partMeta.getLabel().equalsIgnoreCase(authorityItemCommonSchemaName)) {
177 String csid = getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
178 unQObjectProperties.put("csid", csid);
181 return unQObjectProperties;
185 * Filters out AuthorityItemJAXBSchema.IN_AUTHORITY, to ensure that
186 * the parent link remains untouched.
187 * @param objectProps the properties parsed from the update payload
188 * @param partMeta metadata for the object to fill
191 public void filterReadOnlyPropertiesForPart(
192 Map<String, Object> objectProps, ObjectPartType partMeta) {
193 super.filterReadOnlyPropertiesForPart(objectProps, partMeta);
194 objectProps.remove(AuthorityItemJAXBSchema.IN_AUTHORITY);
195 objectProps.remove(AuthorityItemJAXBSchema.CSID);
199 public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
200 MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext();
201 super.extractAllParts(wrapDoc);
203 String showSiblings = ctx.getQueryParams().getFirst(CommonAPI.showSiblings_QP);
204 if (Tools.isTrue(showSiblings)) {
205 showSiblings(wrapDoc, ctx);
206 return; // actual result is returned on ctx.addOutputPart();
209 String showRelations = ctx.getQueryParams().getFirst(CommonAPI.showRelations_QP);
210 if (Tools.isTrue(showRelations)) {
211 showRelations(wrapDoc, ctx);
212 return; // actual result is returned on ctx.addOutputPart();
215 String showAllRelations = ctx.getQueryParams().getFirst(CommonAPI.showAllRelations_QP);
216 if (Tools.isTrue(showAllRelations)) {
217 showAllRelations(wrapDoc, ctx);
218 return; // actual result is returned on ctx.addOutputPart();
222 /** @return null on parent not found
224 protected String getParentCSID(String thisCSID) throws Exception {
225 String parentCSID = null;
227 String predicate = RelationshipType.HAS_BROADER.value();
228 RelationsCommonList parentListOuter = getRelations(thisCSID, null, predicate);
229 List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
230 if (parentList != null) {
231 if (parentList.size()==0){
234 RelationsCommonList.RelationListItem relationListItem = parentList.get(0);
235 parentCSID = relationListItem.getObjectCsid();
238 } catch (Exception e) {
239 logger.error("Could not find parent for this: "+thisCSID, e);
244 public void showRelations(DocumentWrapper<DocumentModel> wrapDoc,
245 MultipartServiceContext ctx) throws Exception {
246 String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
248 String predicate = RelationshipType.HAS_BROADER.value();
249 RelationsCommonList parentListOuter = getRelations(thisCSID, null, predicate);
250 List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
252 RelationsCommonList childrenListOuter = getRelations(null, thisCSID, predicate);
253 List<RelationsCommonList.RelationListItem> childrenList = childrenListOuter.getRelationListItem();
255 //Assume that there are more children than parents. Will be true for parent/child, but maybe not for other relations.
256 //Now add all parents to our childrenList, to be able to return just one list of consolidated results.
257 //Not optimal, but that's the current design spec.
259 for (RelationsCommonList.RelationListItem parent : parentList) {
260 childrenList.add(parent);
263 long childrenSize = childrenList.size();
264 childrenListOuter.setTotalItems(childrenSize);
265 childrenListOuter.setItemsInPage(childrenListOuter.getItemsInPage()+added);
267 PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, childrenListOuter);
268 ctx.addOutputPart(relationsPart);
271 public void showSiblings(DocumentWrapper<DocumentModel> wrapDoc,
272 MultipartServiceContext ctx) throws Exception {
273 String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
274 String parentCSID = getParentCSID(thisCSID);
275 if (parentCSID == null){
276 logger.warn("~~~~~\r\n~~~~ Could not find parent for this: "+thisCSID);
280 String predicate = RelationshipType.HAS_BROADER.value();
281 RelationsCommonList siblingListOuter = getRelations(null, parentCSID, predicate);
282 List<RelationsCommonList.RelationListItem> siblingList = siblingListOuter.getRelationListItem();
284 List<RelationsCommonList.RelationListItem> toRemoveList = newList();
287 RelationsCommonList.RelationListItem item = null;
288 for (RelationsCommonList.RelationListItem sibling : siblingList) {
289 if (thisCSID.equals(sibling.getSubjectCsid())){
290 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.
293 //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.
294 for (RelationsCommonList.RelationListItem self : toRemoveList) {
295 removeFromList(siblingList, self);
298 long siblingSize = siblingList.size();
299 siblingListOuter.setTotalItems(siblingSize);
300 siblingListOuter.setItemsInPage(siblingSize);
302 PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME,siblingListOuter);
303 ctx.addOutputPart(relationsPart);
306 public void showAllRelations(DocumentWrapper<DocumentModel> wrapDoc, MultipartServiceContext ctx) throws Exception {
307 String thisCSID = NuxeoUtils.getCsid(wrapDoc.getWrappedObject());
309 RelationsCommonList subjectListOuter = getRelations(thisCSID, null, null); // nulls are wildcards: predicate=*, and object=*
310 List<RelationsCommonList.RelationListItem> subjectList = subjectListOuter.getRelationListItem();
312 RelationsCommonList objectListOuter = getRelations(null, thisCSID, null); // nulls are wildcards: subject=*, and predicate=*
313 List<RelationsCommonList.RelationListItem> objectList = objectListOuter.getRelationListItem();
316 subjectList.addAll(objectList);
318 //now subjectList actually has records BOTH where thisCSID is subject and object.
319 long relatedSize = subjectList.size();
320 subjectListOuter.setTotalItems(relatedSize);
321 subjectListOuter.setItemsInPage(relatedSize);
323 PayloadOutputPart relationsPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME,subjectListOuter);
324 ctx.addOutputPart(relationsPart);
327 public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
328 super.fillAllParts(wrapDoc, action);
329 ServiceContext ctx = getServiceContext();
330 PoxPayloadIn input = (PoxPayloadIn)ctx.getInput();
331 DocumentModel documentModel = (wrapDoc.getWrappedObject());
332 String itemCsid = documentModel.getName();
334 //UPDATE and CREATE will call. Updates relations part
335 RelationsCommonList relationsCommonList = updateRelations(itemCsid, input, wrapDoc);
337 PayloadOutputPart payloadOutputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMON_LIST_NAME, relationsCommonList);
338 ctx.setProperty(RelationClient.SERVICE_COMMON_LIST_NAME, payloadOutputPart);
341 public void completeUpdate(DocumentWrapper<DocumentModel> wrapDoc) throws Exception {
342 super.completeUpdate(wrapDoc);
343 //now we add part for relations list
344 ServiceContext ctx = getServiceContext();
345 PayloadOutputPart foo = (PayloadOutputPart)ctx.getProperty(RelationClient.SERVICE_COMMON_LIST_NAME);
346 ((PoxPayloadOut)ctx.getOutput()).addPart(foo);
349 /** updateRelations strategy:
351 go through inboundList, remove anything from childList that matches from childList
352 go through inboundList, remove anything from parentList that matches from parentList
353 go through parentList, delete all remaining
354 go through childList, delete all remaining
355 go through actionList, add all remaining.
356 check for duplicate children
357 check for more than one parent.
359 inboundList parentList childList actionList
360 ---------------- --------------- ---------------- ----------------
361 child-a parent-c child-a child-b
362 child-b parent-d child-c
365 public RelationsCommonList updateRelations(String itemCSID, PoxPayloadIn input, DocumentWrapper<DocumentModel> wrapDoc)
367 PayloadInputPart part = input.getPart(RelationClient.SERVICE_COMMON_LIST_NAME); //input.getPart("relations_common");
369 return null; //nothing to do--they didn't send a list of relations.
371 RelationsCommonList relationsCommonListBody = (RelationsCommonList) part.getBody();
373 ServiceContext ctx = getServiceContext();
374 UriInfo uriInfo = ctx.getUriInfo();
375 MultivaluedMap queryParams = uriInfo.getQueryParameters();
377 //Run getList() once as sent to get childListOuter:
378 String predicate = RelationshipType.HAS_BROADER.value();
379 queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
380 queryParams.putSingle(IRelationsManager.SUBJECT_QP, null);
381 queryParams.putSingle(IRelationsManager.SUBJECT_TYPE_QP, null);
382 queryParams.putSingle(IRelationsManager.OBJECT_QP, itemCSID);
383 queryParams.putSingle(IRelationsManager.OBJECT_TYPE_QP, null);
384 RelationsCommonList childListOuter = (new RelationResource()).getList(ctx.getUriInfo()); //magically knows all query params because they are in the context.
386 //Now run getList() again, leaving predicate, swapping subject and object, to get parentListOuter.
387 queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
388 queryParams.putSingle(IRelationsManager.SUBJECT_QP, itemCSID);
389 queryParams.putSingle(IRelationsManager.OBJECT_QP, null);
390 RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo());
392 String HAS_BROADER = RelationshipType.HAS_BROADER.value();
394 List<RelationsCommonList.RelationListItem> inboundList = relationsCommonListBody.getRelationListItem();
395 List<RelationsCommonList.RelationListItem> actionList = newList();
396 List<RelationsCommonList.RelationListItem> childList = childListOuter.getRelationListItem();
397 List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
399 if (parentList.size()>1){
400 throw new Exception("Too many parents for object: "+itemCSID+" list: "+dumpList(parentList, "parentList"));
403 DocumentModel docModel = wrapDoc.getWrappedObject();
405 //Do magic replacement of ${itemCSID} and fix URI's.
406 fixupInboundListItems(ctx, inboundList, docModel, itemCSID);
408 for (RelationsCommonList.RelationListItem inboundItem : inboundList) {
409 if (inboundItem.getObject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) {
410 //then this is an item that says we have a child. That child is inboundItem
411 RelationsCommonList.RelationListItem childItem = findInList(childList, inboundItem);
412 if (childItem != null){
413 removeFromList(childList, childItem); //exists, just take it off delete list
415 actionList.add(inboundItem); //doesn't exist as a child, but is a child. Add to additions list
417 ensureChildHasNoOtherParents(ctx, queryParams, inboundItem.getSubject().getCsid());
419 } else if (inboundItem.getSubject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) {
420 //then this is an item that says we have a parent. inboundItem is that parent.
421 RelationsCommonList.RelationListItem parentItem = findInList(parentList, inboundItem);
422 if (parentItem != null){
423 removeFromList(parentList, parentItem); //exists, just take it off delete list
425 actionList.add(inboundItem); //doesn't exist as a parent, but is a parent. Add to additions list
428 logger.warn("Element didn't match parent or child, but may have partial fields that match. inboundItem: "+inboundItem);
429 //not dealing with: hasNarrower or any other predicate.
432 String dump = dumpLists(itemCSID, parentList, childList, actionList);
433 //System.out.println("====dump====="+CR+dump);
434 logger.info("~~~~~~~~~~~~~~~~~~~~~~dump~~~~~~~~~~~~~~~~~~~~~~~~"+CR+ dump);
435 deleteRelations(parentList, ctx, "parentList"); //todo: there are items appearing on both lists....april 20.
436 deleteRelations(childList, ctx, "childList");
437 createRelations(actionList, ctx);
438 //We return all elements on the inbound list, since we have just worked to make them exist in the system
439 // and be non-redundant, etc. That list came from relationsCommonListBody, so it is still attached to it, just pass that back.
440 return relationsCommonListBody;
443 private void ensureChildHasNoOtherParents(ServiceContext ctx, MultivaluedMap queryParams, String childCSID){
444 queryParams.putSingle(IRelationsManager.SUBJECT_QP, childCSID);
445 queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value());
446 queryParams.putSingle(IRelationsManager.OBJECT_QP, null); //null means ANY
447 RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo());
448 List<RelationsCommonList.RelationListItem> parentList = parentListOuter.getRelationListItem();
449 //logger.warn("ensureChildHasNoOtherParents preparing to delete relations on "+childCSID+"\'s parent list: \r\n"+dumpList(parentList, "duplicate parent list"));
450 deleteRelations(parentList, ctx, "parentList-delete");
453 private String dumpLists(String itemCSID,
454 List <RelationsCommonList.RelationListItem> parentList,
455 List<RelationsCommonList.RelationListItem> childList,
456 List<RelationsCommonList.RelationListItem> actionList){
457 StringBuffer sb = new StringBuffer();
458 sb.append("itemCSID: "+itemCSID+CR);
459 sb.append(dumpList(parentList, "parentList"));
460 sb.append(dumpList(childList, "childList"));
461 sb.append(dumpList(actionList, "actionList"));
462 return sb.toString();
465 private final static String CR="\r\n";
466 private final static String T = " ";
468 private String dumpList(List <RelationsCommonList.RelationListItem> list, String label){
469 StringBuffer sb = new StringBuffer();
471 if (list.size()>0) sb.append("=========== "+label+" =========="+CR);
472 for (RelationsCommonList.RelationListItem item : list) {
474 T + item.getSubject().getCsid() //+T4 + item.getSubject().getUri()
475 + T + item.getPredicate()
476 + T + item.getObject().getCsid() //+T4 + item.getObject().getUri()
478 //+"subject:{"+item.getSubject()+"}\r\n object:{"+item.getObject()+"}"
479 //+ CR + "relation-record: {"+item+"}"
484 return sb.toString();
487 /** Performs substitution for ${itemCSID} (see CommonAPI.AuthorityItemCSID_REPLACE for constant)
488 * and sets URI correctly for related items.
489 * Operates directly on the items in the list. Does not change the list ordering, does not add or remove any items.
491 protected void fixupInboundListItems(ServiceContext ctx,
492 List<RelationsCommonList.RelationListItem> inboundList,
493 DocumentModel docModel,
494 String itemCSID) throws Exception {
495 String thisURI = this.getUri(docModel);
496 // WARNING: the two code blocks below are almost identical and seem to ask to be put in a generic method.
497 // beware of the little diffs in inboundItem.setObjectCsid(itemCSID); and inboundItem.setSubjectCsid(itemCSID); in the two blocks.
498 for (RelationsCommonList.RelationListItem inboundItem : inboundList) {
499 RelationsDocListItem inboundItemObject = inboundItem.getObject();
500 RelationsDocListItem inboundItemSubject = inboundItem.getSubject();
502 if (inboundItemObject.getCsid().equalsIgnoreCase(CommonAPI.AuthorityItemCSID_REPLACE)){
503 inboundItem.setObjectCsid(itemCSID);
504 inboundItemObject.setCsid(itemCSID);
505 inboundItemObject.setUri(getUri(docModel));
507 String objectCsid = inboundItemObject.getCsid();
508 DocumentModel itemDocModel = NuxeoUtils.getDocFromCsid(getRepositorySession(), ctx, objectCsid); //null if not found.
509 DocumentWrapper wrapper = new DocumentWrapperImpl(itemDocModel);
510 String uri = this.getRepositoryClient(ctx).getDocURI(wrapper);
511 inboundItemObject.setUri(uri); //CSPACE-4037
513 uriPointsToSameAuthority(thisURI, inboundItemObject.getUri()); //CSPACE-4042
515 if (inboundItemSubject.getCsid().equalsIgnoreCase(CommonAPI.AuthorityItemCSID_REPLACE)){
516 inboundItem.setSubjectCsid(itemCSID);
517 inboundItemSubject.setCsid(itemCSID);
518 inboundItemSubject.setUri(getUri(docModel));
520 String subjectCsid =inboundItemSubject.getCsid();
521 DocumentModel itemDocModel = NuxeoUtils.getDocFromCsid(getRepositorySession(), ctx, subjectCsid); //null if not found.
522 DocumentWrapper wrapper = new DocumentWrapperImpl(itemDocModel);
523 String uri = this.getRepositoryClient(ctx).getDocURI(wrapper);
524 inboundItemSubject.setUri(uri); //CSPACE-4037
526 uriPointsToSameAuthority(thisURI, inboundItemSubject.getUri()); //CSPACE-4042
531 public RepositoryClient getRepositoryClient(ServiceContext ctx) {
532 RepositoryClient repositoryClient = RepositoryClientFactory.getInstance().getClient(ctx.getRepositoryClientName());
533 return repositoryClient;
536 // this method calls the RelationResource to have it create the relations and persist them.
537 private void createRelations(List<RelationsCommonList.RelationListItem> inboundList, ServiceContext ctx){
538 for (RelationsCommonList.RelationListItem item : inboundList) {
539 RelationsCommon rc = new RelationsCommon();
540 //rc.setCsid(item.getCsid());
541 //todo: assignTo(item, rc);
542 RelationsDocListItem itemSubject = item.getSubject();
543 RelationsDocListItem itemObject = item.getObject();
545 String subjectCsid = itemSubject.getCsid();
546 rc.setDocumentId1(subjectCsid);
547 rc.setSubjectCsid(subjectCsid);
549 String objCsid = item.getObject().getCsid();
550 rc.setDocumentId2(objCsid);
551 rc.setObjectCsid(objCsid);
553 rc.setRelationshipType(item.getPredicate());
554 //RelationshipType foo = (RelationshipType.valueOf(item.getPredicate())) ;
555 //rc.setPredicate(foo); //this must be one of the type found in the enum in services/jaxb/src/main/resources/relations_common.xsd
557 rc.setDocumentType1(itemSubject.getDocumentType());
558 rc.setDocumentType2(itemObject.getDocumentType());
560 rc.setSubjectUri(itemSubject.getUri());
561 rc.setObjectUri(itemObject.getUri());
564 PoxPayloadOut payloadOut = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME);
565 PayloadOutputPart outputPart = new PayloadOutputPart(RelationClient.SERVICE_COMMONPART_NAME, rc);
566 payloadOut.addPart(outputPart);
567 //System.out.println("\r\n==== TO CREATE: "+rc.getDocumentId1()+"==>"+rc.getPredicate()+"==>"+rc.getDocumentId2());
568 RelationResource relationResource = new RelationResource();
569 Object res = relationResource.create(ctx.getUriInfo(), payloadOut.toXML()); //NOTE ui recycled from above to pass in unknown query params.
572 private void deleteRelations(List<RelationsCommonList.RelationListItem> list,ServiceContext ctx, String listName){
574 //if (list.size()>0){ logger.info("==== deleteRelations from : "+listName); }
575 for (RelationsCommonList.RelationListItem item : list) {
576 RelationResource relationResource = new RelationResource();
577 //logger.info("==== TO DELETE: " + item.getCsid() + ": " + item.getSubject().getCsid() + "--" + item.getPredicate() + "-->" + item.getObject().getCsid());
578 Object res = relationResource.delete(item.getCsid());
580 } catch (Throwable t){
581 String msg = "Unable to deleteRelations: "+ Tools.errorToString(t, true);
586 private List<RelationsCommonList.RelationListItem> newList(){
587 List<RelationsCommonList.RelationListItem> result = new ArrayList<RelationsCommonList.RelationListItem>();
590 protected List<RelationsCommonList.RelationListItem> cloneList(List<RelationsCommonList.RelationListItem> inboundList){
591 List<RelationsCommonList.RelationListItem> result = newList();
592 for (RelationsCommonList.RelationListItem item: inboundList){
597 private RelationsCommonList.RelationListItem findInList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
598 for (RelationsCommonList.RelationListItem listItem : list) {
599 if (itemsEqual(listItem, item)){ //equals must be defined, else
606 private boolean itemsEqual(RelationsCommonList.RelationListItem item, RelationsCommonList.RelationListItem item2){
607 if (item==null || item2==null){
610 RelationsDocListItem subj1 = item.getSubject();
611 RelationsDocListItem subj2 = item2.getSubject();
612 RelationsDocListItem obj1 = item.getObject();
613 RelationsDocListItem obj2 = item2.getObject();
615 return (subj1.getCsid().equals(subj2.getCsid()))
616 && (obj1.getCsid().equals(obj1.getCsid()))
617 && ( (item.getPredicate().equals(item2.getPredicate()))
618 && (item.getRelationshipType().equals(item2.getRelationshipType())) )
619 && (obj1.getDocumentType().equals(obj2.getDocumentType()))
620 && (subj1.getDocumentType().equals(subj2.getDocumentType())) ;
623 private void removeFromList(List<RelationsCommonList.RelationListItem> list, RelationsCommonList.RelationListItem item){
627 /* don't even THINK of re-using this method.
628 * String example_uri = "/locationauthorities/7ec60f01-84ab-4908-9a6a/items/a5466530-713f-43b4-bc05";
630 private String extractInAuthorityCSID(String uri){
631 String IN_AUTHORITY_REGEX = "/(.*?)/(.*?)/(.*)";
632 Pattern p = Pattern.compile(IN_AUTHORITY_REGEX);
633 Matcher m = p.matcher(uri);
635 if (m.groupCount()<3){
636 logger.warn("REGEX-WRONG-GROUPCOUNT looking in "+uri);
639 //String service = m.group(1);
640 String inauth = m.group(2);
641 //String theRest = m.group(3);
643 //print("service:"+service+", inauth:"+inauth+", rest:"+rest);
646 logger.warn("REGEX-NOT-MATCHED looking in "+uri);
651 //ensures CSPACE-4042
652 protected void uriPointsToSameAuthority(String thisURI, String inboundItemURI) throws Exception {
653 String authorityCSID = extractInAuthorityCSID(thisURI);
654 String authorityCSIDForInbound = extractInAuthorityCSID(inboundItemURI);
655 if ( Tools.isBlank(authorityCSID)
656 || Tools.isBlank(authorityCSIDForInbound)
657 || ( ! authorityCSID.equalsIgnoreCase(authorityCSIDForInbound) )
659 throw new Exception("Item URI "+thisURI+" must point to same authority as related item: "+inboundItemURI);
663 //================= TODO: move this to common, refactoring this and CollectionObjectResource.java
664 public RelationsCommonList getRelations(String subjectCSID, String objectCSID, String predicate) throws Exception {
665 ServiceContext ctx = getServiceContext();
666 MultivaluedMap queryParams = ctx.getQueryParams();
667 queryParams.putSingle(IRelationsManager.PREDICATE_QP, predicate);
668 queryParams.putSingle(IRelationsManager.SUBJECT_QP, subjectCSID);
669 queryParams.putSingle(IRelationsManager.OBJECT_QP, objectCSID);
671 RelationResource relationResource = new RelationResource();
672 RelationsCommonList relationsCommonList = relationResource.getList(ctx.getUriInfo());
673 return relationsCommonList;
675 //============================= END TODO refactor ==========================