From 573a01ef957491049b4cb5b5330925f96205fcef Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Sat, 9 Apr 2016 04:22:24 -0700 Subject: [PATCH] CSPACE-6935: Next iteration of authority syncing. Pushing to master to get into Nightly build. --- .../vocabulary/res/GetVocabularyItems.res.xml | 2 +- .../src/main/resources/log4j.properties | 1 + .../common/vocabulary/AuthorityResource.java | 207 +++++++++++++----- .../nuxeo/AuthorityDocumentModelHandler.java | 137 +++++++++++- .../AuthorityItemDocumentModelHandler.java | 50 +++-- .../nuxeo/AuthorityServiceUtils.java | 38 ++++ .../collectionspace-client.properties | 2 +- .../services/common/api/RefNameUtils.java | 2 +- .../services/common/XmlTools.java | 42 ++++ .../java/NuxeoDocumentModelHandler.java | 14 +- 10 files changed, 413 insertions(+), 82 deletions(-) create mode 100644 services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityServiceUtils.java diff --git a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/vocabulary/res/GetVocabularyItems.res.xml b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/vocabulary/res/GetVocabularyItems.res.xml index 976e978a0..6b20dc881 100644 --- a/services/IntegrationTests/src/test/resources/test-data/xmlreplay/vocabulary/res/GetVocabularyItems.res.xml +++ b/services/IntegrationTests/src/test/resources/test-data/xmlreplay/vocabulary/res/GetVocabularyItems.res.xml @@ -6,7 +6,7 @@ 0 3 3 - csid|uri|refName|updatedAt|workflowState|order|termStatus|displayName|shortIdentifier + csid|uri|refName|updatedAt|workflowState|rev|order|termStatus|displayName|shortIdentifier ${Item1.displayName} ${Item1.itemID} diff --git a/services/JaxRsServiceProvider/src/main/resources/log4j.properties b/services/JaxRsServiceProvider/src/main/resources/log4j.properties index 271685f80..ccbc09580 100644 --- a/services/JaxRsServiceProvider/src/main/resources/log4j.properties +++ b/services/JaxRsServiceProvider/src/main/resources/log4j.properties @@ -54,6 +54,7 @@ log4j.additivity.perf.collectionspace=false # log4j.logger.org.collectionspace=WARN log4j.logger.org.collectionspace.services.nuxeo.client.java.NuxeoClientEmbedded=TRACE +log4j.logger.org.collectionspace.services.nuxeo.client.java.RepositoryClientImpl=DEBUG #log4j.logger.org.collectionspace.services.nuxeo.client.java=ERROR #log4j.logger.org.collectionspace.services.common.storage.JDBCTools=ERROR #log4j.logger.org.collectionspace.services.common.profile.CSpaceFilter=ERROR diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java index 60547b788..bab68fcd9 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/AuthorityResource.java @@ -594,7 +594,44 @@ public abstract class AuthorityResource } } + protected Response createAuthorityItem(ServiceContext ctx, String parentspecifier) throws Exception { + Response result = null; + + // Note: must have the parentShortId, to do the create. + CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(null, parentspecifier, "createAuthorityItem", "CREATE_ITEM", null); + DocumentHandler handler = + createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier); + String itemcsid = getRepositoryClient(ctx).create(ctx, handler); + UriBuilder path = UriBuilder.fromResource(resourceClass); + path.path(parent.CSID + "/items/" + itemcsid); + result = Response.created(path.build()).build(); + + return result; + } + + /** + * Called with an existing context. + * @param parentCtx + * @param parentspecifier + * @param input + * @return + * @throws Exception + */ + public Response createAuthorityItemWithParentContext(ServiceContext parentCtx, + String parentspecifier, + PoxPayloadIn input) throws Exception { + Response result = null; + + ServiceContext ctx = createServiceContext(getItemServiceName(), input, + parentCtx.getResourceMap(), parentCtx.getUriInfo()); + if (parentCtx.getCurrentRepositorySession() != null) { + ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession()); + } + result = this.createAuthorityItem(ctx, parentspecifier); + return result; + } + /************************************************************************* * Create an AuthorityItem - this is a sub-resource of Authority * @param specifier either a CSID or one of the urn forms @@ -612,15 +649,7 @@ public abstract class AuthorityResource try { PoxPayloadIn input = new PoxPayloadIn(xmlPayload); ServiceContext ctx = createServiceContext(getItemServiceName(), input, resourceMap, uriInfo); - - // Note: must have the parentShortId, to do the create. - CsidAndShortIdentifier parent = lookupParentCSIDAndShortIdentifer(null, parentspecifier, "createAuthorityItem", "CREATE_ITEM", null); - DocumentHandler handler = - createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier); - String itemcsid = getRepositoryClient(ctx).create(ctx, handler); - UriBuilder path = UriBuilder.fromResource(resourceClass); - path.path(parent.CSID + "/items/" + itemcsid); - result = Response.created(path.build()).build(); + result = this.createAuthorityItem(ctx, parentspecifier); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.CREATE_FAILED); } @@ -689,7 +718,48 @@ public abstract class AuthorityResource return result.getBytes(); } + + private PoxPayloadOut getAuthorityItem( + ServiceContext ctx, + String parentIdentifier, + String itemIdentifier) throws Exception { + PoxPayloadOut result = null; + + String parentcsid = lookupParentCSID(parentIdentifier, "getAuthorityItem(parent)", "GET_ITEM", null); + // We omit the parentShortId, only needed when doing a create... + DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null); + + Specifier itemSpec = getSpecifier(itemIdentifier, "getAuthorityItem(item)", "GET_ITEM"); + if (itemSpec.form == SpecifierForm.CSID) { + getRepositoryClient(ctx).get(ctx, itemSpec.value, handler); + } else { + String itemWhereClause = + RefNameServiceUtils.buildWhereForAuthItemByName(authorityItemCommonSchemaName, itemSpec.value, parentcsid); + DocumentFilter myFilter = new NuxeoDocumentFilter(itemWhereClause, 0, 1); // start at page 0 and get 1 item + handler.setDocumentFilter(myFilter); + getRepositoryClient(ctx).get(ctx, handler); + } + // TODO should we assert that the item is in the passed vocab? + result = (PoxPayloadOut) ctx.getOutput(); + + return result; + } + public PoxPayloadOut getAuthorityItemWithParentContext( + ServiceContext parentCtx, + String parentIdentifier, + String itemIdentifier) throws Exception { + PoxPayloadOut result = null; + + ServiceContext ctx = createServiceContext(getItemServiceName(), parentCtx.getResourceMap(), parentCtx.getUriInfo()); + if (parentCtx.getCurrentRepositorySession() != null) { + ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession()); // Reuse the current repo session if one exists + } + result = getAuthorityItem(ctx, parentIdentifier, itemIdentifier); + + return result; + } + /** * Gets the authority item. * @@ -704,44 +774,23 @@ public abstract class AuthorityResource @Context Request request, @Context UriInfo uriInfo, @Context ResourceMap resourceMap, - @PathParam("csid") String parentspecifier, - @PathParam("itemcsid") String itemspecifier) { + @PathParam("csid") String parentIdentifier, + @PathParam("itemcsid") String itemIdentifier) { PoxPayloadOut result = null; try { - String parentcsid = lookupParentCSID(parentspecifier, "getAuthorityItem(parent)", "GET_ITEM", uriInfo); - RemoteServiceContext ctx = - (RemoteServiceContext) createServiceContext(getItemServiceName(), resourceMap, uriInfo); - - JaxRsContext jaxRsContext = new JaxRsContext(request, uriInfo); // Needed for getting account permissions part of the payload - ctx.setJaxRsContext(jaxRsContext); + (RemoteServiceContext) createServiceContext(getItemServiceName(), resourceMap, uriInfo); - // We omit the parentShortId, only needed when doing a create... - DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid, null); - - Specifier itemSpec = getSpecifier(itemspecifier, "getAuthorityItem(item)", "GET_ITEM"); - if (itemSpec.form == SpecifierForm.CSID) { - getRepositoryClient(ctx).get(ctx, itemSpec.value, handler); - } else { - String itemWhereClause = - RefNameServiceUtils.buildWhereForAuthItemByName(authorityItemCommonSchemaName, itemSpec.value, parentcsid); - DocumentFilter myFilter = new NuxeoDocumentFilter(itemWhereClause, 0, 1); // start at page 0 and get 1 item - handler.setDocumentFilter(myFilter); - getRepositoryClient(ctx).get(ctx, handler); - } - // TODO should we assert that the item is in the passed vocab? - result = ctx.getOutput(); + JaxRsContext jaxRsContext = new JaxRsContext(request, uriInfo); // Needed for getting account permissions part of the resource + ctx.setJaxRsContext(jaxRsContext); + + result = getAuthorityItem(ctx, parentIdentifier, itemIdentifier); + } catch (DocumentNotFoundException dnf) { + throw bigReThrow(dnf, ServiceMessages.resourceNotFoundMsg(itemIdentifier)); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.GET_FAILED); } - - if (result == null) { - Response response = Response.status(Response.Status.NOT_FOUND).entity( - "Get failed, the requested AuthorityItem specifier:" + itemspecifier + ": was not found.").type( - "text/plain").build(); - throw new CSWebApplicationException(response); - } - + return result.getBytes(); } @@ -927,9 +976,68 @@ public abstract class AuthorityResource } return authRefList; } + + /** + * Synchronizes a local authority item with a share authority server (SAS) item. + * @param ctx + * @param parentIdentifier + * @param itemIdentifier + * @return + * @throws Exception + */ + protected PoxPayloadOut synchronizeItem( + ServiceContext ctx, + String parentIdentifier, + String itemIdentifier) throws Exception { + PoxPayloadOut result = null; + AuthorityItemSpecifier specifier; + CsidAndShortIdentifier parent; + boolean neededSync = false; + + parent = lookupParentCSIDAndShortIdentifer(null, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null); + AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier); + Specifier parentSpecifier = getSpecifier(parent.CSID, "getAuthority", "GET"); + Specifier itemSpecifier = getSpecifier(itemIdentifier, "getAuthorityItem", "GET"); + specifier = new AuthorityItemSpecifier(parentSpecifier, itemSpecifier); + // + neededSync = getRepositoryClient(ctx).synchronize(ctx, specifier, handler); + if (neededSync == true) { + result = (PoxPayloadOut) ctx.getOutput(); + } + + return result; + } /** - * Synchronizes the authority and its terms with a Shared Authority Server (SAS). + * Using the parent and item ID, sync the local item with the SAS (shared authority server) + * Used by the AuthorityItemDocumentModelHandler when synchronizing a list of remote authority items with a + * local authority. The parent context was created for the authority (parent) because the sync started there. + * @param parentCtx + * @param parentIdentifier + * @param itemIdentifier + * @return + * @throws Exception + */ + public PoxPayloadOut synchronizeItemWithParentContext( + ServiceContext parentCtx, + String parentIdentifier, + String itemIdentifier + ) throws Exception { + PoxPayloadOut result = null; + + ServiceContext ctx = createServiceContext(getItemServiceName(), + parentCtx.getResourceMap(), + parentCtx.getUriInfo()); + if (parentCtx.getCurrentRepositorySession() != null) { + ctx.setCurrentRepositorySession(parentCtx.getCurrentRepositorySession()); + } + result = synchronizeItem(ctx, parentIdentifier, itemIdentifier); + + return result; + } + + /** + * Synchronizes an authority item and with a Shared Authority Server (SAS) item. * * @param specifier either CSIDs and/or one of the urn forms * @@ -939,26 +1047,19 @@ public abstract class AuthorityResource @Path("{csid}/items/{itemcsid}/sync") public byte[] synchronizeItem( @Context ResourceMap resourceMap, - @Context Request request, @Context UriInfo uriInfo, @PathParam("csid") String parentIdentifier, - @PathParam("itemcsid") String itemIdentifier - ) { + @PathParam("itemcsid") String itemIdentifier) { byte[] result; boolean neededSync = false; PoxPayloadOut payloadOut = null; - AuthorityItemSpecifier specifier; - CsidAndShortIdentifier parent; try { ServiceContext ctx = createServiceContext(getItemServiceName(), null, resourceMap, uriInfo); - parent = lookupParentCSIDAndShortIdentifer(null, parentIdentifier, "syncAuthorityItem(parent)", "SYNC_ITEM", null); - AuthorityItemDocumentModelHandler handler = (AuthorityItemDocumentModelHandler)createItemDocumentHandler(ctx, parent.CSID, parent.shortIdentifier); - Specifier parentSpecifier = getSpecifier(parent.CSID, "getAuthority", "GET"); - Specifier itemSpecifier = getSpecifier(itemIdentifier, "getAuthorityItem", "GET"); - specifier = new AuthorityItemSpecifier(parentSpecifier, itemSpecifier); - neededSync = getRepositoryClient(ctx).synchronize(ctx, specifier, handler); - payloadOut = ctx.getOutput(); + payloadOut = this.synchronizeItem(ctx, parentIdentifier, itemIdentifier); + if (payloadOut != null) { + neededSync = true; + } } catch (Exception e) { throw bigReThrow(e, ServiceMessages.SYNC_FAILED, itemIdentifier); } diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java index 35c85b80c..c3d634009 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityDocumentModelHandler.java @@ -23,6 +23,7 @@ */ package org.collectionspace.services.common.vocabulary.nuxeo; +import java.util.List; import java.util.Map; import javax.ws.rs.core.Response; @@ -39,6 +40,7 @@ import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.RefName.Authority; import org.collectionspace.services.common.api.RefNameUtils; import org.collectionspace.services.common.api.RefNameUtils.AuthorityInfo; +import org.collectionspace.services.common.api.RefNameUtils.AuthorityTermInfo; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentException; @@ -110,13 +112,14 @@ public abstract class AuthorityDocumentModelHandler String shortId = (String) NuxeoUtils.getProperyValue(docModel, AuthorityJAXBSchema.SHORT_IDENTIFIER); String refName = (String) NuxeoUtils.getProperyValue(docModel, AuthorityJAXBSchema.REF_NAME); // - // Using the short ID of the local authority, created a URN specifier to retrieve the SAS authority + // Using the short ID of the local authority, create a URN specifier to retrieve the SAS authority // Specifier sasSpecifier = new Specifier(SpecifierForm.URN_NAME, RefNameUtils.createShortIdRefName(shortId)); PoxPayloadIn sasPayloadIn = getPayloadIn(ctx, sasSpecifier); Long sasRev = getRevision(sasPayloadIn); if (sasRev > rev) { + syncAllItems(ctx, sasSpecifier); ResourceMap resourceMap = ctx.getResourceMap(); String resourceName = ctx.getClient().getServiceName(); AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName); @@ -129,7 +132,139 @@ public abstract class AuthorityDocumentModelHandler return result; } + + /* + * Get the list of authority items from the remote shared authority server (SAS) and try + * to synchronize them with the local items. If items exist on the remote but not the local, we'll create them. + */ + protected int syncAllItems(ServiceContext ctx, Specifier sasSpecifier) throws Exception { + int result = -1; + int created = 0; + int synched = 0; + int alreadySynched = 0; + int totalItemsProcessed = 0; + + PoxPayloadIn sasPayloadInItemList = getPayloadInItemList(ctx, sasSpecifier); + List itemList = getItemList(sasPayloadInItemList); + if (itemList != null) { + for (Element e:itemList) { + String remoteRefName = XmlTools.getElementValue(e, "//refName"); + long status = syncRemoteItemWithLocalItem(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)); + logger.info(String.format("Number not needing synchronization: %d", alreadySynched)); + + return result; + } + + /** + * + * @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) + * @throws Exception + */ + protected void createLocalItem(ServiceContext ctx, String parentIdentifier, String itemIdentifier) throws Exception { + // + // Create a URN short ID specifier for the getting to the remote item payload + Specifier authoritySpecifier = new Specifier(SpecifierForm.URN_NAME, parentIdentifier); + Specifier itemSpecifier = new Specifier(SpecifierForm.URN_NAME, itemIdentifier); + AuthorityItemSpecifier sasAuthorityItemSpecifier = new AuthorityItemSpecifier(authoritySpecifier, itemSpecifier); + // + // Get the remote payload + // + PoxPayloadIn sasPayloadIn = AuthorityServiceUtils.getPayloadIn(sasAuthorityItemSpecifier, + ctx.getServiceName(), getEntityResponseType()); + // + // Using the payload from the remote server, create a local copy of the item + // + ResourceMap resourceMap = ctx.getResourceMap(); + String resourceName = ctx.getClient().getServiceName(); + AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName); + Response response = authorityResource.createAuthorityItemWithParentContext(ctx, authoritySpecifier.value, sasPayloadIn); + if (response.getStatus() != Response.Status.CREATED.getStatusCode()) { + throw new DocumentException(String.format("Could not create new authority item '%s' during synchronization of the '%s' authority.", + itemIdentifier, parentIdentifier)); + } + } + + /** + * Try to synchronize a remote item (using its refName) with a local item. If the local doesn't yet + * exist, we'll create it. + * Result values: + * -1 = sync not needed; i.e., already in sync + * 0 = sync succeeded + * 1 = local item was missing so we created it + * @param ctx + * @param refName + * @return + * @throws Exception + */ + protected long syncRemoteItemWithLocalItem(ServiceContext ctx, String remoteRefName) throws Exception { + long result = -1; + + AuthorityTermInfo authorityTermInfo = RefNameUtils.parseAuthorityTermInfo(remoteRefName); + String parentIdentifier = RefNameUtils.createShortIdRefName(authorityTermInfo.inAuthority.name); + String itemIdentifier = RefNameUtils.createShortIdRefName(authorityTermInfo.name); + + ResourceMap resourceMap = ctx.getResourceMap(); + String resourceName = ctx.getClient().getServiceName(); + AuthorityResource authorityResource = (AuthorityResource) resourceMap.get(resourceName); + + PoxPayloadOut localItemPayloadOut; + try { + localItemPayloadOut = authorityResource.getAuthorityItemWithParentContext(ctx, parentIdentifier, itemIdentifier); + } catch (DocumentNotFoundException dnf) { + logger.info(String.format("Remote item with refname='%s' doesn't exist locally, so we'll create it.", remoteRefName)); + 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 + // + authorityResource.synchronizeItemWithParentContext(ctx, parentIdentifier, itemIdentifier); + result = 0; + + return result; + } + private PoxPayloadIn getPayloadInItemList(ServiceContext ctx, Specifier specifier) throws Exception { + PoxPayloadIn result = null; + + AuthorityClient client = (AuthorityClient) ctx.getClient(); + Response res = client.readItemList(specifier.value, + null, // partial term string + null // keyword string + ); + try { + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); + } + + result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response! + } finally { + res.close(); + } + + return result; + } + private PoxPayloadIn getPayloadIn(ServiceContext ctx, Specifier specifier) throws Exception { PoxPayloadIn result = null; diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java index b1b0bdfb9..4acf9b25e 100644 --- a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityItemDocumentModelHandler.java @@ -344,28 +344,28 @@ public abstract class AuthorityItemDocumentModelHandler return list; } - private PoxPayloadIn getPayloadIn(AuthorityItemSpecifier specifier) throws Exception { - PoxPayloadIn result = null; - - ServiceContext parentCtx = new MultipartServiceContextImpl(this.getAuthorityServicePath()); - AuthorityClient client = (AuthorityClient) parentCtx.getClient(); - Response res = client.readItem(specifier.getParentSpecifier().value, specifier.getItemSpecifier().value); - try { - int statusCode = res.getStatus(); - - // Check the status code of the response: does it match - // the expected response(s)? - if (logger.isDebugEnabled()) { - logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); - } - - result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response! - } finally { - res.close(); - } - - return result; - } +// private PoxPayloadIn getPayloadIn(AuthorityItemSpecifier specifier) throws Exception { +// PoxPayloadIn result = null; +// +// ServiceContext parentCtx = new MultipartServiceContextImpl(this.getAuthorityServicePath()); +// AuthorityClient client = (AuthorityClient) parentCtx.getClient(); +// Response res = client.readItem(specifier.getParentSpecifier().value, specifier.getItemSpecifier().value); +// try { +// int statusCode = res.getStatus(); +// +// // Check the status code of the response: does it match +// // the expected response(s)? +// if (logger.isDebugEnabled()) { +// logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); +// } +// +// result = new PoxPayloadIn((String)res.readEntity(getEntityResponseType())); // Get the entire response! +// } finally { +// res.close(); +// } +// +// return result; +// } @Override public boolean handleSync(DocumentWrapper wrapDoc) throws Exception { @@ -400,7 +400,8 @@ public abstract class AuthorityItemDocumentModelHandler Specifier sasItemSpecifier = new Specifier(SpecifierForm.URN_NAME, RefNameUtils.createShortIdRefName(itemShortId)); AuthorityItemSpecifier sasAuthorityItemSpecifier = new AuthorityItemSpecifier(sasAuthoritySpecifier, sasItemSpecifier); // Get the shared authority server's copy - PoxPayloadIn sasPayloadIn = getPayloadIn(sasAuthorityItemSpecifier); + PoxPayloadIn sasPayloadIn = AuthorityServiceUtils.getPayloadIn(sasAuthorityItemSpecifier, + getAuthorityServicePath(), getEntityResponseType()); Long sasRev = getRevision(sasPayloadIn); if (sasRev > itemRev) { @@ -521,6 +522,9 @@ public abstract class AuthorityItemDocumentModelHandler if (this.shouldUpdateParentRevNumber == true) { DocumentModel inAuthorityDocModel = NuxeoUtils.getDocFromCsid(getServiceContext(), getRepositorySession(), getInAuthority()); Long parentRev = (Long)inAuthorityDocModel.getProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV); + if (parentRev == null) { + parentRev = new Long(0); + } parentRev++; inAuthorityDocModel.setProperty(getParentCommonSchemaName(), AuthorityJAXBSchema.REV, parentRev); getRepositorySession().saveDocument(inAuthorityDocModel); diff --git a/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityServiceUtils.java b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityServiceUtils.java new file mode 100644 index 000000000..1bdf10f3d --- /dev/null +++ b/services/authority/service/src/main/java/org/collectionspace/services/common/vocabulary/nuxeo/AuthorityServiceUtils.java @@ -0,0 +1,38 @@ +package org.collectionspace.services.common.vocabulary.nuxeo; + +import javax.ws.rs.core.Response; + +import org.collectionspace.services.client.AuthorityClient; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.common.context.MultipartServiceContextImpl; +import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AuthorityServiceUtils { + private static final Logger logger = LoggerFactory.getLogger(AuthorityIdentifierUtils.class); + + static public PoxPayloadIn getPayloadIn(AuthorityItemSpecifier specifier, String serviceName, Class responseType) throws Exception { + PoxPayloadIn result = null; + + ServiceContext parentCtx = new MultipartServiceContextImpl(serviceName); + AuthorityClient client = (AuthorityClient) parentCtx.getClient(); + Response res = client.readItem(specifier.getParentSpecifier().value, specifier.getItemSpecifier().value); + try { + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(client.getClass().getCanonicalName() + ": status = " + statusCode); + } + + result = new PoxPayloadIn((String)res.readEntity(responseType)); // Get the entire response! + } finally { + res.close(); + } + + return result; + } +} \ No newline at end of file diff --git a/services/client/src/main/resources/collectionspace-client.properties b/services/client/src/main/resources/collectionspace-client.properties index 75cb8b86d..574d3567a 100644 --- a/services/client/src/main/resources/collectionspace-client.properties +++ b/services/client/src/main/resources/collectionspace-client.properties @@ -9,8 +9,8 @@ cspace.url=http://localhost:8180/cspace-services/ cspace.ssl=false cspace.auth=true # default user +#cspace.user=admin@core.collectionspace.org cspace.user=admin@core.collectionspace.org -#cspace.user=admin@testsci.collectionspace.org cspace.password=Administrator # default tenant cspace.tenant=1 diff --git a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java index bc4cbff79..d8f099c7d 100644 --- a/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java +++ b/services/common-api/src/main/java/org/collectionspace/services/common/api/RefNameUtils.java @@ -72,7 +72,7 @@ public class RefNameUtils { public String domain; public String resource; public String csid; - public String name; + public String name; // Is this the short ID? public String displayName; public AuthorityInfo(String refNameTokens[]) throws IllegalArgumentException { diff --git a/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java b/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java index 7bcdc288f..d344243fa 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java +++ b/services/common/src/main/java/org/collectionspace/services/common/XmlTools.java @@ -5,6 +5,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; +import java.util.List; import org.collectionspace.services.common.api.Tools; import org.dom4j.Document; @@ -16,9 +17,12 @@ import org.dom4j.io.HTMLWriter; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class XmlTools { + static final Logger logger = LoggerFactory.getLogger(XmlTools.class); // @TODO Refactoring opportunity: the utility methods below // could potentially be moved into the 'common' module, @@ -214,6 +218,44 @@ public class XmlTools { } } + public static String getElementValue(Element doc, String xpathExpr) { + String elementValue = ""; + if (Tools.isBlank(xpathExpr)) { + return elementValue; + } + try { + Node node = doc.selectSingleNode(xpathExpr); + if ((node == null) || (node.getNodeType() != Node.ELEMENT_NODE)) { + return elementValue; + } + Element element = (Element) node; + elementValue = element.getText(); + } catch (Exception e) { + System.err.println(e.getStackTrace()); + } finally { + return elementValue; + } + } + + /** + * Returns the (text node) value of a specified element in a dom4j XML document. + * @param doc A dom4j XML document. + * @param xpathExpr An XPath expression intended to match a single element + * in the XML document, in the default namespace. + * @return The (text node) value of the matched element, if any. + */ + public static List getElementNodes(Document doc, String xpathExpr) { + List result = null; + + try { + result = doc.selectNodes(xpathExpr); + } catch (Exception e) { + logger.debug("No list-item nodes exist."); + } + + return result; + } + /** * Sets the (text node) value of a specified element in a dom4j XML document. * @param doc A dom4j XML document. diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java index e56a91936..6ace56a4f 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/NuxeoDocumentModelHandler.java @@ -35,6 +35,7 @@ import javax.ws.rs.core.MultivaluedMap; import org.collectionspace.services.client.CollectionSpaceClient; import org.collectionspace.services.client.IQueryManager; import org.collectionspace.services.client.IRelationsManager; +import org.collectionspace.services.client.PoxPayload; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.common.ReflectionMapper; @@ -115,15 +116,24 @@ public abstract class NuxeoDocumentModelHandler extends RemoteDocumentModelHa return String.class; } - protected Long getRevision(PoxPayloadIn payloadIn) { + protected Long getRevision(PoxPayload payload) { Long result = null; - Document document = payloadIn.getDOMDocument(); + Document document = payload.getDOMDocument(); String xmlRev = XmlTools.getElementValue(document, "//rev"); result = Long.valueOf(xmlRev); return result; } + + protected List getItemList(PoxPayloadIn payloadIn) { + List result = null; + + Document document = payloadIn.getDOMDocument(); + result = XmlTools.getElementNodes(document, "//list-item"); + + return result; + } /** * Subclass DocHandlers may override this method to control exact creation of the common list. -- 2.47.3