]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6937-A: Support for SAS item field and starting to add support for sync'ing...
authorremillet <remillet@yahoo.com>
Sat, 23 Apr 2016 04:50:28 +0000 (21:50 -0700)
committerremillet <remillet@yahoo.com>
Sat, 23 Apr 2016 04:50:28 +0000 (21:50 -0700)
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityServiceUtils.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java
services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java

index 51a12e20abb9b797b06ee2b002164337e38a9e5d..fe8bb78b6178316212794cc52904cf6a3e615fb3 100644 (file)
@@ -218,7 +218,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
 
        protected String lookupParentCSID(String parentspecifier, String method,
                        String op, UriInfo uriInfo) throws Exception {
-               CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(null,
+               CsidAndShortIdentifier tempResult = lookupParentCSIDAndShortIdentifer(NULL_CONTEXT,
                                parentspecifier, method, op, uriInfo);
                return tempResult.CSID;
        }
@@ -592,13 +592,14 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
      * @param ctx
      * @param parentspecifier          - ID of the container. Can be URN or CSID form
      * @param shouldUpdateRevNumber - Indicates if the revision number should be updated on create -won't do this when synching with SAS
-     * @param proposed                         - In a shared authority context, indicates if this item just a proposed item and not yet part of the SAS authority
+     * @param isProposed                               - In a shared authority context, indicates if this item just a proposed item and not yet part of the SAS authority
      * @return
      * @throws Exception
      */
     protected Response createAuthorityItem(ServiceContext ctx, String parentIdentifier,
                boolean shouldUpdateRevNumber,
-               boolean proposed) throws Exception {
+               boolean isProposed,
+               boolean isSasItem) throws Exception {
        Response result = null;
        
         // Note: must have the parentShortId, to do the create.
@@ -606,7 +607,8 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
         AuthorityItemDocumentModelHandler handler = 
                (AuthorityItemDocumentModelHandler) createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
         handler.setShouldUpdateRevNumber(shouldUpdateRevNumber);
-        handler.setIsProposed(proposed);
+        handler.setIsProposed(isProposed);
+        handler.setIsSASItem(isSasItem);
         // Make the client call
         String itemcsid = getRepositoryClient(ctx).create(ctx, handler);
         
@@ -630,7 +632,8 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
                String parentIdentifier,
                PoxPayloadIn input,
                boolean shouldUpdateRevNumber,
-               boolean isProposed) throws Exception {
+               boolean isProposed,
+               boolean isSASItem) throws Exception {
        Response result = null;
        
         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input,
@@ -638,7 +641,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
         if (parentCtx.getCurrentRepositorySession() != null) {
                ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession());
         }
-        result = this.createAuthorityItem(ctx, parentIdentifier, shouldUpdateRevNumber, isProposed);
+        result = this.createAuthorityItem(ctx, parentIdentifier, shouldUpdateRevNumber, isProposed, isSASItem);
 
        return result;
     }
@@ -661,7 +664,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             PoxPayloadIn input = new PoxPayloadIn(xmlPayload);
             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), input, resourceMap, uriInfo);
             result = this.createAuthorityItem(ctx, parentIdentifier, AuthorityServiceUtils.UPDATE_REV,
-                       AuthorityServiceUtils.PROPOSED);
+                       AuthorityServiceUtils.PROPOSED, AuthorityServiceUtils.NOT_SAS_ITEM);
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
         }
@@ -888,56 +891,56 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
      * Gets the authorityItem list for the specified authority
      * If partialPerm is specified, keywords will be ignored.
      * 
-     * @param specifier either a CSID or one of the urn forms
+     * @param authorityIdentifier either a CSID or one of the urn forms
      * @param partialTerm if non-null, matches partial terms
      * @param keywords if non-null, matches terms in the keyword index for items
      * @param ui passed to include additional parameters, like pagination controls
      *
      */
     public AbstractCommonList getAuthorityItemList(ServiceContext existingContext,
-               String specifier,
+               String authorityIdentifier,
             UriInfo uriInfo) throws Exception {
        AbstractCommonList result = null;
        
-            ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
-            MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
+        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
+        MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
         if (existingContext != null && existingContext.getCurrentRepositorySession() != null) { // Merge some of the existing context properties with our new context
                ctx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());
                ctx.setProperties(existingContext.getProperties());
         }
             
-            String orderBy = queryParams.getFirst(IClientQueryParams.ORDER_BY_PARAM);
-            String termStatus = queryParams.getFirst(SEARCH_TYPE_TERMSTATUS);
-            String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
-            String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
-            String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
+        String orderBy = queryParams.getFirst(IClientQueryParams.ORDER_BY_PARAM);
+        String termStatus = queryParams.getFirst(SEARCH_TYPE_TERMSTATUS);
+        String keywords = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_KW);
+        String advancedSearch = queryParams.getFirst(IQueryManager.SEARCH_TYPE_KEYWORDS_AS);
+        String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
 
-            // For the wildcard case, parentcsid is null, but docHandler will deal with this.
-            // We omit the parentShortId, only needed when doing a create...
-            String parentcsid = PARENT_WILDCARD.equals(specifier) ? null :
-                               lookupParentCSID(specifier, "getAuthorityItemList", "LIST", uriInfo);
-            DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler =
-               createItemDocumentHandler(ctx, parentcsid, null);
-            
-            DocumentFilter myFilter = handler.getDocumentFilter();
-            // If we are not wildcarding the parent, add a restriction
-            if (parentcsid != null) {
-                   myFilter.appendWhereClause(authorityItemCommonSchemaName + ":"
-                           + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
-                           + "'" + parentcsid + "'",
-                           IQueryManager.SEARCH_QUALIFIER_AND);
-            }
+        // For the wildcard case, parentcsid is null, but docHandler will deal with this.
+        // We omit the parentShortId, only needed when doing a create...
+        String parentcsid = PARENT_WILDCARD.equals(authorityIdentifier) ? null :
+                       lookupParentCSID(ctx, authorityIdentifier, "getAuthorityItemList", "LIST", uriInfo);
+        DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler =
+               createItemDocumentHandler(ctx, parentcsid, null);
+        
+        DocumentFilter myFilter = handler.getDocumentFilter();
+        // If we are not wildcarding the parent, add a restriction
+        if (parentcsid != null) {
+            myFilter.appendWhereClause(authorityItemCommonSchemaName + ":"
+                    + AuthorityItemJAXBSchema.IN_AUTHORITY + "="
+                    + "'" + parentcsid + "'",
+                    IQueryManager.SEARCH_QUALIFIER_AND);
+        }
 
-            if (Tools.notBlank(termStatus)) {
-               // Start with the qualified termStatus field
-               String qualifiedTermStatusField = authorityItemCommonSchemaName + ":"
-                        + AuthorityItemJAXBSchema.TERM_STATUS;
-               String[] filterTerms = termStatus.trim().split("\\|");
-               String tsClause = QueryManager.createWhereClauseToFilterFromStringList(qualifiedTermStatusField, filterTerms, IQueryManager.FILTER_EXCLUDE);
-                myFilter.appendWhereClause(tsClause, IQueryManager.SEARCH_QUALIFIER_AND);
-            }
+        if (Tools.notBlank(termStatus)) {
+               // Start with the qualified termStatus field
+               String qualifiedTermStatusField = authorityItemCommonSchemaName + ":"
+                    + AuthorityItemJAXBSchema.TERM_STATUS;
+               String[] filterTerms = termStatus.trim().split("\\|");
+               String tsClause = QueryManager.createWhereClauseToFilterFromStringList(qualifiedTermStatusField, filterTerms, IQueryManager.FILTER_EXCLUDE);
+            myFilter.appendWhereClause(tsClause, IQueryManager.SEARCH_QUALIFIER_AND);
+        }
 
-            result = search(ctx, handler, uriInfo, orderBy, keywords, advancedSearch, partialTerm);            
+        result = search(ctx, handler, uriInfo, orderBy, keywords, advancedSearch, partialTerm);            
        
        return result;
     }
@@ -946,7 +949,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
      * Gets the authorityItem list for the specified authority
      * If partialPerm is specified, keywords will be ignored.
      * 
-     * @param specifier either a CSID or one of the urn forms
+     * @param authorityIdentifier either a CSID or one of the urn forms
      * @param partialTerm if non-null, matches partial terms
      * @param keywords if non-null, matches terms in the keyword index for items
      * @param ui passed to include additional parameters, like pagination controls
@@ -956,12 +959,12 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
     @GET
     @Path("{csid}/items")
     @Produces("application/xml")
-    public AbstractCommonList getAuthorityItemList(@PathParam("csid") String specifier,
+    public AbstractCommonList getAuthorityItemList(@PathParam("csid") String authorityIdentifier,
             @Context UriInfo uriInfo) {
        AbstractCommonList result = null;
        
         try {
-            result = getAuthorityItemList(NULL_CONTEXT, specifier, uriInfo);    
+            result = getAuthorityItemList(NULL_CONTEXT, authorityIdentifier, uriInfo);    
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.LIST_FAILED);
         }
@@ -1032,7 +1035,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
                ctx.setProperties(existingContext.getProperties());
         }
 
-        String parentcsid = lookupParentCSID(parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", uriInfo);
+        String parentcsid = lookupParentCSID(ctx, parentspecifier, "getReferencingObjects(parent)", "GET_ITEM_REF_OBJS", uriInfo);
         String itemcsid = lookupItemCSID(ctx, itemspecifier, parentcsid, "getReferencingObjects(item)", "GET_ITEM_REF_OBJS");
 
         List<String> serviceTypes = queryParams.remove(ServiceBindingUtils.SERVICE_TYPE_PROP);
@@ -1063,6 +1066,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             @PathParam("itemcsid") String itemspecifier,
             @Context UriInfo uriInfo) {
         AuthorityRefList authRefList = null;
+        
         try {
             // Note that we have to create the service context for the Items, not the main service
             ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), uriInfo);
@@ -1079,6 +1083,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.GET_FAILED + " parentspecifier: " + parentspecifier + " itemspecifier:" + itemspecifier);
         }
+        
         return authRefList;
     }
     
@@ -1101,6 +1106,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
        CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(ctx, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null);
         AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier);
         handler.setIsProposed(AuthorityServiceUtils.NOT_PROPOSED); // In case it was formally locally proposed, clear the proposed flag
+        handler.setIsSASItem(AuthorityServiceUtils.SAS_ITEM); // Since we're sync'ing, this is now a SAS controlled item
         // Create an authority item specifier
         Specifier parentSpecifier = Specifier.getSpecifier(parent.CSID, "getAuthority", "GET");
         Specifier itemSpecifier = Specifier.getSpecifier(itemIdentifier, "getAuthorityItem", "GET");
@@ -1207,7 +1213,8 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             PoxPayloadIn theUpdate = new PoxPayloadIn(xmlPayload);
             result = updateAuthorityItem(null, resourceMap, uriInfo, parentSpecifier, itemSpecifier, theUpdate,
                        AuthorityServiceUtils.UPDATE_REV,                       // passing TRUE so rev num increases, passing
-                       AuthorityServiceUtils.NO_CHANGE);       // don't change the state of the "proposed" field -we could be performing a sync or just a plain update
+                       AuthorityServiceUtils.NO_CHANGE,        // don't change the state of the "proposed" field -we could be performing a sync or just a plain update
+                       AuthorityServiceUtils.NO_CHANGE);       // don't change the state of the "sas" field -we could be performing a sync or just a plain update
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.UPDATE_FAILED);
         }
@@ -1223,7 +1230,9 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
             String itemspecifier,
             PoxPayloadIn theUpdate,
             boolean shouldUpdateRevNumber,
-            Boolean isProposed) throws Exception {
+            Boolean isProposed,
+            Boolean isSASItem
+            ) throws Exception {
         PoxPayloadOut result = null;
         
         CsidAndShortIdentifier csidAndShortId = lookupParentCSIDAndShortIdentifer(itemServiceCtx, parentspecifier, "updateAuthorityItem(parent)", "UPDATE_ITEM", null);
@@ -1247,6 +1256,9 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
         if (isProposed != null) {
                handler.setIsProposed(isProposed);
         }
+        if (isSASItem != null) {
+               handler.setIsSASItem(isSASItem);
+        }
         getRepositoryClient(ctx).update(ctx, itemcsid, handler);
         result = ctx.getOutput();
 
@@ -1277,7 +1289,7 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
         
         try {
             ServiceContext ctx = createServiceContext(getItemServiceName(), uriInfo);
-            deleteAuthorityItem(ctx, parentIdentifier, itemIdentifier);
+            deleteAuthorityItem(ctx, parentIdentifier, itemIdentifier, AuthorityServiceUtils.UPDATE_REV);
             result = Response.status(HttpResponseCodes.SC_OK).build();
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.DELETE_FAILED + "  itemcsid: " + itemIdentifier + " parentcsid:" + parentIdentifier);
@@ -1295,19 +1307,23 @@ public abstract class AuthorityResource<AuthCommon, AuthItemHandler>
      */
     public void deleteAuthorityItem(ServiceContext existingCtx,
             String parentIdentifier,
-            String itemIdentifier) throws Exception {
+            String itemIdentifier,
+            boolean shouldUpdateRevNumber
+            ) throws Exception {
        Response result = null;
        
         ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), existingCtx.getUriInfo());
-        String parentcsid = lookupParentCSID(ctx, parentIdentifier, "deleteAuthorityItem(parent)", "DELETE_ITEM", null);
-        String itemCsid = lookupItemCSID(ctx, itemIdentifier, parentcsid, "deleteAuthorityItem(item)", "DELETE_ITEM"); //use itemServiceCtx if it is not null
-
-        if (existingCtx != null && existingCtx.getCurrentRepositorySession() != null) {
-               ctx.setCurrentRepositorySession(existingCtx.getCurrentRepositorySession()); // Use existing repo session if one exists
+        if (existingCtx != null) {
+               ctx.setCurrentRepositorySession(existingCtx.getCurrentRepositorySession());
                ctx.setProperties(existingCtx.getProperties());
         }
         
+        String parentcsid = lookupParentCSID(ctx, parentIdentifier, "deleteAuthorityItem(parent)", "DELETE_ITEM", null);
+        String itemCsid = lookupItemCSID(ctx, itemIdentifier, parentcsid, "deleteAuthorityItem(item)", "DELETE_ITEM"); //use itemServiceCtx if it is not null
+        
         DocumentHandler<?, AbstractCommonList, DocumentModel, DocumentModelList> handler = createDocumentHandler(ctx);
+               ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, shouldUpdateRevNumber);  // Sometimes we can only soft-delete, so if it is during a sync we dont' update the revision number
+
         getRepositoryClient(ctx).delete(ctx, itemCsid, handler);
     }
 
index 1cdec5731d393d8c55fc673248d8187ea35f8d29..498e979080865da7c898250df99a3c550d3092ab 100644 (file)
@@ -12,6 +12,7 @@ import org.collectionspace.services.common.context.MultipartServiceContextImpl;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
 import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityIdentifierUtils;
 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
@@ -37,6 +38,9 @@ public class AuthorityServiceUtils {
     public static final String IS_PROPOSED_PROPERTY = "IS_PROPOSED";
     public static final Boolean PROPOSED = true;
     public static final Boolean NOT_PROPOSED = !PROPOSED;
+    public static final Boolean SAS_ITEM = true;
+    public static final Boolean NOT_SAS_ITEM = !SAS_ITEM;
+
     public static final Boolean NO_CHANGE = null;
 
     static public PoxPayloadIn requestPayloadIn(ServiceContext ctx, Specifier specifier, Class responseType) throws Exception {
@@ -137,14 +141,15 @@ public class AuthorityServiceUtils {
      * @param itemInfo
      * @throws Exception
      */
-    static public boolean markAuthorityItemAsDeprecated(ServiceContext ctx, String authorityItemCommonSchemaName, String itemCsid) throws Exception {
+    static public boolean markAuthorityItemAsDeprecated(ServiceContext ctx, String authorityItemCommonSchemaName, AuthorityItemSpecifier authorityItemSpecifier) throws Exception {
        boolean result = false;
        
        try {
-               DocumentModel docModel = NuxeoUtils.getDocFromCsid(ctx, (CoreSessionInterface)ctx.getCurrentRepositorySession(), itemCsid);
+               DocumentModel docModel = NuxeoUtils.getDocFromSpecifier(ctx, (CoreSessionInterface)ctx.getCurrentRepositorySession(),
+                               authorityItemCommonSchemaName, authorityItemSpecifier);
                result = setAuthorityItemDeprecated(ctx, docModel, authorityItemCommonSchemaName, AuthorityServiceUtils.DEPRECATED);
        } catch (Exception e) {
-               logger.warn(String.format("Could not mark item '%s' as deprecated.", itemCsid), e);
+               logger.warn(String.format("Could not mark item '%s' as deprecated.", authorityItemSpecifier.getItemSpecifier().getURNValue()), e);
                throw e;
        }
        
index c2a89e7402f02b3463ae251871bb97ac431b2e97..e9d2427df1209d0f75913774bbc895cff5e83b74 100644 (file)
@@ -184,8 +184,8 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
         List<Element> itemList = getItemList(sasPayloadInItemList);
         if (itemList != null) {
                for (Element e:itemList) {
-                       String remoteRefName = XmlTools.getElementValue(e, "refName");
-                       itemsInRemoteAuthority.add(remoteRefName);
+                       String remoteRefName = XmlTools.getElementValue(e, AuthorityItemJAXBSchema.REF_NAME);
+                       itemsInRemoteAuthority.add(XmlTools.getElementValue(e, AuthorityItemJAXBSchema.SHORT_IDENTIFIER));
                        long status = syncRemoteItemWithLocalItem(ctx, remoteRefName);
                        if (status == 1) {
                                created++;
@@ -203,8 +203,9 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
         // of the remote items have been hard deleted.
         //
        ArrayList<String> itemsInLocalAuthority = getItemsInLocalAuthority(ctx, sasAuthoritySpecifier);
-       if (itemsInLocalAuthority.removeAll(itemsInRemoteAuthority) == true) {
-               ArrayList<String> remainingItems = itemsInLocalAuthority; // now a subset of local items
+       itemsInLocalAuthority.removeAll(itemsInRemoteAuthority);
+       if (itemsInLocalAuthority.size() > 0) {
+               ArrayList<String> remainingItems = itemsInLocalAuthority; // now a subset of local items that no longer exist on the SAS, so we need to try to delete them (or mark them as deprecated if they still have records referencing them)
                //
                // We now need to either hard-deleted or deprecate the remaining authorities
                //
@@ -213,8 +214,26 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
                        throw new Exception("Encountered unexpected exception trying to delete or deprecated authority items during synchronization.");
                }
        }
-
-        
+       //
+       // We need to synchronize the hierarchy relationships
+       //
+        itemList = getItemList(sasPayloadInItemList); // Really need to re-request the sasPayload?  I don't think so.
+        if (itemList != null) {
+               for (Element e:itemList) {
+                       String remoteRefName = XmlTools.getElementValue(e, "refName");
+                       itemsInRemoteAuthority.add(remoteRefName);
+                       long status = syncRemoteItemRelationshipsWithLocalItem(ctx, remoteRefName);
+                       if (status == 1) {
+                               created++;
+                       } else if (status == 0) {
+                               synched++;
+                       } else {
+                               alreadySynched++;
+                       }
+                       totalItemsProcessed++;
+               }
+        }      
+       
         logger.info(String.format("Total number of items processed during sync: %d", totalItemsProcessed));
         logger.info(String.format("Number of items synchronized: %d", synched));
         logger.info(String.format("Number of items created during sync: %d", created));
@@ -224,7 +243,7 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
     }
 
     /**
-     * 
+     * This method should only be used as part of a SAS synch operation.
      * @param ctx
      * @param refNameList
      * @return
@@ -233,25 +252,29 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
     private long deleteOrDeprecateItems(ServiceContext ctx, ArrayList<String> refNameList) throws Exception {
        long result = 0;
        
-       ArrayList<String> failureList = new ArrayList<String>();
-        ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, false);
-
-       for (String refName:refNameList) {
-               AuthorityTermInfo itemInfo = RefNameUtils.parseAuthorityTermInfo(refName);
+        ctx.setProperty(AuthorityServiceUtils.SHOULD_UPDATE_REV_PROPERTY, false); // Don't update the revision number when we delete or deprecate the item
+       for (String itemRefName:refNameList) {
+               AuthorityTermInfo authorityTermInfo = RefNameUtils.parseAuthorityTermInfo(itemRefName);
+            AuthorityItemSpecifier authorityItemSpecificer = new AuthorityItemSpecifier(SpecifierForm.URN_NAME, authorityTermInfo.inAuthority.name,
+                       authorityTermInfo.name);
+                       
                AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
                try {
-                       authorityResource.deleteAuthorityItem(ctx, itemInfo.inAuthority.csid, itemInfo.csid);
+                       authorityResource.deleteAuthorityItem(ctx,
+                                       Specifier.createShortIdURNValue(authorityTermInfo.inAuthority.name),
+                                       Specifier.createShortIdURNValue(authorityTermInfo.name),
+                                       AuthorityServiceUtils.DONT_UPDATE_REV); // Since we're sync'ing, we shouldn't update the revision number (obviously this only applies to soft-deletes since hard-deletes destroy the record)
                        result++;
                } catch (DocumentReferenceException de) {
                        logger.info(String.format("Authority item '%s' has existing references and cannot be removed during sync.",
-                                       refName), de);
+                                       itemRefName), de);
                        boolean marked = AuthorityServiceUtils.markAuthorityItemAsDeprecated(ctx, authorityItemCommonSchemaName,
-                                       itemInfo.csid);
+                                       authorityItemSpecificer);
                        if (marked == true) {
                                result++;
                        }
                } catch (Exception e) {
-                       logger.warn(String.format("Unable to delete authority item '%s'", refName), e);
+                       logger.warn(String.format("Unable to delete authority item '%s'", itemRefName), e);
                        throw e;
                }
        }
@@ -273,22 +296,23 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
      * We need to add pagination support to this call!!!
      * 
      * @param ctx
-     * @param specifier
+     * @param authoritySpecifier
      * @return
      * @throws Exception
      */
-    private ArrayList<String> getItemsInLocalAuthority(ServiceContext ctx, Specifier specifier) throws Exception {
+    private ArrayList<String> getItemsInLocalAuthority(ServiceContext ctx, Specifier authoritySpecifier) throws Exception {
        ArrayList<String> result = new ArrayList<String>();
        
        ResourceMap resourceMap = ctx.getResourceMap();
        String resourceName = ctx.getClient().getServiceName();
        AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName);
-       AbstractCommonList acl = authorityResource.getAuthorityItemList(ctx, specifier.value, ctx.getUriInfo());
+       AbstractCommonList acl = authorityResource.getAuthorityItemList(ctx, authoritySpecifier.getURNValue(), ctx.getUriInfo());
+       
        List<ListItem> listItemList = acl.getListItem();
        for (ListItem listItem:listItemList) {
                Boolean proposed = getBooleanValue(listItem, AuthorityItemJAXBSchema.PROPOSED);
                if (proposed == false) { // exclude "proposed" (i.e., local-only items)
-                       result.add(AbstractCommonListUtils.ListItemGetElementValue(listItem, AuthorityItemJAXBSchema.REF_NAME));
+                       result.add(AbstractCommonListUtils.ListItemGetElementValue(listItem, AuthorityItemJAXBSchema.SHORT_IDENTIFIER));
                }
        }
        
@@ -311,7 +335,8 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
     }
     
     /**
-     * This is a sync method.
+     * This method should only be used during a SAS synchronization request.
+     * 
      * @param ctx
      * @param parentIdentifier - Must be in short-id-refname form -i.e., urn:cspace:name(shortid)
      * @param itemIdentifier   - Must be in short-id-refname form -i.e., urn:cspace:name(shortid)
@@ -335,7 +360,7 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
         //
        AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();
        Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.getURNValue(),
-                       sasPayloadIn, AuthorityServiceUtils.DONT_UPDATE_REV, AuthorityServiceUtils.NOT_PROPOSED);
+                       sasPayloadIn, AuthorityServiceUtils.DONT_UPDATE_REV, AuthorityServiceUtils.NOT_PROPOSED, AuthorityServiceUtils.SAS_ITEM);
        //
        // Check the response for successful POST result
        //
@@ -404,6 +429,66 @@ public abstract class AuthorityDocumentModelHandler<AuthCommon>
        
        return result; // -1 = no sync needed/possible, 0 = sync'd, 1 = created new item
     }
+    
+    /**
+     * Ensure the local items relationships look the same as the remote items' by synchronizing the hierarchy relationship records
+     * of the SAS item with the local item.
+     * 
+     * @param ctx
+     * @param refName
+     * @return
+     * @throws Exception
+     */
+    protected long syncRemoteItemRelationshipsWithLocalItem(ServiceContext ctx, String itemRefName) throws Exception {
+       long result = -1;
+       //
+       // WARNING: THIS CODE IS NOT IMPLEMENTED YET
+       //
+       return result;
+       //
+       // Using the item refname (with no local CSID), create specifiers that we'll use to find the local versions
+       //
+       
+       /*
+       AuthorityTermInfo authorityTermInfo = RefNameUtils.parseAuthorityTermInfo(itemRefName);
+       String parentIdentifier = Specifier.createShortIdURNValue(authorityTermInfo.inAuthority.name);
+       String itemIdentifier = Specifier.createShortIdURNValue(authorityTermInfo.name);
+       //
+       // We'll use the Authority JAX-RS resource to peform sync operations (creates and updates)
+       //
+       AuthorityResource authorityResource = (AuthorityResource) ctx.getResource();            
+       PoxPayloadOut localItemPayloadOut;
+       try {
+               localItemPayloadOut = authorityResource.getAuthorityItemWithExistingContext(ctx, parentIdentifier, itemIdentifier);
+       } catch (DocumentNotFoundException dnf) {
+               //
+               // Document not found, means we need to create an item/term that exists only on the SAS
+               //
+               logger.info(String.format("Remote item with refname='%s' doesn't exist locally, so we'll create it.", itemRefName));
+               createLocalItem(ctx, parentIdentifier, itemIdentifier);
+               return 1; // exit with status of 1 means we created a new authority item
+       }
+       //
+       // If we get here, we know the item exists both locally and remotely, so we need to synchronize them.
+       //
+       //
+       try {
+               PoxPayloadOut theUpdate = authorityResource.synchronizeItemWithExistingContext(ctx, parentIdentifier, itemIdentifier);
+               if (theUpdate != null) {
+                       result = 0; // means we needed to sync this item with SAS
+                       logger.debug(String.format("Sync'd authority item parent='%s' id='%s with SAS.  Updated payload is: \n%s",
+                                       parentIdentifier, itemIdentifier, theUpdate.getXmlPayload()));
+               }
+       } catch (DocumentReferenceException de) { // Exception for items that still have records/resource referencing them.
+               result = -1;
+               logger.error(String.format("Could not sync authority item = '%s' because it has existing records referencing it.",
+                               itemIdentifier));
+       }
+       
+       return result; // -1 = no sync needed/possible, 0 = sync'd, 1 = created new item
+       */
+       
+    }    
         
     private PoxPayloadIn requestPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception {
        PoxPayloadIn result = null;
index bef1d45171a3426bc2e52800ada2f7983ffddeb1..4153c69cf240c99d491f3b1f9c3b3a2164a02ace 100644 (file)
@@ -98,6 +98,7 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
     private String authorityItemTermGroupXPathBase;
     
     private boolean isProposed = false; // used by local authority to propose a new shared item. Allows local deployments to use new terms until they become official
+    private boolean isSAS = false; // used to indicate if the authority item originated as a SAS item
     private boolean shouldUpdateRevNumber = true; // by default we should update the revision number -not true on synchronization with SAS
     /**
      * inVocabulary is the parent Authority for this context
@@ -127,6 +128,17 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
        this.isProposed = flag;
     }
     
+    //
+    // Getter and Setter for 'isSAS'
+    //
+    public boolean getIsSASItem() {
+       return this.isSAS;
+    }
+
+    public void setIsSASItem(boolean flag) {
+       this.isSAS = flag;
+    }
+    
     //
     // Getter and Setter for 'shouldUpdateRevNumber'
     //
@@ -449,12 +461,13 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
                PoxPayloadOut payloadOut = authorityResource.updateAuthorityItem(ctx, 
                                ctx.getResourceMap(),                                   
                                ctx.getUriInfo(),
-                               localParentCsid,                                // parent's CSID
-                               localItemCsid,                                  // item's CSID
-                               sasPayloadIn,                                   // the payload from the remote SAS
+                               localParentCsid,                                                // parent's CSID
+                               localItemCsid,                                                  // item's CSID
+                               sasPayloadIn,                                                   // the payload from the remote SAS
                                AuthorityServiceUtils.DONT_UPDATE_REV,  // don't update the parent's revision number
-                               AuthorityServiceUtils.NOT_PROPOSED);    // The items is not proposed, make it a real SAS item now
-               if (payloadOut != null) {
+                               AuthorityServiceUtils.NOT_PROPOSED,             // The items is not proposed, make it a real SAS item now
+                               AuthorityServiceUtils.SAS_ITEM);                // Since we're sync'ing, this must be a SAS item
+               if (payloadOut != null) {       
                        ctx.setOutput(payloadOut);
                        result = true;
                }
@@ -482,6 +495,9 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
                }
                result = true;
         }
+        //
+        // We need to synchronize the hierarchy relationships here.
+        //
         
         return result;
     }
@@ -623,9 +639,10 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
                //
                ctx.setUriInfo(this.getServiceContext().getUriInfo()); // try to get a UriInfo instance from the handler's context
         }
-        ctx.getUriInfo().getQueryParameters().addFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED, Boolean.toString(onlyRefsToDeletedObjects));  // Add the wf_deleted query param to the resource call
+        ctx.getUriInfo().getQueryParameters().addFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED, Boolean.toString(onlyRefsToDeletedObjects));  // Add the wf_only_deleted query param to the resource call
        AuthorityRefDocList refObjs = authorityResource.getReferencingObjects(ctx, inAuthorityCsid, itemCsid, 
                        uriTemplateRegistry, ctx.getUriInfo());
+       ctx.getUriInfo().getQueryParameters().remove(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED);  // Need to clear wf_only_deleted values to prevent unexpected side effects
        
        result = refObjs.getTotalItems();
        if (result > 0) {
@@ -722,18 +739,26 @@ public abstract class AuthorityItemDocumentModelHandler<AICommon>
     //
     public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
        super.fillAllParts(wrapDoc, action);
+        DocumentModel documentModel = wrapDoc.getWrappedObject();
+
        //
-       // Update the record's revision number on both CREATE and UPDATE actions
+       // Update the record's revision number on both CREATE and UPDATE actions (as long as it is NOT a SAS authority item)
        //
-       if (this.getShouldUpdateRevNumber() == true) { // We won't update rev numbers on synchronization with SAS
+        Boolean propertyValue = (Boolean) documentModel.getProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.SAS);
+        boolean isMarkedAsSASItem = propertyValue != null ? propertyValue : false;
+       if (this.getShouldUpdateRevNumber() == true && !isMarkedAsSASItem) { // We won't update rev numbers on synchronization with SAS items and on local changes to SAS items
                updateRevNumbers(wrapDoc);
        }
        //
        // If this is a proposed item (not part of the SAS), mark it as such
        //
-        DocumentModel documentModel = wrapDoc.getWrappedObject();
         documentModel.setProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.PROPOSED,
                        new Boolean(this.getIsProposed()));
+        //
+        // If it is a SAS authority item, mark it as such
+        //
+        documentModel.setProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.SAS,
+                       new Boolean(this.getIsSASItem()));
     }
     
     /**