import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.core.Response.ResponseBuilder;
import org.collectionspace.services.client.IClientQueryParams;
import org.collectionspace.services.client.IQueryManager;
import org.collectionspace.services.client.PoxPayloadOut;
import org.collectionspace.services.client.XmlTools;
import org.collectionspace.services.client.workflow.WorkflowClient;
-
import org.collectionspace.services.common.CSWebApplicationException;
import org.collectionspace.services.common.NuxeoBasedResource;
import org.collectionspace.services.common.ResourceMap;
import org.collectionspace.services.common.document.Hierarchy;
import org.collectionspace.services.common.query.QueryManager;
import org.collectionspace.services.common.repository.RepositoryClient;
-import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
-import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
-import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
-
+import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.SpecifierForm;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityDocumentModelHandler;
+import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityItemDocumentModelHandler;
+import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
import org.collectionspace.services.config.ClientType;
import org.collectionspace.services.config.service.ServiceBindingType;
+import org.collectionspace.services.description.ServiceDescription;
import org.collectionspace.services.jaxb.AbstractCommonList;
import org.collectionspace.services.jaxb.AbstractCommonList.ListItem;
import org.collectionspace.services.lifecycle.TransitionDef;
-import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
+import org.collectionspace.services.nuxeo.client.java.DocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentFilter;
import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
import org.collectionspace.services.workflow.WorkflowCommon;
-import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
-import org.collectionspace.services.description.ServiceDescription;
-
import org.jboss.resteasy.util.HttpResponseCodes;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
return result.getBytes();
}
+ public PoxPayloadOut updateItemWorkflowWithTransition(ServiceContext<PoxPayloadIn, PoxPayloadOut> existingContext,
+ String parentIdentifier,
+ String itemIdentifier,
+ String transition,
+ boolean updateRevNumber) throws DocumentReferenceException {
+ return updateItemWorkflowWithTransition(existingContext, parentIdentifier, itemIdentifier, transition, updateRevNumber, true);
+ }
+
/**
* Update an authority item's workflow state.
* @param existingContext
String parentIdentifier,
String itemIdentifier,
String transition,
- boolean updateRevNumber) throws DocumentReferenceException {
+ boolean updateRevNumber,
+ boolean rollbackOnException) throws DocumentReferenceException {
PoxPayloadOut result = null;
try {
PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(),
WorkflowClient.SERVICE_COMMONPART_NAME);
MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, input);
+ ctx.setRollbackOnException(rollbackOnException);
if (existingContext != null && existingContext.getCurrentRepositorySession() != null) {
ctx.setCurrentRepositorySession(existingContext.getCurrentRepositorySession());// If a repo session is already open, we need to use it and not create a new one
}
return result;
}
+ public boolean deleteAuthorityItem(ServiceContext<PoxPayloadIn, PoxPayloadOut> existingCtx,
+ String parentIdentifier,
+ String itemIdentifier,
+ boolean shouldUpdateRevNumber) throws Exception {
+ return deleteAuthorityItem(existingCtx, parentIdentifier, itemIdentifier, shouldUpdateRevNumber, true);
+ }
+
/**
*
* @param existingCtx
public boolean deleteAuthorityItem(ServiceContext<PoxPayloadIn, PoxPayloadOut> existingCtx,
String parentIdentifier,
String itemIdentifier,
- boolean shouldUpdateRevNumber
+ boolean shouldUpdateRevNumber,
+ boolean rollbackOnException
) throws Exception {
boolean result = true;
ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext(getItemServiceName(), existingCtx.getUriInfo());
+ ctx.setRollbackOnException(rollbackOnException);
if (existingCtx != null && existingCtx.getCurrentRepositorySession() != null) {
ctx.setCurrentRepositorySession(existingCtx.getCurrentRepositorySession());
ctx.setProperties(existingCtx.getProperties());
package org.collectionspace.services.common.vocabulary;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.collectionspace.services.client.AuthorityClient;
import org.collectionspace.services.client.PoxPayloadIn;
+import org.collectionspace.services.client.workflow.WorkflowClient;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.api.RefNameUtils;
import org.collectionspace.services.common.api.RefNameUtils.AuthorityTermInfo;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.context.MultipartServiceContextImpl;
import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.DocumentException;
+import org.collectionspace.services.common.document.DocumentNotFoundException;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.Specifier;
-import org.collectionspace.services.common.vocabulary.nuxeo.AuthorityIdentifierUtils;
import org.collectionspace.services.config.service.ServiceBindingType;
import org.collectionspace.services.config.tenant.RemoteClientConfig;
import org.collectionspace.services.config.tenant.RemoteClientConfigurations;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.dom4j.XPath;
-import org.collectionspace.services.common.document.DocumentException;
-import org.collectionspace.services.common.document.DocumentNotFoundException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public static final boolean UPDATE_REV = true;
public static final boolean DONT_UPDATE_REV = !UPDATE_REV;
+ public static final boolean ROLLBACK_ON_EXCEPTION = true;
+ public static final boolean DONT_ROLLBACK_ON_EXCEPTION = !ROLLBACK_ON_EXCEPTION;
+
// Used to keep track if an authority item is a locally proposed member of a SAS authority
public static final String IS_PROPOSED_PROPERTY = "IS_PROPOSED";
public static final Boolean PROPOSED = true;
return result;
}
- public static boolean setAuthorityItemDeprecated(ServiceContext ctx,
- DocumentModel docModel, String authorityItemCommonSchemaName, Boolean flag) throws Exception {
- boolean result = false;
-
- docModel.setProperty(authorityItemCommonSchemaName, AuthorityItemJAXBSchema.DEPRECATED,
- new Boolean(flag));
- CoreSessionInterface repoSession = (CoreSessionInterface) ctx.getCurrentRepositorySession();
- repoSession.saveDocument(docModel);
- result = true;
-
- return result;
- }
-
/*
* The domain name part of refnames on a remote SAS may not match that of local refnames.
* Update all the payload's refnames with the local domain name.
* @param itemInfo
* @throws Exception
*/
- public static boolean markAuthorityItemAsDeprecated(ServiceContext ctx, String authorityItemCommonSchemaName, AuthorityItemSpecifier authorityItemSpecifier) throws Exception {
- boolean result = false;
+ public static boolean setAuthorityItemDeprecated(ServiceContext ctx, AuthorityResource authorityResource, String authorityItemCommonSchemaName, AuthorityItemSpecifier authorityItemSpecifier) throws Exception {
+ DocumentModel docModel = NuxeoUtils.getDocFromSpecifier(ctx, (CoreSessionInterface)ctx.getCurrentRepositorySession(),
+ authorityItemCommonSchemaName, authorityItemSpecifier);
- try {
- 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.", authorityItemSpecifier.getItemSpecifier().getURNValue()), e);
- throw e;
+ return setAuthorityItemDeprecated(ctx, authorityResource, authorityItemSpecifier.getParentSpecifier().value, authorityItemSpecifier.getItemSpecifier().getURNValue(), docModel);
+ }
+
+ public static boolean setAuthorityItemDeprecated(ServiceContext ctx, AuthorityResource authorityResource, String parentIdentifier, String itemIdentifier, DocumentModel docModel) throws Exception {
+ String currentWorkflowState = docModel.getCurrentLifeCycleState();
+
+ // Find the transitions needed to get from the current state to the replicated deprecated state.
+ List<String> transitions = AuthorityServiceUtils.getTransitionList(WorkflowClient.WORKFLOWSTATE_DEPRECATED, currentWorkflowState);
+
+ if (!transitions.isEmpty()) {
+ for (String transition : transitions) {
+ authorityResource.updateItemWorkflowWithTransition(ctx, parentIdentifier, itemIdentifier, transition, AuthorityServiceUtils.DONT_UPDATE_REV);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * We need to change the local item's state to one that maps to the replication server's workflow
+ * state. This might involve making multiple transitions.
+ *
+ * WIKI:
+ * See table at https://collectionspace.atlassian.net/wiki/spaces/SDR/pages/665886940/Workflow+transitions+to+map+SAS+item+states+to+Local+item+states
+ * (was https://wiki.collectionspace.org/pages/viewpage.action?pageId=162496564)
+ *
+ */
+ public static List<String> getTransitionList(String sasWorkflowState, String localItemWorkflowState) throws DocumentException {
+ List<String> result = new ArrayList<String>();
+ //
+ // The first set of conditions maps a replication-server "project" state to a local client state of "replicated"
+ //
+ if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
+ // Do nothing. We're good with this state
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ //
+ // The second set of conditions maps a replication-server "deleted" state to a local client state of "deleted"
+ //
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
+ // Do nothing. We're good with this state
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ //
+ // The third set of conditions maps a replication-server "replicated" state to a local state of "replicated"
+ //
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
+ // Do nothing. We're good with this state
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ //
+ // The fourth set of conditions maps a replicatation-server "deprecated" state to a local state of "replicated_deprecated"
+ //
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
+ // Do nothing.
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
+ //
+ // The last set of conditions maps a replication-server "replicated_deleted" state to a local client state of "deleted"
+ //
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
+ // Do nothing. We're good with this state
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
+ } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
+ result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
+ } else {
+ //
+ // If we get here, we've encountered a SAS workflow state that we don't recognize.
+ //
+ throw new DocumentException(String.format("Encountered an invalid workflow state of '%s' on a SAS authority item.", sasWorkflowState));
}
return result;
try {
authorityResource.deleteAuthorityItem(ctx, parentSpecifier.getURNValue(),
- itemSpecifier.getURNValue(), AuthorityServiceUtils.DONT_UPDATE_REV);
+ itemSpecifier.getURNValue(), AuthorityServiceUtils.DONT_UPDATE_REV, AuthorityServiceUtils.DONT_ROLLBACK_ON_EXCEPTION);
handledCount++;
} catch (DocumentReferenceException dre) {
- logger.info(String.format("Item %s has existing references and cannot be deleted.", itemShortId), dre);
+ logger.info(String.format("Failed to delete %s: item is referenced, and will be deprecated instead", itemShortId));
AuthorityItemSpecifier authorityItemSpecifier = new AuthorityItemSpecifier(parentSpecifier, itemSpecifier);
- boolean deprecated = AuthorityServiceUtils.markAuthorityItemAsDeprecated(ctx, authorityItemCommonSchemaName, authorityItemSpecifier);
+ boolean deprecated = AuthorityServiceUtils.setAuthorityItemDeprecated(ctx, authorityResource, authorityItemCommonSchemaName, authorityItemSpecifier);
if (deprecated == true) {
handledCount++;
}
- } catch (Exception e) {
- logger.error(String.format("Unable to delete or deprecate item %s", itemShortId), e);
-
- throw(e);
}
}
*/
package org.collectionspace.services.common.vocabulary.nuxeo;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import javax.ws.rs.core.MultivaluedMap;
+
import org.collectionspace.services.client.AuthorityClient;
import org.collectionspace.services.client.IQueryManager;
-import org.collectionspace.services.client.PayloadInputPart;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.PoxPayloadOut;
-import org.collectionspace.services.client.RelationClient;
import org.collectionspace.services.client.workflow.WorkflowClient;
import org.collectionspace.services.common.api.RefName;
import org.collectionspace.services.common.api.Tools;
import org.collectionspace.services.common.document.DocumentReferenceException;
import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.repository.RepositoryClient;
-import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema;
import org.collectionspace.services.common.vocabulary.AuthorityItemJAXBSchema;
+import org.collectionspace.services.common.vocabulary.AuthorityJAXBSchema;
import org.collectionspace.services.common.vocabulary.AuthorityResource;
import org.collectionspace.services.common.vocabulary.AuthorityServiceUtils;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils;
import org.collectionspace.services.config.service.ListResultField;
import org.collectionspace.services.config.service.ObjectPartType;
import org.collectionspace.services.lifecycle.TransitionDef;
-import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
+import org.collectionspace.services.nuxeo.client.java.NuxeoDocumentModelHandler;
import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
import org.collectionspace.services.relation.RelationsCommonList;
import org.collectionspace.services.vocabulary.VocabularyItemJAXBSchema;
-
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.model.PropertyException;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.ws.rs.core.MultivaluedMap;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
//import org.collectionspace.services.common.authority.AuthorityItemRelations;
/**
* AuthorityItemDocumentModelHandler
//
// Check to see if we need to update the local items's workflow state to reflect that of the remote's
//
- List<String> transitionList = getTransitionList(sasWorkflowState, localItemWorkflowState);
+ List<String> transitionList = AuthorityServiceUtils.getTransitionList(sasWorkflowState, localItemWorkflowState);
+
if (transitionList.isEmpty() == false) {
AuthorityResource authorityResource = (AuthorityResource) ctx.getResource(getAuthorityServicePath()); // Get the authority (parent) client not the item client
//
// We need to move the local item to the SAS workflow state. This might involve multiple transitions.
//
- for (String transition:transitionList) {
- try {
- authorityResource.updateItemWorkflowWithTransition(ctx, localParentCsid, localItemCsid, transition, AuthorityServiceUtils.DONT_UPDATE_REV);
- } catch (DocumentReferenceException de) {
- //
- // This exception means we tried unsuccessfully to soft-delete (workflow transition 'delete') an item that still has references to it from other records.
- //
- AuthorityServiceUtils.setAuthorityItemDeprecated(ctx, itemDocModel, authorityItemCommonSchemaName, AuthorityServiceUtils.DEPRECATED); // Since we can't sof-delete it, we need to mark it as deprecated since it is soft-deleted on the SAS
- logger.warn(String.format("Could not transition item CSID='%s' from workflow state '%s' to '%s'. Check the services log file for details.",
- localItemCsid, localItemWorkflowState, sasWorkflowState));
+ try {
+ for (String transition:transitionList) {
+ authorityResource.updateItemWorkflowWithTransition(ctx, localParentCsid, localItemCsid, transition, AuthorityServiceUtils.DONT_UPDATE_REV, AuthorityServiceUtils.DONT_ROLLBACK_ON_EXCEPTION);
}
- }
- result = true;
- }
+ } catch (DocumentReferenceException de) {
+ //
+ // This exception means we tried unsuccessfully to soft-delete (workflow transition 'delete') an item that still has references to it from other records.
+ //
+ logger.info(String.format("Failed to soft-delete %s (transition from %s to %s): item is referenced, and will be deprecated instead", localItemCsid, localItemWorkflowState, sasWorkflowState));
- return result;
- }
+ // One or more of the transitions may have succeeded, so refresh the document model to make sure it
+ // reflects the current workflow state.
+ itemDocModel.refresh();
- /**
- * We need to change the local item's state to one that maps to the replication server's workflow
- * state. This might involve making multiple transitions.
- *
- * WIKI:
- * See table at https://collectionspace.atlassian.net/wiki/spaces/SDR/pages/665886940/Workflow+transitions+to+map+SAS+item+states+to+Local+item+states
- * (was https://wiki.collectionspace.org/pages/viewpage.action?pageId=162496564)
- *
- */
- private List<String> getTransitionList(String sasWorkflowState, String localItemWorkflowState) throws DocumentException {
- List<String> result = new ArrayList<String>();
- //
- // The first set of conditions maps a replication-server "project" state to a local client state of "replicated"
- //
- if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
- // Do nothing. We're good with this state
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- //
- // The second set of conditions maps a replication-server "deleted" state to a local client state of "deleted"
- //
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
- // Do nothing. We're good with this state
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- //
- // The third set of conditions maps a replication-server "replicated" state to a local state of "replicated"
- //
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
- // Do nothing. We're good with this state
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- //
- // The fourth set of conditions maps a replicatation-server "deprecated" state to a local state of "replicated_deprecated"
- //
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DEPRECATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
- // Do nothing.
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DEPRECATED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDELETE);
- //
- // The last set of conditions maps a replication-server "replicated_deleted" state to a local client state of "deleted"
- //
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_PROJECT)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_REPLICATE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED)) {
- // Do nothing. We're good with this state
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- result.add(WorkflowClient.WORKFLOWTRANSITION_DELETE);
- } else if (sasWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED) && localItemWorkflowState.equals(WorkflowClient.WORKFLOWSTATE_REPLICATED_DEPRECATED_DELETED)) {
- result.add(WorkflowClient.WORKFLOWTRANSITION_UNDEPRECATE);
- } else {
- //
- // If we get here, we've encountered a SAS workflow state that we don't recognize.
- //
- throw new DocumentException(String.format("Encountered an invalid workflow state of '%s' on a SAS authority item.", sasWorkflowState));
+ // Since we can't soft-delete it, we need to mark it as deprecated since it is soft-deleted on the SAS.
+ AuthorityServiceUtils.setAuthorityItemDeprecated(ctx, authorityResource, localParentCsid, localItemCsid, itemDocModel);
+ }
+
+ result = true;
}
return result;
import javax.ws.rs.core.UriInfo;
import org.collectionspace.authentication.AuthN;
-import org.collectionspace.authentication.spi.AuthNContext;
import org.collectionspace.services.client.AuthorityClient;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.IClientQueryParams;
import org.collectionspace.services.client.workflow.WorkflowClient;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.api.Tools;
-import org.collectionspace.services.common.authorization_mgt.AuthorizationCommon;
import org.collectionspace.services.common.config.PropertyItemUtils;
import org.collectionspace.services.common.config.ServiceConfigUtils;
import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
-import org.collectionspace.services.common.document.DocumentHandler;
import org.collectionspace.services.common.document.DocumentFilter;
+import org.collectionspace.services.common.document.DocumentHandler;
import org.collectionspace.services.common.document.ValidatorHandler;
import org.collectionspace.services.common.security.SecurityContext;
import org.collectionspace.services.common.security.SecurityContextImpl;
/** The logger. */
final Logger logger = LoggerFactory.getLogger(AbstractServiceContextImpl.class);
-
+
/** The properties. */
Map<String, Object> properties = new HashMap<String, Object>();
/** The object part map. */
private Object currentRepositorySession;
/** A reference count for the current repository session */
private int currentRepoSesssionRefCount = 0;
-
+ /** Should the current transaction be rolled back when an exception is caught */
+ private boolean rollbackOnException = true;
+
/**
* Instantiates a new abstract service context impl.
*/
/**
* Instantiates a new abstract service context impl.
- *
+ *
* @param serviceName the service name
- *
+ *
* @throws UnauthorizedException the unauthorized exception
*/
protected AbstractServiceContextImpl(String serviceName, UriInfo uriInfo) throws UnauthorizedException {
}
}
}
-
+
public int getTimeoutParam(UriInfo ui) {
int result = DEFAULT_TX_TIMEOUT;
if (timeoutString == null) {
timeoutString = queryParams.getFirst(IClientQueryParams.IMPORT_TIMOUT_PARAM);
}
-
+
if (timeoutString != null) {
- try {
+ try {
result = Integer.parseInt(timeoutString);
} catch (NumberFormatException e) {
logger.warn("Transaction timeout period parameter could not be parsed. The characters in the parameter string must all be decimal digits. The Import service will use the default timeout period instead.",
return result;
}
-
+
@Override
public int getTimeoutSecs() {
UriInfo uriInfo = this.getUriInfo();
@Override
public boolean shouldUpdateCoreValues() {
boolean recordUpdates = true;
-
+
MultivaluedMap<String, String> queryParams = getQueryParams();
String paramValue = queryParams.getFirst(IClientQueryParams.UPDATE_CORE_VALUES);
if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.FALSE.toString())) { // Find our if the caller wants us to record updates
} else if (paramValue != null && paramValue.equals(Long.toString(0))) {
recordUpdates = false;
}
-
+
return recordUpdates;
}
-
+
/**
* Default value is 'FALSE'
* If this returns true, it means that the refname values in referencing objects (records that reference authority or vocabulary terms) will be updated
@Override
public boolean shouldForceUpdateRefnameReferences() {
boolean forceUpdates = false;
-
+
MultivaluedMap<String, String> queryParams = getQueryParams();
String paramValue = queryParams.getFirst(IClientQueryParams.FORCE_REFNAME_UPDATES);
if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.TRUE.toString())) { // Find our if the caller wants us to force refname updates
} else if (paramValue != null && paramValue.equals(Long.toString(1))) {
forceUpdates = true;
}
-
+
return forceUpdates;
}
-
-
+
+
/* (non-Javadoc)
* @see org.collectionspace.services.common.context.ServiceContext#getCommonPartLabel()
*/
/**
* Gets the properties for part.
- *
+ *
* @param partLabel the part label
- *
+ *
* @return the properties for part
*/
public List<PropertyItemType> getPropertiesForPart(String partLabel) {
/**
* Gets the common part properties.
- *
+ *
* @return the common part properties
*/
public List<PropertyItemType> getCommonPartProperties() {
// object.
return (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
}
-
+
@Override
public String getTenantQualifiedDoctype(String docType) {
// If they have not overridden the setting, use the type of the service
// object.
String result = ServiceBindingUtils.getTenantQualifiedDocType(this.getTenantId(), docType);
-
+
return result;
}
-
+
@Override
public String getTenantQualifiedDoctype() {
String docType = (overrideDocumentType != null) ? overrideDocumentType : serviceBinding.getObject().getName();
/**
* Helps to filter for queries that either want to include or exclude documents in deleted workflow states.
- *
+ *
* By default, we return *all* objects/records.
- *
+ *
* @param queryParams
* @return
*/
String includeDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_DELETED_QP);
String includeOnlyDeleted = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_ONLY_DELETED_QP); // if set to true, it doesn't matter what the value is for 'includeDeleted'
-
- if (includeOnlyDeleted != null) {
+
+ if (includeOnlyDeleted != null) {
if (Tools.isTrue(includeOnlyDeleted)) {
//
// A value of 'true' for 'includeOnlyDeleted' means we're looking *only* for soft-deleted records/documents.
//
result = String.format("(ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s' OR ecm:currentLifeCycleState = '%s')",
- WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_DELETED,
WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
}
// Ensure we don't return soft-deleted records
//
result = String.format("(ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s' AND ecm:currentLifeCycleState <> '%s')",
- WorkflowClient.WORKFLOWSTATE_DELETED,
+ WorkflowClient.WORKFLOWSTATE_DELETED,
WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED,
WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
}
return result;
}
-
+
/**
* Creates the document handler instance.
- *
+ *
* @return the document handler
- *
+ *
* @throws Exception the exception
*/
private DocumentHandler createDocumentHandlerInstance() throws Exception {
docHandler = ServiceConfigUtils.createDocumentHandlerInstance(tenantBinding, serviceBinding);
-
+
//
// The docHandler for a Service can be null, but usually is not.
//
docFilter.setPagination(queryParameters);
String workflowWhereClause = buildWorkflowWhereClause(queryParameters);
if (workflowWhereClause != null) {
- docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
- }
-
+ docFilter.appendWhereClause(workflowWhereClause, IQueryManager.SEARCH_QUALIFIER_AND);
+ }
+
}
docHandler.setDocumentFilter(docFilter);
}
-
+
return docHandler;
}
documentFilter.setPagination(queryParams);
return result;
}
-
+
/*
* If this element is set in the service binding then use it otherwise
* assume that asserts are NOT disabled.
result = (disableAsserts != null) ? disableAsserts : false;
return result;
}
-
+
/* (non-Javadoc)
* @see org.collectionspace.services.common.context.ServiceContext#getValidatorHandlers()
*/
valHandlers = handlers;
return valHandlers;
}
-
+
/**
* If one doesn't already exist, use the default properties filename to load a set of properties that
* will be used to create an HTTP client to a CollectionSpace instance.
if (authorityClient == null) {
result = authorityClient = getClient(CollectionSpaceClient.DEFAULT_CLIENT_PROPERTIES_FILENAME);
}
-
+
return result;
}
-
+
/*
* Use the properties filename passed in to load the URL and credentials that will be used
* to create a new HTTP client.
- *
+ *
* Never uses or resets the this.authorityClient member. Always creates a new HTTP client using
* the loaded properties.
- *
+ *
* (non-Javadoc)
* @see org.collectionspace.services.common.context.ServiceContext#getClient(java.lang.String)
*/
@Override
public AuthorityClient getClient(String clientPropertiesFilename) throws Exception {
AuthorityClient result = null;
-
+
Properties inProperties = Tools.loadProperties(clientPropertiesFilename, true);
result = getClient(inProperties);
-
+
return result;
}
-
+
public AuthorityClient getClient(Properties inProperties) throws Exception {
AuthorityClient result = null;
-
+
String authorityClientClazz = getServiceBinding().getClientHandler();
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
authorityClientClazz = authorityClientClazz.trim();
logger.warn(msg);
logger.trace(msg, e);
}
-
+
return result;
}
-
+
@Override
public AuthorityClient getClient(RemoteClientConfig remoteClientConfig) throws Exception {
AuthorityClient result = null;
-
+
Properties properties = new Properties();
properties.setProperty(AuthorityClient.URL_PROPERTY, remoteClientConfig.getUrl());
properties.setProperty(AuthorityClient.USER_PROPERTY, remoteClientConfig.getUser());
if (tenantName != null) {
properties.setProperty(AuthorityClient.TENANT_NAME_PROPERTY, tenantName);
}
-
+
result = getClient(properties);
-
+
return result;
}
-
+
@Override
public void addValidatorHandler(ValidatorHandler<IT, OT> validator) throws Exception {
if (valHandlers == null) {
/* (non-Javadoc)
* @see org.collectionspace.services.common.context.ServiceContext#getQueryParams()
- *
+ *
* When we first created these services, the RESTEasy query parameters used to be a modifiable map. That changed in a
* more recent version of RESTEasy, so we need to make a copy of the params into a modifiable map and return it instead.
*/
public UriInfo getUriInfo() {
return this.uriInfo;
}
-
+
@Override
public Request getRequestInfo() {
return this.requestInfo;
}
-
+
@Override
public void setRequestInfo(Request requestInfo) {
this.requestInfo = requestInfo;
}
-
+
/*
* We expect the 'currentRepositorySession' member to be set only once per instance. Also, we expect only one open repository session
* per HTTP request. We'll log an error if we see more than one attempt to set a service context's current repo session.
logger.error(errMsg);
throw new Exception(errMsg);
}
-
+
currentRepositorySession = repoSession;
this.currentRepoSesssionRefCount++;
}
-
+
@Override
public void clearCurrentRepositorySession() {
if (this.currentRepoSesssionRefCount > 0) {
currentRepoSesssionRefCount--;
}
-
+
if (currentRepoSesssionRefCount == 0) {
this.currentRepositorySession = null;
}
-
+
if (currentRepoSesssionRefCount < 0) {
throw new RuntimeException("Attempted to clear/close a repository session that has already been cleared/closed.");
}
}
-
+
@Override
public Object getCurrentRepositorySession() {
// TODO Auto-generated method stub
return currentRepositorySession;
- }
+ }
- @Override
+ @Override
public RepositoryDomainType getRepositoryDomain() {
return repositoryDomain;
}
- @Override
+ @Override
public void setRepositoryDomain(RepositoryDomainType repositoryDomain) {
this.repositoryDomain = repositoryDomain;
}
-
+
/**
* Check for a query parameter that indicates if we should force a sync even if the revision numbers indicate otherwise.
* @return
@Override
public boolean shouldForceSync() {
boolean forceSync = false;
-
+
MultivaluedMap<String, String> queryParams = getQueryParams();
String paramValue = queryParams.getFirst(IClientQueryParams.FORCE_SYCN);
if (paramValue != null && paramValue.equalsIgnoreCase(Boolean.TRUE.toString())) { // Find our if the caller wants us to force refname updates
} else if (paramValue != null && paramValue.equals(Long.toString(1))) {
forceSync = true;
}
-
+
return forceSync;
}
-
+
+ @Override
+ public void setRollbackOnException(boolean rollbackOnException) {
+ this.rollbackOnException = rollbackOnException;
+ }
+
+ @Override
+ public boolean isRollbackOnException() {
+ return this.rollbackOnException;
+ }
}
/** The Constant PART_COMMON_LABEL. */
public static final String PART_COMMON_LABEL = "common";
/** Used to qualify document types **/
- public static final String TENANT_SUFFIX = "Tenant";
+ public static final String TENANT_SUFFIX = "Tenant";
- /**
+ /**
* Tells the TransactionManager to use the default value. The default value can
* be set in this file:
* services/JaxRsServiceProvider/src/main/webapp/META-INF/context.xml
* transactionTimeoutSeconds="300"/>
* See the following documentation page for more details:
* http://docs.oracle.com/javaee/7/api/javax/transaction/TransactionManager.html#setTransactionTimeout(int)
- *
+ *
*/
public static final int DEFAULT_TX_TIMEOUT = 0;
-
- /*
+
+ /*
* Sets the current/open repository session
*/
public void setCurrentRepositorySession(Object repoSession) throws Exception;
-
+
/*
* Decrements the context's repo session ref count and nulls it if the count becomes 0.
*/
public void clearCurrentRepositorySession();
-
+
/*
* If a current repository session exists, returns it.
*/
public Object getCurrentRepositorySession();
-
+
/**
* getSecurityContext is contains security info. for the service layer
*/
* @return
*/
public boolean shouldUpdateCoreValues();
-
+
/**
* getTimeoutSecs();
*/
public int getTimeoutSecs();
-
+
/**
* getUserId get authenticated user's userId
*/
* @return service name
*/
public String getDocumentType();
-
+
/**
* Returns a tenant qualified document type.
- *
+ *
*/
public String getTenantQualifiedDoctype();
-
+
/**
* Returns a tenant qualified document type.
- *
+ *
*/
public String getTenantQualifiedDoctype(String docType);
* @return repository domain for the tenant
*/
public String getRepositoryDomainName();
-
+
/*
* The name of the repository/db for the current context
*/
public String getRepositoryName() throws Exception;
-
+
/*
* Get's the name/label used to create the storage container (folder or directory name)
*/
- public String getRepositoryDomainStorageName();
+ public String getRepositoryDomainStorageName();
/**
* getRepositoryClientName returns the repository client name as
* @return the input
*/
public IT getInput();
-
+
/**
* setInput is used to set request input before starting to
* process input data
* @param map the map of service names to resource instances.
*/
public void setResourceMap(ResourceMap map);
-
+
/**
- *
+ *
* @param jaxsRsRequest - Keep track of the JAX-RS request information
*/
public void setRequestInfo(Request jaxsRsRequest);
public Map<String, ObjectPartType> getPartsMetadata();
/**
- * getCommonPartLabel returns label for common part of a service
+ * getCommonPartLabel returns label for common part of a service
* @return label
*/
public String getCommonPartLabel();
/**
* getCommonPartLabel returns label for common part of a specified schema.
- * This is useful for sub-resources.
+ * This is useful for sub-resources.
* @return label
*/
public String getCommonPartLabel(String schemaName);
/**
* Gets the document hanlder.
- *
+ *
* @param queryParams the query params
- *
+ *
* @return the document hanlder
- *
+ *
* @throws Exception the exception
*/
public DocumentHandler getDocumentHandler(MultivaluedMap<String, String> queryParams) throws Exception;
/**
* Gets the query params.
- *
+ *
* @return the query params
*/
public MultivaluedMap<String, String> getQueryParams();
/**
* Sets the query params.
- *
+ *
* @param queryParams the query params
*/
public void setQueryParams(MultivaluedMap<String, String> queryParams);
public void setRepositoryDomain(RepositoryDomainType repositoryDomain);
public CollectionSpaceClient getClient() throws Exception;
-
+
public CollectionSpaceClient getClient(String clientProperitesFilename) throws Exception;
-
+
public CollectionSpaceClient getClient(RemoteClientConfig remoteClientConfig) throws Exception;
/**
* @return the JAX-RS resource of service for the current context.
- * @throws Exception
+ * @throws Exception
*/
public CollectionSpaceResource<IT, OT> getResource() throws Exception;
/**
* @return the JAX-RS resource of service for the current context.
- * @throws Exception
+ * @throws Exception
*/
public CollectionSpaceResource<IT, OT> getResource(
String serviceName) throws Exception;
public boolean shouldForceSync();
/**
- *
+ *
* @return The JAX-RS request information
*/
Request getRequestInfo();
-
+
/**
- *
+ *
*/
public TransactionContext openConnection() throws TransactionException; // Only 1 active connection at a time
-
+
/**
- *
+ *
*/
public boolean hasActiveConnection();
-
+
/**
- *
+ *
*/
public void closeConnection() throws TransactionException; // Assumes there's been a call to getConnection.
-
+
/**
- * @throws TransactionException
- *
+ * @throws TransactionException
+ *
*/
void setTransactionContext(TransactionContext transactionCtx) throws TransactionException; // For sharing a transaction context with another service context.
-
+
/**
- *
+ *
*/
public boolean isTransactionContextShared() throws TransactionException;
/**
- *
+ *
* @return
*/
TransactionContext getCurrentTransactionContext();
-}
-
-
+ public void setRollbackOnException(boolean rollbackOnException);
+ public boolean isRollbackOnException();
+}
import javax.sql.rowset.CachedRowSet;
import javax.ws.rs.core.MultivaluedMap;
-import org.collectionspace.services.lifecycle.TransitionDef;
-import org.collectionspace.services.nuxeo.util.CSReindexFulltextRoot;
-import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+//
+// CSPACE-5036 - How to make CMISQL queries from Nuxeo
+//
+import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
+import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory;
import org.collectionspace.services.client.CollectionSpaceClient;
import org.collectionspace.services.client.IQueryManager;
import org.collectionspace.services.client.PoxPayloadIn;
import org.collectionspace.services.client.Profiler;
import org.collectionspace.services.client.index.IndexClient;
import org.collectionspace.services.client.workflow.WorkflowClient;
+import org.collectionspace.services.common.CSWebApplicationException;
+import org.collectionspace.services.common.ServiceMain;
+import org.collectionspace.services.common.api.Tools;
+import org.collectionspace.services.common.config.ConfigUtils;
+import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
+import org.collectionspace.services.common.config.TenantBindingUtils;
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.storage.JDBCTools;
-import org.collectionspace.services.common.storage.PreparedStatementSimpleBuilder;
import org.collectionspace.services.common.document.BadRequestException;
import org.collectionspace.services.common.document.DocumentException;
import org.collectionspace.services.common.document.DocumentFilter;
import org.collectionspace.services.common.document.DocumentHandler;
-import org.collectionspace.services.common.document.DocumentNotFoundException;
import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.document.DocumentNotFoundException;
import org.collectionspace.services.common.document.DocumentWrapper;
import org.collectionspace.services.common.document.DocumentWrapperImpl;
import org.collectionspace.services.common.document.TransactionException;
-import org.collectionspace.services.common.CSWebApplicationException;
-import org.collectionspace.services.common.ServiceMain;
-import org.collectionspace.services.common.api.Tools;
-import org.collectionspace.services.common.config.ConfigUtils;
-import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
-import org.collectionspace.services.common.config.TenantBindingUtils;
+import org.collectionspace.services.common.query.QueryContext;
+import org.collectionspace.services.common.repository.RepositoryClient;
+import org.collectionspace.services.common.storage.JDBCTools;
import org.collectionspace.services.common.storage.PreparedStatementBuilder;
+import org.collectionspace.services.common.storage.PreparedStatementSimpleBuilder;
import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthorityItemSpecifier;
import org.collectionspace.services.config.service.ServiceBindingType;
-import org.collectionspace.services.config.tenant.TenantBindingType;
import org.collectionspace.services.config.tenant.RepositoryDomainType;
-
-//
-// CSPACE-5036 - How to make CMISQL queries from Nuxeo
-//
-import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
-import org.apache.chemistry.opencmis.commons.server.CallContext;
-import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
-import org.apache.chemistry.opencmis.server.shared.ThresholdOutputStreamFactory;
+import org.collectionspace.services.config.tenant.TenantBindingType;
+import org.collectionspace.services.lifecycle.TransitionDef;
+import org.collectionspace.services.nuxeo.util.CSReindexFulltextRoot;
+import org.collectionspace.services.nuxeo.util.NuxeoUtils;
import org.nuxeo.common.utils.IdUtils;
import org.nuxeo.ecm.core.api.ClientException;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
-import org.nuxeo.ecm.core.api.IterableQueryResult;
-import org.nuxeo.ecm.core.api.VersioningOption;
-import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
+import org.nuxeo.ecm.core.api.IterableQueryResult;
import org.nuxeo.ecm.core.api.PathRef;
-import org.nuxeo.runtime.api.Framework;
-import org.nuxeo.runtime.transaction.TransactionRuntimeException;
+import org.nuxeo.ecm.core.api.VersioningOption;
+import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
import org.nuxeo.ecm.core.opencmis.bindings.NuxeoCmisServiceFactory;
import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService;
-import org.nuxeo.elasticsearch.api.ElasticSearchAdmin;
-import org.nuxeo.elasticsearch.api.ElasticSearchIndexing;
-import org.nuxeo.elasticsearch.api.ElasticSearchService;
import org.nuxeo.elasticsearch.ElasticSearchComponent;
+import org.nuxeo.elasticsearch.api.ElasticSearchService;
+import org.nuxeo.runtime.api.Framework;
+import org.nuxeo.runtime.transaction.TransactionRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
handler.complete(Action.CREATE, wrapDoc);
return id;
} catch (BadRequestException bre) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw bre;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
if (logger.isDebugEnabled()) {
logger.debug("Call to low-level Nuxeo document create call failed: ", e);
}
CSReindexFulltextRoot indexer = new CSReindexFulltextRoot(repoSession);
indexer.reindexFulltext(0, 0, queryString);
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
if (logger.isDebugEnabled()) {
logger.debug("Caught exception trying to reindex Nuxeo repository ", e);
}
result = true;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
if (logger.isDebugEnabled()) {
logger.debug("Caught exception trying to reindex Nuxeo repository ", e);
}
result = handler.handle(Action.SYNC, wrapDoc);
handler.complete(Action.SYNC, wrapDoc);
} catch (IllegalArgumentException iae) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw iae;
} catch (DocumentException de) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw de;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
if (logger.isDebugEnabled()) {
logger.debug("Caught exception ", e);
}
result = handler.handle(Action.SYNC, wrapDoc);
handler.complete(Action.SYNC, wrapDoc);
} catch (IllegalArgumentException iae) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw iae;
} catch (DocumentException de) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw de;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw new NuxeoDocumentException(e);
} finally {
if (repoSession != null) {
doc.refresh();
handler.complete(Action.UPDATE, wrapDoc);
} catch (BadRequestException bre) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw bre;
} catch (DocumentException de) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
+
throw de;
} catch (CSWebApplicationException wae) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw wae;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw new NuxeoDocumentException(e);
} finally {
if (repoSession != null) {
handler.complete(Action.DELETE, wrapDoc);
}
} catch (DocumentException de) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw de;
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ if (ctx.isRollbackOnException()) {
+ rollbackTransaction(repoSession);
+ }
throw new NuxeoDocumentException(e);
} finally {
if (repoSession != null) {
logger.debug("Path to Workspaces root: " + workspacesRoot.getPathAsString());
}
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ rollbackTransaction(repoSession);
if (logger.isDebugEnabled()) {
logger.debug("Could not create tenant domain name=" + repositoryDomain.getStorageName() + " caught exception ", e);
}
+ " id=" + workspaceId);
}
} catch (Throwable e) {
- rollbackTransaction(repoSession);
+ rollbackTransaction(repoSession);
if (logger.isDebugEnabled()) {
logger.debug("createWorkspace caught exception ", e);
}