From 564728f24d5354bd2bcdc11863b72b2ab1018792 Mon Sep 17 00:00:00 2001 From: Laramie Crocker Date: Wed, 25 May 2011 21:54:14 +0000 Subject: [PATCH] CSPACE-4045 merging changes from branch 1.7 to trunk, preserving previous trunk commits for getAuthorityServicePath() and getUri() in AuthorityItemDocumentModelHandler. This fix ensures that create or update to hierarchic authorities cleans up old parent relationships for related child items. Effectively, an item in a hierarchy can not have two parents. --- .../AuthorityItemDocumentModelHandler.java | 73 +++++++++++++++++-- .../services/common/api/Tools.java | 31 +++++++- .../AbstractCollectionSpaceResourceImpl.java | 23 +----- .../nuxeo/RelationDocumentModelHandler.java | 14 ++-- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java b/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java index 1dd57f0a2..df55d4d91 100644 --- a/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java +++ b/services/authority/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java @@ -278,6 +278,9 @@ public abstract class AuthorityItemDocumentModelHandler RelationsCommonList parentListOuter = getRelations(thisCSID, null, predicate); List parentList = parentListOuter.getRelationListItem(); if (parentList != null) { + if (parentList.size()==0){ + return null; + } RelationsCommonList.RelationListItem relationListItem = parentList.get(0); parentCSID = relationListItem.getObjectCsid(); } @@ -443,6 +446,10 @@ public abstract class AuthorityItemDocumentModelHandler List childList = childListOuter.getRelationListItem(); List parentList = parentListOuter.getRelationListItem(); + if (parentList.size()>1){ + throw new Exception("Too many parents for object: "+itemCSID+" list: "+dumpList(parentList, "parentList")); + } + DocumentModel docModel = wrapDoc.getWrappedObject(); //Do magic replacement of ${itemCSID} and fix URI's. @@ -450,15 +457,17 @@ public abstract class AuthorityItemDocumentModelHandler for (RelationsCommonList.RelationListItem inboundItem : inboundList) { if (inboundItem.getObject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) { - //then this is an item that says we have a child. + //then this is an item that says we have a child. That child is inboundItem RelationsCommonList.RelationListItem childItem = findInList(childList, inboundItem); if (childItem != null){ removeFromList(childList, childItem); //exists, just take it off delete list } else { actionList.add(inboundItem); //doesn't exist as a child, but is a child. Add to additions list } + ensureChildHasNoOtherParents(ctx, queryParams, inboundItem.getSubject().getCsid()); + } else if (inboundItem.getSubject().getCsid().equals(itemCSID) && inboundItem.getPredicate().equals(HAS_BROADER)) { - //then this is an item that says we have a parent + //then this is an item that says we have a parent. inboundItem is that parent. RelationsCommonList.RelationListItem parentItem = findInList(parentList, inboundItem); if (parentItem != null){ removeFromList(parentList, parentItem); //exists, just take it off delete list @@ -470,14 +479,61 @@ public abstract class AuthorityItemDocumentModelHandler //not dealing with: hasNarrower or any other predicate. } } - deleteRelations(parentList, ctx); //todo: there are items appearing on both lists....april 20. - deleteRelations(childList, ctx); + String dump = dumpLists(itemCSID, parentList, childList, actionList); + //System.out.println("====dump====="+CR+dump); + logger.info("~~~~~~~~~~~~~~~~~~~~~~dump~~~~~~~~~~~~~~~~~~~~~~~~"+CR+ dump); + deleteRelations(parentList, ctx, "parentList"); //todo: there are items appearing on both lists....april 20. + deleteRelations(childList, ctx, "childList"); createRelations(actionList, ctx); //We return all elements on the inbound list, since we have just worked to make them exist in the system // and be non-redundant, etc. That list came from relationsCommonListBody, so it is still attached to it, just pass that back. return relationsCommonListBody; } + private void ensureChildHasNoOtherParents(ServiceContext ctx, MultivaluedMap queryParams, String childCSID){ + queryParams.putSingle(IRelationsManager.SUBJECT_QP, childCSID); + queryParams.putSingle(IRelationsManager.PREDICATE_QP, RelationshipType.HAS_BROADER.value()); + queryParams.putSingle(IRelationsManager.OBJECT_QP, null); //null means ANY + RelationsCommonList parentListOuter = (new RelationResource()).getList(ctx.getUriInfo()); + List parentList = parentListOuter.getRelationListItem(); + //logger.warn("ensureChildHasNoOtherParents preparing to delete relations on "+childCSID+"\'s parent list: \r\n"+dumpList(parentList, "duplicate parent list")); + deleteRelations(parentList, ctx, "parentList-delete"); + } + + private String dumpLists(String itemCSID, + List parentList, + List childList, + List actionList){ + StringBuffer sb = new StringBuffer(); + sb.append("itemCSID: "+itemCSID+CR); + sb.append(dumpList(parentList, "parentList")); + sb.append(dumpList(childList, "childList")); + sb.append(dumpList(actionList, "actionList")); + return sb.toString(); + } + + private final static String CR="\r\n"; + private final static String T = " "; + + private String dumpList(List list, String label){ + StringBuffer sb = new StringBuffer(); + String s; + if (list.size()>0) sb.append("=========== "+label+" =========="+CR); + for (RelationsCommonList.RelationListItem item : list) { + s = + T + item.getSubject().getCsid() //+T4 + item.getSubject().getUri() + + T + item.getPredicate() + + T + item.getObject().getCsid() //+T4 + item.getObject().getUri() + + CR + //+"subject:{"+item.getSubject()+"}\r\n object:{"+item.getObject()+"}" + //+ CR + "relation-record: {"+item+"}" + ; + sb.append(s); + + } + return sb.toString(); + } + /** Performs substitution for ${itemCSID} (see CommonAPI.AuthorityItemCSID_REPLACE for constant) * and sets URI correctly for related items. * Operates directly on the items in the list. Does not change the list ordering, does not add or remove any items. @@ -563,12 +619,13 @@ public abstract class AuthorityItemDocumentModelHandler Object res = relationResource.create(ctx.getUriInfo(), payloadOut.toXML()); //NOTE ui recycled from above to pass in unknown query params. } } - private void deleteRelations(List list,ServiceContext ctx){ + private void deleteRelations(List list,ServiceContext ctx, String listName){ try { - for (RelationsCommonList.RelationListItem inboundItem : list) { + //if (list.size()>0){ logger.info("==== deleteRelations from : "+listName); } + for (RelationsCommonList.RelationListItem item : list) { RelationResource relationResource = new RelationResource(); - //System.out.println("\r\n==== TO DELETE: "+inboundItem.getCsid()); - Object res = relationResource.delete(inboundItem.getCsid()); + //logger.info("==== TO DELETE: " + item.getCsid() + ": " + item.getSubject().getCsid() + "--" + item.getPredicate() + "-->" + item.getObject().getCsid()); + Object res = relationResource.delete(item.getCsid()); } } catch (Throwable t){ String msg = "Unable to deleteRelations: "+ Tools.errorToString(t, true); diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java index 4cf7875e7..dff7526a1 100755 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/Tools.java @@ -148,6 +148,12 @@ public class Tools { } public static String getStackTrace(Throwable e){ + return getStackTrace(e, -1); + } + + + /** @param includeLines if zero, returns all lines */ + public static String getStackTrace(Throwable e, int includeLines){ if (e==null){ return ""; } @@ -160,14 +166,33 @@ public class Tools { else System.out.println("bos was null, not closing"); } catch (Exception e2) {System.out.println("ERROR: couldn't reset() bos in Tools "+e2);} - return result; + if (includeLines == 0){ + return result; //return all. + } + StringBuffer sb = new StringBuffer(); + int i = 0; + String[] foo = result.split("\n"); + for (String line: foo){ + i++; + if (i>includeLines){ + sb.append(" ...first "+i+" lines. "+(foo.length-i)+" more.\r\n"); + return sb.toString(); + } + sb.append(line).append("\r\n"); + } + return sb.toString(); + } + + public static String errorToString(Throwable e, boolean stackTraceOnException){ + return errorToString(e, stackTraceOnException, 0); } /** Takes an Exception object and formats a message that provides more debug information * suitable for developers for printing to System.out or for logging. Not suitable for * presentation of error messages to clients. + * @param includeLines if zero, return all lines of stack trace, otherwise return number of lines from top. */ - public static String errorToString(Throwable e, boolean stackTraceOnException){ + public static String errorToString(Throwable e, boolean stackTraceOnException, int includeLines){ if (e==null){ return ""; } @@ -182,7 +207,7 @@ public class Tools { if (causeBuffer.length()>0) s = s + "\r\n -- Causes: "+causeBuffer.toString(); - s = s + "\r\n -- Stack Trace: \r\n -- " + getStackTrace(e); + s = s + "\r\n -- Stack Trace: \r\n -- " + getStackTrace(e, includeLines); return s; } diff --git a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java index 3ed87f85e..98be84586 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java @@ -369,23 +369,9 @@ public abstract class AbstractCollectionSpaceResourceImpl if (logger.isDebugEnabled()) { logger.debug(getClass().getName(), e); } - /* ===== how RoleResource does it: ======= - } catch (BadRequestException bre) { - response = Response.status( - Response.Status.BAD_REQUEST).entity(ServiceMessages.POST_FAILED - + bre.getErrorReason()).type("text/plain").build(); - throw new WebApplicationException(response); - } catch (DocumentException bre) { - response = Response.status( - Response.Status.BAD_REQUEST).entity(ServiceMessages.POST_FAILED - + bre.getErrorReason()).type("text/plain").build(); - throw new WebApplicationException(response); - } catch (UnauthorizedException ue) { - response = Response.status( - Response.Status.UNAUTHORIZED).entity(ServiceMessages.POST_FAILED - + ue.getErrorReason()).type("text/plain").build(); - throw new WebApplicationException(response); - */ + String detail = Tools.errorToString(e, true); + String detailNoTrace = Tools.errorToString(e, true, 3); + logger.error(getClass().getName()+" detail: "+detailNoTrace, e); if (e instanceof UnauthorizedException) { response = Response.status(Response.Status.UNAUTHORIZED).entity(serviceMsg + e.getMessage()).type("text/plain").build(); @@ -415,8 +401,7 @@ public abstract class AbstractCollectionSpaceResourceImpl return (WebApplicationException) e; } else { // e is now instanceof Exception - String detail = Tools.errorToString(e, true); - response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(serviceMsg + " detail: " + detail).type("text/plain").build(); + response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(serviceMsg + " detail: " + detailNoTrace).type("text/plain").build(); return new WebApplicationException(response); } } diff --git a/services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationDocumentModelHandler.java b/services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationDocumentModelHandler.java index 17c269575..cdc141d80 100644 --- a/services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationDocumentModelHandler.java +++ b/services/relation/service/src/main/java/org/collectionspace/services/relation/nuxeo/RelationDocumentModelHandler.java @@ -222,10 +222,10 @@ public class RelationDocumentModelHandler propName = ServiceBindingUtils.getPropertyValue(itemSbt, ServiceBindingUtils.OBJ_NAME_PROP); String itemDocname = ServiceBindingUtils.getMappedFieldInDoc(itemSbt, ServiceBindingUtils.OBJ_NAME_PROP, itemDocModel); if (propName==null || itemDocname==null){ - System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType); + //System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType); } else{ item.setName(itemDocname); - System.out.println("=== found prop : "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType); + //System.out.println("=== found prop : "+ServiceBindingUtils.OBJ_NAME_PROP+"::"+propName+"="+itemDocname+" documentType: "+documentType); } } catch (Throwable t){ System.out.println("====Error finding objectNameProperty: "+itemDocModel+" field "+ServiceBindingUtils.OBJ_NAME_PROP+"="+propName @@ -237,15 +237,15 @@ public class RelationDocumentModelHandler String itemDocnumber = ServiceBindingUtils.getMappedFieldInDoc(itemSbt, ServiceBindingUtils.OBJ_NUMBER_PROP, itemDocModel); if (propName==null || itemDocnumber==null){ - System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber - +" documentType: "+documentType); + //System.out.println("=== prop NOT found: "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber + // +" documentType: "+documentType); } else { item.setNumber(itemDocnumber); - System.out.println("============ found prop : "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber - +" documentType: "+documentType); + //System.out.println("============ found prop : "+ServiceBindingUtils.OBJ_NUMBER_PROP+"::"+propName+"="+itemDocnumber + // +" documentType: "+documentType); } } catch (Throwable t){ - System.out.println("====Error finding objectNumberProperty: "+ServiceBindingUtils.OBJ_NUMBER_PROP+"="+propName + logger.error("====Error finding objectNumberProperty: "+ServiceBindingUtils.OBJ_NUMBER_PROP+"="+propName +" not found in itemDocType: "+itemDocType+" inner: "+t.getMessage()); } } else { -- 2.47.3