From c54dacc5f61fb7e57949933baf34b7ec89187dcd Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Fri, 20 Apr 2012 12:27:18 -0700 Subject: [PATCH] CSPACE-5025: Adding 'prepare' 'handle' 'complete' phases to RepositoryClient delete operations. Adding validate for soft and hard deletes on relationship records. Signed-off-by: Richard Millet --- services/IntegrationTests/pom.xml | 10 + .../test/RelationIntegrationTest.java | 208 ++++++++++++++++++ .../common/vocabulary/AuthorityResource.java | 32 ++- .../client/test/AbstractServiceTestImpl.java | 3 +- .../client/workflow/WorkflowClient.java | 1 + ...tMultiPartCollectionSpaceResourceImpl.java | 27 ++- .../services/common/ResourceBase.java | 3 +- .../document/AbstractDocumentHandlerImpl.java | 1 + .../common/document/DocumentHandler.java | 9 +- .../common/storage/StorageClient.java | 10 +- .../storage/jpa/JpaDocumentHandler.java | 10 + .../storage/jpa/JpaStorageClientImpl.java | 9 + .../nuxeo/WorkflowDocumentModelHandler.java | 26 ++- .../java/RemoteDocumentModelHandlerImpl.java | 7 + .../client/java/RepositoryJavaClientImpl.java | 32 ++- .../nuxeo/ConceptValidatorHandler.java | 6 + .../AuthorityResourceWithContacts.java | 3 +- .../nuxeo-platform-cs-dimension/pom.xml | 2 +- services/dimension/client/pom.xml | 3 +- .../client/test/DimensionXmlReplayTest.java | 10 +- .../nuxeo/DimensionDocumentModelHandler.java | 1 + .../nuxeo/LocationValidatorHandler.java | 6 + .../nuxeo/OrgAuthorityValidatorHandler.java | 6 + .../nuxeo/OrganizationValidatorHandler.java | 6 + .../PersonAuthorityValidatorHandler.java | 6 + .../person/nuxeo/PersonValidatorHandler.java | 6 + .../place/nuxeo/PlaceValidatorHandler.java | 6 + .../nuxeo/RelationDocumentModelHandler.java | 65 +++++- .../taxonomy/nuxeo/TaxonValidatorHandler.java | 6 + .../nuxeo/VocabularyItemValidatorHandler.java | 6 + .../nuxeo/VocabularyValidatorHandler.java | 6 + 31 files changed, 496 insertions(+), 36 deletions(-) diff --git a/services/IntegrationTests/pom.xml b/services/IntegrationTests/pom.xml index de513d3fc..c9720b6c1 100644 --- a/services/IntegrationTests/pom.xml +++ b/services/IntegrationTests/pom.xml @@ -58,6 +58,16 @@ org.collectionspace.services.intake.client ${project.version} + + org.collectionspace.services + org.collectionspace.services.dimension.jaxb + ${project.version} + + + org.collectionspace.services + org.collectionspace.services.dimension.client + ${project.version} + org.collectionspace.services org.collectionspace.services.relation.client diff --git a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java index fbc73e5d9..1e7a46faa 100644 --- a/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java +++ b/services/IntegrationTests/src/test/java/org/collectionspace/services/IntegrationTests/test/RelationIntegrationTest.java @@ -22,11 +22,15 @@ */ package org.collectionspace.services.IntegrationTests.test; +import java.io.StringWriter; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; import org.testng.Assert; import org.testng.annotations.Test; @@ -37,6 +41,8 @@ import org.slf4j.LoggerFactory; import org.jboss.resteasy.client.ClientResponse; import org.collectionspace.services.client.CollectionObjectClient; +import org.collectionspace.services.client.DimensionClient; +import org.collectionspace.services.client.DimensionFactory; import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; @@ -46,6 +52,8 @@ import org.collectionspace.services.client.IntakeClient; import org.collectionspace.services.intake.IntakesCommon; import org.collectionspace.services.client.RelationClient; +import org.collectionspace.services.client.workflow.WorkflowClient; +import org.collectionspace.services.dimension.DimensionsCommon; import org.collectionspace.services.relation.RelationsCommon; import org.collectionspace.services.relation.RelationsCommonList; import org.collectionspace.services.relation.RelationshipType; @@ -65,9 +73,209 @@ public class RelationIntegrationTest extends CollectionSpaceIntegrationTest { private CollectionObjectClient collectionObjectClient = new CollectionObjectClient(); private RelationClient relationClient = new RelationClient(); private IntakeClient intakeClient = new IntakeClient(); + private DimensionClient dimensionClient = new DimensionClient(); private static final int OBJECTS_TO_INTAKE = 1; + + /** + * Object as xml string. + * + * @param o the o + * @param clazz the clazz + * @return the string + */ + static protected String objectAsXmlString(Object o, Class clazz) { + StringWriter sw = new StringWriter(); + try { + JAXBContext jc = JAXBContext.newInstance(clazz); + Marshaller m = jc.createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, + Boolean.TRUE); + m.marshal(o, sw); + } catch (Exception e) { + e.printStackTrace(); + } + return sw.toString(); + } + + private PoxPayloadOut createDimensionInstance(String commonPartName, String dimensionType, String dimensionValue, String entryDate) { + DimensionsCommon dimensionsCommon = new DimensionsCommon(); + dimensionsCommon.setDimension(dimensionType); + dimensionsCommon.setValue(new BigDecimal(dimensionValue)); + dimensionsCommon.setValueDate(entryDate); + PoxPayloadOut multipart = DimensionFactory.createDimensionInstance( + commonPartName, dimensionsCommon); + + if (logger.isDebugEnabled()) { + logger.debug("to be created, dimension common"); + logger.debug(objectAsXmlString(dimensionsCommon, + DimensionsCommon.class)); + } + + return multipart; + } + + protected PoxPayloadOut createDimensionInstance(String identifier) { + DimensionClient client = new DimensionClient(); + return createDimensionInstance(client.getCommonPartName(), identifier); + } + + /** + * Creates the dimension instance. + * + * @param identifier the identifier + * @return the multipart output + */ + protected PoxPayloadOut createDimensionInstance(String commonPartName, String identifier) { + final String DIMENSION_VALUE = "78.306"; + + return createDimensionInstance(commonPartName, + "dimensionType-" + identifier, + DIMENSION_VALUE, + "entryDate-" + identifier); + } + + @Test void deleteCollectionObjectRelationshipToLockedDimension() { + // + // First create a CollectionObject + // + CollectionobjectsCommon co = new CollectionobjectsCommon(); + fillCollectionObject(co, createIdentifier()); + + // Next, create a part object + PoxPayloadOut multipart = new PoxPayloadOut(CollectionObjectClient.SERVICE_PAYLOAD_NAME); + PayloadOutputPart commonPart = multipart.addPart(co, MediaType.APPLICATION_XML_TYPE); + commonPart.setLabel(collectionObjectClient.getCommonPartName()); + + // Make the create call and check the response + ClientResponse response = collectionObjectClient.create(multipart); + String collectionObjectCsid = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED + .getStatusCode()); + collectionObjectCsid = extractId(response); + } finally { + response.releaseConnection(); + } + + //Next, create a Dimension record to relate the collection object to + multipart = this.createDimensionInstance(createIdentifier()); + // Make the call to create and check the response + response = dimensionClient.create(multipart); + String dimensionCsid = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode()); + dimensionCsid = extractId(response); + } finally { + response.releaseConnection(); + } + + // Relate the two entities, by creating a new relation object + RelationsCommon relation = new RelationsCommon(); + fillRelation(relation, collectionObjectCsid, CollectionobjectsCommon.class.getSimpleName(), + dimensionCsid, DimensionsCommon.class.getSimpleName(), + "collectionobject-dimension"); + // Create the part and fill it with the relation object + multipart = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME); + commonPart = multipart.addPart(relation, MediaType.APPLICATION_XML_TYPE); + commonPart.setLabel(relationClient.getCommonPartName()); + + // Create the relationship + response = relationClient.create(multipart); + @SuppressWarnings("unused") + String relationCsid = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode()); + relationCsid = extractId(response); + } finally { + response.releaseConnection(); + } + + // Now lock the dimension record. + + @SuppressWarnings("unused") + ClientResponse workflowResponse = dimensionClient.updateWorkflowWithTransition(dimensionCsid, WorkflowClient.WORKFLOWTRANSITION_LOCK); + System.out.println("Locked dimension record with CSID=" + dimensionCsid); + + // Finally, try to delete the relationship + + // Try to delete the relationship -should fail because we don't allow delete if one of the sides is locked. + response = relationClient.delete(relationCsid); + try { + Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); + } finally { + response.releaseConnection(); + } + + // Also, try to soft-delete. This should also fail. + workflowResponse = dimensionClient.updateWorkflowWithTransition(dimensionCsid, WorkflowClient.WORKFLOWTRANSITION_DELETE); + System.out.println("Locked dimension record with CSID=" + dimensionCsid); + } + + + @Test void releteCollectionObjectToLockedDimension() { + // + // First create a CollectionObject + // + CollectionobjectsCommon co = new CollectionobjectsCommon(); + fillCollectionObject(co, createIdentifier()); + + // Next, create a part object + PoxPayloadOut multipart = new PoxPayloadOut(CollectionObjectClient.SERVICE_PAYLOAD_NAME); + PayloadOutputPart commonPart = multipart.addPart(co, MediaType.APPLICATION_XML_TYPE); + commonPart.setLabel(collectionObjectClient.getCommonPartName()); + + // Make the create call and check the response + ClientResponse response = collectionObjectClient.create(multipart); + String collectionObjectCsid = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED + .getStatusCode()); + collectionObjectCsid = extractId(response); + } finally { + response.releaseConnection(); + } + + //Next, create a Dimension record to relate the collection object to + multipart = this.createDimensionInstance(createIdentifier()); + // Make the call to create and check the response + response = dimensionClient.create(multipart); + String dimensionCsid = null; + try { + Assert.assertEquals(response.getStatus(), Response.Status.CREATED.getStatusCode()); + dimensionCsid = extractId(response); + } finally { + response.releaseConnection(); + } + + @SuppressWarnings("unused") + ClientResponse workflowResponse = dimensionClient.updateWorkflowWithTransition(dimensionCsid, WorkflowClient.WORKFLOWTRANSITION_LOCK); + System.out.println("Locked dimension record with CSID=" + dimensionCsid); + + // Lastly, relate the two entities, by creating a new relation object + RelationsCommon relation = new RelationsCommon(); + fillRelation(relation, collectionObjectCsid, CollectionobjectsCommon.class.getSimpleName(), + dimensionCsid, DimensionsCommon.class.getSimpleName(), + "collectionobject-dimension"); + // Create the part and fill it with the relation object + multipart = new PoxPayloadOut(RelationClient.SERVICE_PAYLOAD_NAME); + commonPart = multipart.addPart(relation, MediaType.APPLICATION_XML_TYPE); + commonPart.setLabel(relationClient.getCommonPartName()); + + // Make the call to crate + ClientResponse relationresponse = relationClient.create(multipart); + @SuppressWarnings("unused") + String relationCsid = null; + try { + Assert.assertEquals(relationresponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); + relationCsid = extractId(response); + } finally { + relationresponse.releaseConnection(); + } + + } + @Test public void relateCollectionObjectToIntake() { // 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 bf47c2dae..b1c400f1e 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 @@ -32,14 +32,12 @@ import org.collectionspace.services.common.ResourceBase; import org.collectionspace.services.common.ResourceMap; import org.collectionspace.services.common.ServiceMain; import org.collectionspace.services.common.ServiceMessages; -import org.collectionspace.services.common.XmlTools; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.authorityref.AuthorityRefDocList; import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.JaxRsContext; import org.collectionspace.services.common.context.MultipartServiceContext; -import org.collectionspace.services.common.context.MultipartServiceContextImpl; import org.collectionspace.services.common.context.RemoteServiceContext; import org.collectionspace.services.common.context.ServiceBindingUtils; import org.collectionspace.services.common.context.ServiceContext; @@ -49,7 +47,6 @@ import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.query.QueryManager; -import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.vocabulary.RefNameServiceUtils; import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler; import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler; @@ -58,11 +55,7 @@ import org.collectionspace.services.config.ClientType; import org.collectionspace.services.jaxb.AbstractCommonList; import org.collectionspace.services.lifecycle.TransitionDef; import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler; -import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl; import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; -import org.collectionspace.services.relation.RelationResource; -import org.collectionspace.services.relation.RelationsCommonList; -import org.collectionspace.services.relation.RelationshipType; import org.collectionspace.services.workflow.WorkflowCommon; import org.jboss.resteasy.util.HttpResponseCodes; import org.nuxeo.ecm.core.api.DocumentModel; @@ -494,7 +487,8 @@ public abstract class AuthorityResource try { ensureCSID(csid, ServiceMessages.DELETE_FAILED, "Authority.csid"); ServiceContext ctx = createServiceContext(); - getRepositoryClient(ctx).delete(ctx, csid); + DocumentHandler handler = createDocumentHandler(ctx); + getRepositoryClient(ctx).delete(ctx, csid, handler); return Response.status(HttpResponseCodes.SC_OK).build(); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.DELETE_FAILED, csid); @@ -551,6 +545,8 @@ public abstract class AuthorityResource return result.getBytes(); } + //FIXME: This method is almost identical to the method org.collectionspace.services.common.updateWorkflowWithTransition() so + // they should be consolidated -be DRY (don't repeat yourself). @PUT @Path("{csid}/items/{itemcsid}" + WorkflowClient.SERVICE_PATH + "/{transition}") public byte[] updateItemWorkflowWithTransition( @@ -558,23 +554,34 @@ public abstract class AuthorityResource @PathParam("itemcsid") String itemcsid, @PathParam("transition") String transition) { PoxPayloadOut result = null; + try { + // + // Create an empty workflow_commons input part and set it into a new "workflow" sub-resource context PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(), WorkflowClient.SERVICE_COMMONPART_NAME); + MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, input); + // Create a service context and document handler for the parent resource. ServiceContext parentCtx = createServiceContext(getItemServiceName()); - String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName(); + DocumentHandler parentDocHandler = this.createDocumentHandler(parentCtx); + ctx.setProperty(WorkflowClient.PARENT_DOCHANDLER, parentDocHandler); //added as a context param for the workflow document handler -it will call the parent's dochandler "prepareForWorkflowTranstion" method + // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name + String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName(); + ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace + + // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler TransitionDef transitionDef = getTransitionDef(parentCtx, transition); - MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, input); ctx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef); + WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx); - ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace getRepositoryClient(ctx).update(ctx, itemcsid, handler); result = ctx.getOutput(); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.UPDATE_FAILED + WorkflowClient.SERVICE_PAYLOAD_NAME, csid); } + return result.getBytes(); } @@ -879,7 +886,8 @@ public abstract class AuthorityResource // try { // Note that we have to create the service context for the Items, not the main service ServiceContext ctx = createServiceContext(getItemServiceName()); - getRepositoryClient(ctx).delete(ctx, itemcsid); + DocumentHandler handler = createDocumentHandler(ctx); + getRepositoryClient(ctx).delete(ctx, itemcsid, handler); return Response.status(HttpResponseCodes.SC_OK).build(); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.DELETE_FAILED + " itemcsid: " + itemcsid + " parentcsid:" + parentcsid); diff --git a/services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java b/services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java index 7e3c1fb59..c3d5b510d 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java +++ b/services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTestImpl.java @@ -1065,7 +1065,8 @@ public abstract class AbstractServiceTestImpl parentCtx = createServiceContext(); + DocumentHandler parentDocHandler = this.createDocumentHandler(parentCtx); + ctx.setProperty(WorkflowClient.PARENT_DOCHANDLER, parentDocHandler); //added as a context param for the workflow document handler -it will call the parent's dochandler "prepareForWorkflowTranstion" method + + // When looking for the document, we need to use the parent's workspace name -not the "workflow" workspace name String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName(); - + ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace + + // Get the type of transition we're being asked to make and store it as a context parameter -used by the workflow document handler TransitionDef transitionDef = getTransitionDef(parentCtx, transition); - MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, input); ctx.setProperty(WorkflowClient.TRANSITION_ID, transitionDef); + WorkflowDocumentModelHandler handler = createWorkflowDocumentHandler(ctx); - ctx.setRespositoryWorkspaceName(parentWorkspaceName); //find the document in the parent's workspace getRepositoryClient(ctx).update(ctx, csid, handler); result = ctx.getOutput(); } catch (Exception e) { diff --git a/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java b/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java index 78242c97a..38f34669a 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ResourceBase.java @@ -173,7 +173,8 @@ public abstract class ResourceBase * which handles setup of ServiceContext, and does Exception handling. */ protected Response delete(String csid, ServiceContext ctx) throws Exception { - getRepositoryClient(ctx).delete(ctx, csid); + DocumentHandler handler = createDocumentHandler(ctx); + getRepositoryClient(ctx).delete(ctx, csid, handler); return Response.status(HttpResponseCodes.SC_OK).build(); } diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java index 060af748d..f45e0e051 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/AbstractDocumentHandlerImpl.java @@ -148,6 +148,7 @@ public abstract class AbstractDocumentHandlerImpl break; case DELETE: + validate(action); prepareDelete(); break; diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java index e85acf763..fde044675 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/document/DocumentHandler.java @@ -20,6 +20,8 @@ package org.collectionspace.services.common.document; import java.util.Map; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.lifecycle.Lifecycle; +import org.collectionspace.services.lifecycle.TransitionDef; +import org.nuxeo.ecm.core.api.DocumentModel; /** * @@ -42,7 +44,7 @@ import org.collectionspace.services.lifecycle.Lifecycle; public interface DocumentHandler { public enum Action { - CREATE, GET, GET_ALL, UPDATE, DELETE + CREATE, GET, GET_ALL, UPDATE, DELETE, WORKFLOW } public Lifecycle getLifecycle(); @@ -76,6 +78,11 @@ public interface DocumentHandler { */ public void prepare(Action action) throws Exception; + /** + * updateWorkflowTransition - prepare for a workflow transition + */ + public void handleWorkflowTransition(DocumentWrapper wrapDoc, TransitionDef transitionDef) throws Exception; + /** * prepareCreate processes documents before creating document in repository diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java b/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java index 05f4d386d..56108ce28 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/StorageClient.java @@ -24,6 +24,7 @@ import org.collectionspace.services.common.document.BadRequestException; import org.collectionspace.services.common.document.DocumentException; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; +import org.collectionspace.services.lifecycle.TransitionDef; /** * @@ -123,6 +124,13 @@ public interface StorageClient { * @throws DocumentNotFoundException if entity not found * @throws DocumentException */ - void update(ServiceContext ctx, String id, DocumentHandler handler) throws BadRequestException, DocumentNotFoundException, DocumentException; + void update(ServiceContext ctx, String id, DocumentHandler handler) + throws BadRequestException, DocumentNotFoundException, DocumentException; + + /* + * Updates the workflow state of a document + */ + void doWorkflowTransition(ServiceContext ctx, String id, DocumentHandler handler, TransitionDef transitionDef) + throws BadRequestException, DocumentNotFoundException, DocumentException; } diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaDocumentHandler.java b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaDocumentHandler.java index ab9623b73..cc495124d 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaDocumentHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaDocumentHandler.java @@ -7,6 +7,8 @@ import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.jaxb.AbstractCommonList; import org.collectionspace.services.lifecycle.Lifecycle; +import org.collectionspace.services.lifecycle.TransitionDef; +import org.nuxeo.ecm.core.api.DocumentModel; public abstract class JpaDocumentHandler extends AbstractDocumentHandlerImpl{ @@ -47,4 +49,12 @@ public abstract class JpaDocumentHandler public Lifecycle getLifecycle() { return getLifecycle(null); // NOTE: As of 3/2012, none of the JPA-based services support a life cycle type. } + + @Override + public void handleWorkflowTransition( + DocumentWrapper wrapDoc, TransitionDef transitionDef) + throws Exception { + // Do nothing. JPA document handlers do not support workflow transitions yet. + } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java index ff609dce0..457f7ab11 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java @@ -40,6 +40,7 @@ import org.collectionspace.services.common.storage.StorageClient; import org.collectionspace.services.common.context.ServiceContextProperties; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.query.QueryContext; +import org.collectionspace.services.lifecycle.TransitionDef; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -577,4 +578,12 @@ public class JpaStorageClientImpl implements StorageClient { throws DocumentNotFoundException, DocumentException { throw new UnsupportedOperationException(); } + + @Override + public void doWorkflowTransition(ServiceContext ctx, String id, + DocumentHandler handler, TransitionDef transitionDef) + throws BadRequestException, DocumentNotFoundException, + DocumentException { + // Do nothing. JPA services do not support workflow. + } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/workflow/service/nuxeo/WorkflowDocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/common/workflow/service/nuxeo/WorkflowDocumentModelHandler.java index f4d12ae6e..6b1f83a07 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/workflow/service/nuxeo/WorkflowDocumentModelHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/common/workflow/service/nuxeo/WorkflowDocumentModelHandler.java @@ -23,24 +23,20 @@ */ package org.collectionspace.services.common.workflow.service.nuxeo; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.ws.rs.core.MediaType; -import org.collectionspace.services.client.PayloadInputPart; -import org.collectionspace.services.client.PoxPayloadIn; -import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentWrapper; -import org.collectionspace.services.common.document.DocumentHandler.Action; import org.collectionspace.services.common.workflow.jaxb.WorkflowJAXBSchema; import org.collectionspace.services.config.service.ObjectPartType; import org.collectionspace.services.lifecycle.TransitionDef; import org.collectionspace.services.nuxeo.client.java.DocHandlerBase; +import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler; import org.collectionspace.services.workflow.WorkflowCommon; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; @@ -61,11 +57,25 @@ public class WorkflowDocumentModelHandler * * org.nuxeo.ecm.core.LifecycleCoreExtensions--lifecycle (as opposed to --types) */ - private static final String TRANSITION_DELETE = "delete"; - private static final String TRANSITION_APPROVE = "approve"; - private static final String TRANSITION_UNDELETE = "undelete"; private static final String TRANSITION_UNKNOWN = "unknown"; + + @Override + public void handleUpdate(DocumentWrapper wrapDoc) throws Exception { + // + // First, call the parent document handler to give it a chance to handle the workflow transition -otherwise, call + // the super/parent handleUpdate() method. + // + ServiceContext ctx = this.getServiceContext(); + DocumentModelHandler docHandler = (DocumentModelHandler)ctx.getProperty(WorkflowClient.PARENT_DOCHANDLER); + TransitionDef transitionDef = (TransitionDef)ctx.getProperty(WorkflowClient.TRANSITION_ID); + docHandler.handleWorkflowTransition(wrapDoc, transitionDef); + // + // If no exception occurred, then call the super's method + // + super.handleUpdate(wrapDoc); + } + /* * Handle read (GET) */ diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java index 55454ee72..e00c93c71 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java @@ -38,6 +38,7 @@ import javax.xml.bind.JAXBElement; import org.collectionspace.services.authorization.AccountPermission; import org.collectionspace.services.jaxb.AbstractCommonList; +import org.collectionspace.services.lifecycle.TransitionDef; import org.collectionspace.services.client.PayloadInputPart; import org.collectionspace.services.client.PayloadOutputPart; import org.collectionspace.services.client.PoxPayloadIn; @@ -99,6 +100,12 @@ public abstract class RemoteDocumentModelHandlerImpl } } + @Override + public void handleWorkflowTransition(DocumentWrapper wrapDoc, TransitionDef transitionDef) + throws Exception { + // Do nothing by default, but children can override if they want. The really workflow transition happens in the WorkflowDocumemtModelHandler class + } + /* (non-Javadoc) * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#completeUpdate(org.collectionspace.services.common.document.DocumentWrapper) */ diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index 113ea8fe6..c80800b91 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -32,6 +32,7 @@ import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.query.QueryContext; import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.profile.Profiler; +import org.collectionspace.services.lifecycle.TransitionDef; import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.collectionspace.services.common.document.BadRequestException; @@ -889,23 +890,36 @@ public class RepositoryJavaClientImpl implements RepositoryClientdimension Dimension dimensions_common - cs_default + cs_locking diff --git a/services/dimension/client/pom.xml b/services/dimension/client/pom.xml index 20784b837..c795e589c 100644 --- a/services/dimension/client/pom.xml +++ b/services/dimension/client/pom.xml @@ -39,12 +39,13 @@ org.collectionspace.services.common ${project.version} - + diff --git a/services/dimension/client/src/test/java/org/collectionspace/services/client/test/DimensionXmlReplayTest.java b/services/dimension/client/src/test/java/org/collectionspace/services/client/test/DimensionXmlReplayTest.java index e6828898f..3b9aefd98 100644 --- a/services/dimension/client/src/test/java/org/collectionspace/services/client/test/DimensionXmlReplayTest.java +++ b/services/dimension/client/src/test/java/org/collectionspace/services/client/test/DimensionXmlReplayTest.java @@ -1,19 +1,26 @@ package org.collectionspace.services.client.test; +/* + * XMLReplay test classes shoud ***NOT*** be part of the IntegrationTests module. Move them out into the org.collectionspace.services.client (src/main.test) module ASAP! + */ + +/* import org.collectionspace.services.IntegrationTests.xmlreplay.ServiceResult; import org.collectionspace.services.IntegrationTests.xmlreplay.XmlReplay; import org.collectionspace.services.IntegrationTests.xmlreplay.XmlReplayTest; import org.testng.annotations.Test; import java.util.List; +*/ /** * User: laramie * $LastChangedRevision: $ * $LastChangedDate: $ */ -public class DimensionXmlReplayTest extends XmlReplayTest { +public class DimensionXmlReplayTest /*extends XmlReplayTest*/ { + /* //@Test public void runMaster() throws Exception { XmlReplay replay = createXmlReplayUsingIntegrationTestsModule("../../"); @@ -30,5 +37,6 @@ public class DimensionXmlReplayTest extends XmlReplayTest { ServiceResult res = replay.runTest("dimensionTestGroup", "dimension1"); logTest(res, "runOneTest"); } + */ } diff --git a/services/dimension/service/src/main/java/org/collectionspace/services/dimension/nuxeo/DimensionDocumentModelHandler.java b/services/dimension/service/src/main/java/org/collectionspace/services/dimension/nuxeo/DimensionDocumentModelHandler.java index abb61f38e..43b647473 100644 --- a/services/dimension/service/src/main/java/org/collectionspace/services/dimension/nuxeo/DimensionDocumentModelHandler.java +++ b/services/dimension/service/src/main/java/org/collectionspace/services/dimension/nuxeo/DimensionDocumentModelHandler.java @@ -136,5 +136,6 @@ public class DimensionDocumentModelHandler public String getQProperty(String prop) { return DimensionConstants.NUXEO_SCHEMA_NAME + ":" + prop; } + } diff --git a/services/location/service/src/main/java/org/collectionspace/services/location/nuxeo/LocationValidatorHandler.java b/services/location/service/src/main/java/org/collectionspace/services/location/nuxeo/LocationValidatorHandler.java index 5aa5ec9af..5c120d5f4 100644 --- a/services/location/service/src/main/java/org/collectionspace/services/location/nuxeo/LocationValidatorHandler.java +++ b/services/location/service/src/main/java/org/collectionspace/services/location/nuxeo/LocationValidatorHandler.java @@ -53,6 +53,12 @@ public class LocationValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; LocationsCommon location = (LocationsCommon) mctx.getInputPart(mctx.getCommonPartLabel(), diff --git a/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrgAuthorityValidatorHandler.java b/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrgAuthorityValidatorHandler.java index 867baf1ab..a577588ca 100644 --- a/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrgAuthorityValidatorHandler.java +++ b/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrgAuthorityValidatorHandler.java @@ -52,6 +52,12 @@ public class OrgAuthorityValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; OrgauthoritiesCommon organizationAuth = diff --git a/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrganizationValidatorHandler.java b/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrganizationValidatorHandler.java index 88909ebd9..3c6c6a04b 100644 --- a/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrganizationValidatorHandler.java +++ b/services/organization/service/src/main/java/org/collectionspace/services/organization/nuxeo/OrganizationValidatorHandler.java @@ -52,6 +52,12 @@ public class OrganizationValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; OrganizationsCommon org = (OrganizationsCommon) mctx.getInputPart(mctx.getCommonPartLabel(), diff --git a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonAuthorityValidatorHandler.java b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonAuthorityValidatorHandler.java index 70e2ceeb1..5cf4320a2 100644 --- a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonAuthorityValidatorHandler.java +++ b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonAuthorityValidatorHandler.java @@ -53,6 +53,12 @@ public class PersonAuthorityValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; PersonauthoritiesCommon personAuth = diff --git a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java index f84e6c06e..261d81d6d 100644 --- a/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java +++ b/services/person/service/src/main/java/org/collectionspace/services/person/nuxeo/PersonValidatorHandler.java @@ -52,6 +52,12 @@ public class PersonValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; PersonsCommon person = (PersonsCommon) mctx.getInputPart(mctx.getCommonPartLabel(), diff --git a/services/place/service/src/main/java/org/collectionspace/services/place/nuxeo/PlaceValidatorHandler.java b/services/place/service/src/main/java/org/collectionspace/services/place/nuxeo/PlaceValidatorHandler.java index feb798c1a..bbe1f568c 100644 --- a/services/place/service/src/main/java/org/collectionspace/services/place/nuxeo/PlaceValidatorHandler.java +++ b/services/place/service/src/main/java/org/collectionspace/services/place/nuxeo/PlaceValidatorHandler.java @@ -75,6 +75,12 @@ public class PlaceValidatorHandler implements ValidatorHandler { if(logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; PlacesCommon place = (PlacesCommon) mctx.getInputPart(mctx.getCommonPartLabel(), 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 a14a6294b..689319ae3 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 @@ -25,10 +25,12 @@ package org.collectionspace.services.relation.nuxeo; import java.util.HashMap; import java.util.Iterator; +import java.net.HttpURLConnection; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.common.ResourceBase; +import org.collectionspace.services.common.ServiceException; import org.collectionspace.services.common.ServiceMain; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.Tools; @@ -40,6 +42,7 @@ import org.collectionspace.services.common.document.InvalidDocumentException; import org.collectionspace.services.common.relation.RelationJAXBSchema; import org.collectionspace.services.common.relation.nuxeo.RelationConstants; import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.lifecycle.TransitionDef; import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.collectionspace.services.relation.RelationsCommon; import org.collectionspace.services.relation.RelationsCommonList; @@ -53,12 +56,12 @@ import org.collectionspace.services.client.LocationAuthorityClient; import org.collectionspace.services.client.TaxonomyAuthorityClient; import org.collectionspace.services.client.PlaceAuthorityClient; import org.collectionspace.services.client.ConceptAuthorityClient; +import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.config.service.ServiceBindingType; import org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl; import org.collectionspace.services.nuxeo.client.java.RepositoryJavaClientImpl; import org.nuxeo.ecm.core.api.ClientException; -import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.model.PropertyException; @@ -86,6 +89,47 @@ public class RelationDocumentModelHandler * for ACTION.GET_ALL */ private RelationsCommonList relationList; + + private static final String ERROR_TERMS_IN_WORKFLOWSTATE = "Cannot modify a relationship if either end is in the workflow state: "; + + + private boolean subjectOrObjectInWorkflowState(DocumentWrapper wrapDoc, String workflowState) throws ServiceException { + boolean result = false; + DocumentModel relationDocModel = wrapDoc.getWrappedObject(); + String errMsg = ERROR_TERMS_IN_WORKFLOWSTATE + workflowState; + + RepositoryInstance repoSession = this.getRepositorySession(); + try { + DocumentModel subjectDocModel = getSubjectOrObjectDocModel(repoSession, relationDocModel, SUBJ_DOC_MODEL); + DocumentModel objectDocModel = getSubjectOrObjectDocModel(repoSession, relationDocModel, OBJ_DOC_MODEL); + if (subjectDocModel.getCurrentLifeCycleState().equalsIgnoreCase(workflowState) || + objectDocModel.getCurrentLifeCycleState().equalsIgnoreCase(workflowState)) { + result = true; + } + } catch (Exception e) { + if (logger.isInfoEnabled() == true) { + logger.info(errMsg, e); + } + } + + return result; + } + + @Override + /* + * Until we rework the RepositoryClient to handle the workflow transition (just like it does for 'create', 'get', 'update', and 'delete', this method will only check to see if the transition is allowed. Until then, + * the WorkflowDocumentModelHandler class does the actual workflow transition. + * + * @see org.collectionspace.services.nuxeo.client.java.RemoteDocumentModelHandlerImpl#handleWorkflowTransition(org.collectionspace.services.common.document.DocumentWrapper, org.collectionspace.services.lifecycle.TransitionDef) + */ + public void handleWorkflowTransition(DocumentWrapper wrapDoc, TransitionDef transitionDef) + throws Exception { + String workflowState = transitionDef.getDestinationState(); + if (subjectOrObjectInWorkflowState(wrapDoc, workflowState) == true) { + throw new ServiceException(HttpURLConnection.HTTP_FORBIDDEN, + "Cannot change a relationship if either end of it is in the workflow state: " + workflowState); + } + } @Override public void handleCreate(DocumentWrapper wrapDoc) throws Exception { @@ -94,6 +138,13 @@ public class RelationDocumentModelHandler // And take care of ensuring all the values for the relation info are correct populateSubjectAndObjectValues(wrapDoc); + + // both subject and object cannot be locked + String workflowState = WorkflowClient.WORKFLOWSTATE_LOCKED; + if (subjectOrObjectInWorkflowState(wrapDoc, workflowState) == true) { + throw new ServiceException(HttpURLConnection.HTTP_FORBIDDEN, + "Cannot create a relationship if either end is in the workflow state: " + workflowState); + } } @Override @@ -105,6 +156,18 @@ public class RelationDocumentModelHandler populateSubjectAndObjectValues(wrapDoc); } + @Override + public void handleDelete(DocumentWrapper wrapDoc) throws Exception { + String workflowState = WorkflowClient.WORKFLOWSTATE_LOCKED; + // both subject and object cannot be locked + if (subjectOrObjectInWorkflowState(wrapDoc, workflowState) == false) { + super.handleDelete(wrapDoc); + } else { + throw new ServiceException(HttpURLConnection.HTTP_FORBIDDEN, + "Cannot delete a relationship if either end is in the workflow state: " + workflowState); + } + } + private void populateSubjectAndObjectValues(DocumentWrapper wrapDoc) throws Exception { // Obtain document models for the subject and object of the relation, so that // we ensure we have value docType, URI info. If the docModels support refNames, diff --git a/services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/nuxeo/TaxonValidatorHandler.java b/services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/nuxeo/TaxonValidatorHandler.java index 8a87d4f44..abc758b33 100644 --- a/services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/nuxeo/TaxonValidatorHandler.java +++ b/services/taxonomy/service/src/main/java/org/collectionspace/services/taxonomy/nuxeo/TaxonValidatorHandler.java @@ -52,6 +52,12 @@ public class TaxonValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; TaxonCommon taxon = (TaxonCommon) mctx.getInputPart(mctx.getCommonPartLabel(), diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemValidatorHandler.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemValidatorHandler.java index f30b652f9..e51a9be11 100644 --- a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemValidatorHandler.java +++ b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyItemValidatorHandler.java @@ -53,6 +53,12 @@ public class VocabularyItemValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; VocabularyitemsCommon vocabItem = (VocabularyitemsCommon) mctx.getInputPart(mctx.getCommonPartLabel(), diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyValidatorHandler.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyValidatorHandler.java index 02b06dd17..a78737205 100644 --- a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyValidatorHandler.java +++ b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/nuxeo/VocabularyValidatorHandler.java @@ -53,6 +53,12 @@ public class VocabularyValidatorHandler implements ValidatorHandler { if (logger.isDebugEnabled()) { logger.debug("validate() action=" + action.name()); } + + // Bail out if the validation action is for delete. + if (action.equals(Action.DELETE)) { + return; + } + try { MultipartServiceContext mctx = (MultipartServiceContext) ctx; VocabulariesCommon vocab = (VocabulariesCommon) mctx.getInputPart(mctx.getCommonPartLabel(), -- 2.47.3