From 18dfc0f20d0f6e4ae5c5b183421c98d68a645618 Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Tue, 10 Apr 2012 16:07:52 -0700 Subject: [PATCH] Support for workflow by transition ID now working. Also, more permission related bug fixes added. --- .../services/client/PoxPayloadIn.java | 6 + .../client/workflow/WorkflowClient.java | 6 +- ...tMultiPartCollectionSpaceResourceImpl.java | 94 +++++++++++++-- ...CollectionSpaceServiceContextListener.java | 54 +-------- .../services/common/ServiceMain.java | 70 +++-------- .../AuthorizationCommon.java | 50 +++++--- .../authorization_mgt/AuthorizationStore.java | 2 +- .../common/document/DocumentHandler.java | 2 + .../common/security/SecurityInterceptor.java | 2 +- .../storage/jpa/JpaDocumentHandler.java | 9 +- .../nuxeo/WorkflowDocumentModelHandler.java | 31 ++--- .../client/java/DocumentModelHandler.java | 112 +++++++++++++++++- 12 files changed, 284 insertions(+), 154 deletions(-) diff --git a/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java b/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java index 6d9aa0f4d..e887e9886 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java +++ b/services/client/src/main/java/org/collectionspace/services/client/PoxPayloadIn.java @@ -27,6 +27,12 @@ public class PoxPayloadIn extends PoxPayload { private final Logger logger = LoggerFactory.getLogger(this.getClass()); + public PoxPayloadIn(String payloadName, Object jaxbObject, String partLabel) { + setPayloadName(payloadName); + PayloadInputPart inputPart = createPart(partLabel, jaxbObject, null); + this.addPart(inputPart); + } + /* * Parse the POX 'xmlPayload' into individual parts. Each part is saved * as a DOM4j Element and, if possible, a JAXB object instance as well. diff --git a/services/client/src/main/java/org/collectionspace/services/client/workflow/WorkflowClient.java b/services/client/src/main/java/org/collectionspace/services/client/workflow/WorkflowClient.java index 4e5ddc2eb..6db639d37 100644 --- a/services/client/src/main/java/org/collectionspace/services/client/workflow/WorkflowClient.java +++ b/services/client/src/main/java/org/collectionspace/services/client/workflow/WorkflowClient.java @@ -41,7 +41,11 @@ public class WorkflowClient extends AbstractCommonListPoxServiceClientImpl ctx, String transition) { + TransitionDef result = null; + + try { + Lifecycle lifecycle = ctx.getDocumentHandler().getLifecycle(); + List transitionDefList = lifecycle.getTransitionDefList().getTransitionDef(); + Iterator iter = transitionDefList.iterator(); + boolean found = false; + while (iter.hasNext() && found == false) { + TransitionDef transitionDef = iter.next(); + if (transitionDef.getName().equalsIgnoreCase(transition)) { + result = transitionDef; + found = true; + } + } + } catch (Exception e) { + logger.error("Exception trying to retreive life cycle information for: " + ctx.getDocumentType()); + } + + return result; + } + + private PoxPayloadIn synthEmptyWorkflowInput() { + PoxPayloadIn result = null; + + PoxPayloadOut output = new PoxPayloadOut(WorkflowClient.SERVICE_PAYLOAD_NAME); + WorkflowCommon workflowCommons = new WorkflowCommon(); + PayloadOutputPart commonPart = output.addPart(WorkflowClient.SERVICE_COMMONPART_NAME, workflowCommons); + String payloadXML = output.toXML(); + try { + result = new PoxPayloadIn(payloadXML); + } catch (DocumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return result; + } + @PUT - @Path("{csid}" + WorkflowClient.SERVICE_PATH) - public byte[] updateWorkflow(@PathParam("csid") String csid, String xmlPayload) { + @Path("{csid}" + WorkflowClient.SERVICE_PATH + "/" + "{transition}") + public byte[] updateWorkflowWithTransition(@PathParam("csid") String csid, + @PathParam("transition") String transition) { PoxPayloadOut result = null; try { + PoxPayloadIn input = new PoxPayloadIn(WorkflowClient.SERVICE_PAYLOAD_NAME, new WorkflowCommon(), + WorkflowClient.SERVICE_COMMONPART_NAME); + ServiceContext parentCtx = createServiceContext(); String parentWorkspaceName = parentCtx.getRepositoryWorkspaceName(); - - PoxPayloadIn workflowUpdate = new PoxPayloadIn(xmlPayload); - MultipartServiceContext ctx = (MultipartServiceContext) createServiceContext(WorkflowClient.SERVICE_NAME, workflowUpdate); + + 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); @@ -181,4 +256,5 @@ public abstract class AbstractMultiPartCollectionSpaceResourceImpl extends Abstr } return result.getBytes(); } + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/CollectionSpaceServiceContextListener.java b/services/common/src/main/java/org/collectionspace/services/common/CollectionSpaceServiceContextListener.java index f7c0c251e..d9f857f5a 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/CollectionSpaceServiceContextListener.java +++ b/services/common/src/main/java/org/collectionspace/services/common/CollectionSpaceServiceContextListener.java @@ -15,70 +15,22 @@ public class CollectionSpaceServiceContextListener implements ServletContextList @Override public void contextInitialized(ServletContextEvent event) { - try { + try { // // Initialize/start the Nuxeo EP server instance and create/retrieve the service workspaces // ServletContext servletContext = event.getServletContext(); ServiceMain svcMain = ServiceMain.getInstance(servletContext); - { - System.out.print("About to retrieveAllWorkspaceIds - Pausing 4:5 seconds for you to attached the debugger"); - long startTime, currentTime; - currentTime = startTime = System.currentTimeMillis(); - long stopTime = startTime + 5 * 1000; //5 seconds - do { - if (currentTime % 1000 == 0) { - System.out.print("."); - } - currentTime = System.currentTimeMillis(); - } while (currentTime < stopTime); - - System.out.println(); - System.out.println("Resuming cspace services initialization."); - } - svcMain.retrieveAllWorkspaceIds(); - - { - System.out.print("About to firePostInitHandlers - Pausing 5:5 seconds for you to attached the debugger"); - long startTime, currentTime; - currentTime = startTime = System.currentTimeMillis(); - long stopTime = startTime + 5 * 1000; //5 seconds - do { - if (currentTime % 1000 == 0) { - System.out.print("."); - } - currentTime = System.currentTimeMillis(); - } while (currentTime < stopTime); - - System.out.println(); - System.out.println("Resuming cspace services initialization."); - } // // Invoke all post-initialization handlers, passing in a DataSource instance of the Nuxeo db. // Typically, these handlers modify column types and add indexes to the Nuxeo db schema. // svcMain.firePostInitHandlers(); - - { - System.out.print("Finished to firePostInitHandlers - Pausing 6:5 seconds for you to attached the debugger"); - long startTime, currentTime; - currentTime = startTime = System.currentTimeMillis(); - long stopTime = startTime + 5 * 1000; //5 seconds - do { - if (currentTime % 1000 == 0) { - System.out.print("."); - } - currentTime = System.currentTimeMillis(); - } while (currentTime < stopTime); - - System.out.println(); - System.out.println("Resuming cspace services initialization."); - } - - } catch (Exception e) { + + } catch (Throwable e) { e.printStackTrace(); //fail here System.err.println("[ERROR] The CollectionSpace Services could not initialize. Please see the log files for details."); diff --git a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java index 2634d46ab..0c98156ee 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java +++ b/services/common/src/main/java/org/collectionspace/services/common/ServiceMain.java @@ -101,23 +101,6 @@ public class ServiceMain { try { //assume the worse initFailed = true; - - { - System.out.print("About to init ServiceMain - Pausing 3:5 seconds for you to attached the debugger"); - long startTime, currentTime; - currentTime = startTime = System.currentTimeMillis(); - long stopTime = startTime + 5 * 1000; //5 seconds - do { - if (currentTime % 1000 == 0) { - System.out.print("."); - } - currentTime = System.currentTimeMillis(); - } while (currentTime < stopTime); - - System.out.println(); - System.out.println("Resuming cspace services initialization."); - } - temp.initialize(); //celebrate success initFailed = false; @@ -142,41 +125,8 @@ public class ServiceMain { } private void initialize() throws Exception { - - setDataSources(); - setServerRootDir(); - readConfig(); - propagateConfiguredProperties(); - // - // Create all the default user accounts - // - try { - AuthorizationCommon.createDefaultPermissions(tenantBindingConfigReader); - - if (logger.isDebugEnabled() == true) { - System.out.print("Pausing 1:5 seconds for you to attached the debugger"); - long startTime, currentTime; - currentTime = startTime = System.currentTimeMillis(); - long stopTime = startTime + 5 * 1000; //5 seconds - do { - if (currentTime % 1000 == 0) { - System.out.print("."); - } - currentTime = System.currentTimeMillis(); - } while (currentTime < stopTime); - - System.out.println(); - System.out.println("Resuming cspace services initialization."); - } - - AuthorizationCommon.createDefaultAccounts(tenantBindingConfigReader); - - } catch(Exception e) { - logger.error("Default accounts setup failed with exception(s): " + e.getLocalizedMessage()); - } - - if (logger.isDebugEnabled() == true) { - System.out.print("Pausing 2:5 seconds for you to attached the debugger"); + if (logger.isTraceEnabled() == true) { + System.out.print("About to initialize ServiceMain singleton - Pausing 5 seconds for you to attached the debugger"); long startTime, currentTime; currentTime = startTime = System.currentTimeMillis(); long stopTime = startTime + 5 * 1000; //5 seconds @@ -190,7 +140,11 @@ public class ServiceMain { System.out.println(); System.out.println("Resuming cspace services initialization."); } - + + setDataSources(); + setServerRootDir(); + readConfig(); + propagateConfiguredProperties(); // // Start up and initialize our embedded Nuxeo server instance // @@ -206,7 +160,15 @@ public class ServiceMain { // throw new RuntimeException("Unknown CollectionSpace services client type: " + getClientType()); } - + // + // Create all the default user accounts and permissions + // + try { + AuthorizationCommon.createDefaultPermissions(tenantBindingConfigReader); + AuthorizationCommon.createDefaultAccounts(tenantBindingConfigReader); + } catch(Throwable e) { + logger.error("Default accounts and permissions setup failed with exception(s): " + e.getLocalizedMessage(), e); + } } /** diff --git a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java index 0f1d9aa3f..bf4113d02 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java +++ b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java @@ -275,26 +275,37 @@ public class AuthorizationCommon { ActionGroup actionGroup) { Permission result = null; + String workFlowServiceSuffix; + String transitionName; + if (transitionDef != null) { + transitionName = transitionDef.getName(); + workFlowServiceSuffix = WorkflowClient.SERVICE_AUTHZ_SUFFIX; + } else { + transitionName = ""; //since the transitionDef was null, we're assuming that this is the base workflow permission to be created + workFlowServiceSuffix = WorkflowClient.SERVICE_PATH; + } String tenantId = tenantBinding.getId(); String resourceName = "/" + serviceBinding.getName().toLowerCase().trim() - + WorkflowClient.SERVICE_AUTHZ_SUFFIX - + transitionDef.getName(); + + workFlowServiceSuffix + + transitionName; String description = "A generated workflow permission for actiongroup " + actionGroup.name; result = createPermission(tenantId, resourceName, description, actionGroup); if (logger.isDebugEnabled() == true) { logger.debug("Generated a workflow permission: " + result.getResourceName() - + ":" + transitionDef.getName() - + ":" + "tenant id=" + result.getTenantId()); + + ":" + transitionName + + ":" + "tenant id=" + result.getTenantId() + + ":" + actionGroup.name); } return result; } - private static PermissionRole createPermissionRole(Permission permission, + private static PermissionRole createPermissionRole(EntityManager em, + Permission permission, Role role, boolean enforceTenancy) throws Exception { @@ -758,9 +769,10 @@ public class AuthorizationCommon { private static TransitionDefList getTransitionDefList(TenantBindingType tenantBinding, ServiceBindingType serviceBinding) { TransitionDefList result = null; try { + String serviceObjectName = serviceBinding.getObject().getName(); DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance( tenantBinding, serviceBinding); - Lifecycle lifecycle = docHandler.getLifecycle(); + Lifecycle lifecycle = docHandler.getLifecycle(serviceObjectName); if (lifecycle != null) { result = lifecycle.getTransitionDefList(); } @@ -804,40 +816,46 @@ public class AuthorizationCommon { Role readonlyRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_READER); for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) { try { + em.getTransaction().begin(); + // + // For the default admin role, create the base workflow (aka, "/workflow" permissions for the service. + Permission baseAdminPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_CRUDL); + persist(em, baseAdminPerm, adminRole, true); + // + // For the default read-only role, create the base workflow (aka, "/workflow" permissions for the service. + Permission baseReadonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, null, ACTIONGROUP_RL); + persist(em, baseReadonlyPerm, readonlyRole, true); + // + // Next, create a permission for each workflow transition supported by the service's document type. + // TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding); for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) { - em.getTransaction().begin(); - /* // // Create the permission for the admin role - // Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_CRUDL); persist(em, adminPerm, adminRole, true); - */ // // Create the permission for the read-only role Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, ACTIONGROUP_RL); Profiler profiler = new Profiler(AuthorizationCommon.class, 1); profiler.start("createDefaultPermissions started:" + readonlyPerm.getCsid()); - persist(em, readonlyPerm, readonlyRole, true); + persist(em, readonlyPerm, readonlyRole, true); // Persist/store the permission and permrole records and related Spring Security info profiler.stop(); logger.debug("Finished full perm generation for " + ":" + tenantBinding.getId() + ":" + serviceBinding.getName() + ":" + transitionDef.getName() + ":" + ACTIONGROUP_RL - + ":" + profiler.getCumulativeTime()); - + + ":" + profiler.getCumulativeTime()); /* // // Create the permission for the super-admin role. Note we use the same "adminPerm" instance we used for the "adminPermRole" instance // persist(em, adminPerm, superRole, false); - */ - em.getTransaction().commit(); } + em.getTransaction().commit(); } catch (IllegalStateException e) { logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services. } @@ -889,7 +907,7 @@ public class AuthorizationCommon { // Create a PermissionRoleRel (the database relation table for the permission and role) PermissionRoleRel permRoleRel = findPermRoleRel(em, permission.getCsid(), role.getCsid()); if (permRoleRel == null) { - PermissionRole permRole = createPermissionRole(permission, role, enforceTenancy); + PermissionRole permRole = createPermissionRole(em, permission, role, enforceTenancy); List permRoleRels = new ArrayList(); PermissionRoleUtil.buildPermissionRoleRel(em, permRole, SubjectType.ROLE, permRoleRels, false /*not for delete*/); for (PermissionRoleRel prr : permRoleRels) { diff --git a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationStore.java b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationStore.java index 281b88756..3ff03ee6d 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationStore.java +++ b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationStore.java @@ -162,7 +162,7 @@ public class AuthorizationStore { } if (entityExists == true) { - em.merge(entity); + //em.merge(entity); FIXME: Leave commented out until we address CSPACE-5031 } else { em.persist(entity); } 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 bc1c86e01..e85acf763 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 @@ -46,6 +46,8 @@ public interface DocumentHandler { } public Lifecycle getLifecycle(); + + public Lifecycle getLifecycle(String serviceObjectName); /** * getServiceContext returns service context diff --git a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java index 6187754a8..c6a3ef5e7 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java +++ b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityInterceptor.java @@ -136,7 +136,7 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn // They passed the first round of security checks, so now let's check to see if they're trying // to perform a workflow state change and make sure they are allowed to to this. // - if (uriPath.endsWith(WorkflowClient.SERVICE_PATH_COMPONENT) == true) { + if (uriPath.contains(WorkflowClient.SERVICE_PATH_COMPONENT) == true) { String workflowSubResName = SecurityUtils.getResourceName(request.getUri()); res = new URIResourceImpl(AuthN.get().getCurrentTenantId(), workflowSubResName, httpMethod); if (authZ.isAccessAllowed(res) == false) { 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 27a1c3a6d..ab9623b73 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 @@ -37,7 +37,14 @@ public abstract class JpaDocumentHandler return (TL) commonList; } + public Lifecycle getLifecycle(String docTypeName) { + Lifecycle result = new Lifecycle(); + result.setName("Life cycles are not supported by the JPA-based services."); + return result; // NOTE: As of 3/2012, none of the JPA-based services support a life cycle type. + } + + @Override public Lifecycle getLifecycle() { - return null; // NOTE: As of 3/2012, none of the JPA-based services support a life cycle type. + return getLifecycle(null); // NOTE: As of 3/2012, none of the JPA-based services support a life cycle type. } } 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 14a1e7801..29f297b59 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,6 +23,7 @@ */ package org.collectionspace.services.common.workflow.service.nuxeo; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -32,10 +33,13 @@ 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.workflow.WorkflowCommon; import org.nuxeo.ecm.core.api.ClientException; @@ -135,26 +139,23 @@ public class WorkflowDocumentModelHandler */ @Override - protected void fillPart(PayloadInputPart part, DocumentModel docModel, - ObjectPartType partMeta, Action action, - ServiceContext ctx) - throws Exception { - String toState = null; + public void fillAllParts(DocumentWrapper wrapDoc, Action action) throws Exception { + String transitionToFollow = null; + + DocumentModel docModel = wrapDoc.getWrappedObject(); + MultipartServiceContext ctx = (MultipartServiceContext) getServiceContext(); try { - WorkflowCommon workflowsCommon = (WorkflowCommon) part.getBody(); - toState = getTransitionFromState(workflowsCommon.getCurrentLifeCycleState()); - docModel.followTransition(toState); + TransitionDef transitionDef = (TransitionDef)this.getServiceContext().getProperty(WorkflowClient.TRANSITION_ID); + transitionToFollow = transitionDef.getName(); + docModel.followTransition(transitionToFollow); } catch (Exception e) { String msg = "Unable to follow workflow transition to state = " - + toState; - if (logger.isDebugEnabled() == true) { - logger.debug(msg, e); - } - ClientException ce = new ClientException("Unable to follow workflow transition to state = " - + toState); + + transitionToFollow; + logger.error(msg, e); + ClientException ce = new ClientException("Unable to follow workflow transition: " + transitionToFollow); throw ce; } - } + } } diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java index 3f21659aa..9fb971bd5 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocumentModelHandler.java @@ -23,29 +23,37 @@ */ package org.collectionspace.services.nuxeo.client.java; +import java.util.Collection; import java.util.List; import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; -import org.collectionspace.services.common.api.FileTools; import org.collectionspace.services.common.authorityref.AuthorityRefList; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils; import org.collectionspace.services.common.document.AbstractMultipartDocumentHandlerImpl; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentWrapper; -import org.collectionspace.services.lifecycle.Lifecycle; import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.collectionspace.services.common.profile.Profiler; import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.repository.RepositoryClientFactory; import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo; +import org.collectionspace.services.lifecycle.Lifecycle; +import org.collectionspace.services.lifecycle.State; +import org.collectionspace.services.lifecycle.StateList; +import org.collectionspace.services.lifecycle.TransitionDef; +import org.collectionspace.services.lifecycle.TransitionDefList; +import org.collectionspace.services.lifecycle.TransitionList; +import org.nuxeo.ecm.core.NXCore; 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.model.PropertyException; import org.nuxeo.ecm.core.api.repository.RepositoryInstance; +import org.nuxeo.ecm.core.lifecycle.LifeCycleService; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,14 +79,109 @@ public abstract class DocumentModelHandler public final static String COLLECTIONSPACE_CORE_CREATED_BY = "createdBy"; public final static String COLLECTIONSPACE_CORE_UPDATED_BY = "updatedBy"; + /* + * Map Nuxeo's life cycle object to our JAX-B based life cycle object + */ + private Lifecycle createCollectionSpaceLifecycle(org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle) { + Lifecycle result = null; + + if (nuxeoLifecyle != null) { + // + // Copy the life cycle's name + result = new Lifecycle(); + result.setName(nuxeoLifecyle.getName()); + + // We currently support only one initial state, so take the first one from Nuxeo + Collection initialStateNames = nuxeoLifecyle.getInitialStateNames(); + result.setDefaultInitial(initialStateNames.iterator().next()); + + // Next, we copy the state and corresponding transition lists + StateList stateList = new StateList(); + List states = stateList.getState(); + Collection nuxeoStates = nuxeoLifecyle.getStates(); + for (org.nuxeo.ecm.core.lifecycle.LifeCycleState nuxeoState : nuxeoStates) { + State tempState = new State(); + tempState.setDescription(nuxeoState.getDescription()); + tempState.setInitial(nuxeoState.isInitial()); + tempState.setName(nuxeoState.getName()); + // Now get the list of transitions + TransitionList transitionList = new TransitionList(); + List transitions = transitionList.getTransition(); + Collection nuxeoTransitions = nuxeoState.getAllowedStateTransitions(); + for (String nuxeoTransition : nuxeoTransitions) { + transitions.add(nuxeoTransition); + } + tempState.setTransitionList(transitionList); + states.add(tempState); + } + result.setStateList(stateList); + + // Finally, we create the transition definitions + TransitionDefList transitionDefList = new TransitionDefList(); + List transitionDefs = transitionDefList.getTransitionDef(); + Collection nuxeoTransitionDefs = nuxeoLifecyle.getTransitions(); + for (org.nuxeo.ecm.core.lifecycle.LifeCycleTransition nuxeoTransitionDef : nuxeoTransitionDefs) { + TransitionDef tempTransitionDef = new TransitionDef(); + tempTransitionDef.setDescription(nuxeoTransitionDef.getDescription()); + tempTransitionDef.setDestinationState(nuxeoTransitionDef.getDestinationStateName()); + tempTransitionDef.setName(nuxeoTransitionDef.getName()); + transitionDefs.add(tempTransitionDef); + } + result.setTransitionDefList(transitionDefList); + } + + return result; + } + + /* + * Returns the the life cycle definition of the related Nuxeo document type for this handler. + * (non-Javadoc) + * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle() + */ + @Override public Lifecycle getLifecycle() { Lifecycle result = null; + String docTypeName = null; try { - result = (Lifecycle)FileTools.getJaxbObjectFromFile(Lifecycle.class, "default-lifecycle.xml"); + docTypeName = this.getServiceContext().getDocumentType(); + result = getLifecycle(docTypeName); + } catch (Exception e) { + if (logger.isTraceEnabled() == true) { + logger.trace("Could not retrieve lifecycle definition for Nuxeo doctype: " + docTypeName); + } + } + + return result; + } + + /* + * Returns the the life cycle definition of the related Nuxeo document type for this handler. + * (non-Javadoc) + * @see org.collectionspace.services.common.document.DocumentHandler#getLifecycle(java.lang.String) + */ + @Override + public Lifecycle getLifecycle(String docTypeName) { + org.nuxeo.ecm.core.lifecycle.LifeCycle nuxeoLifecyle; + Lifecycle result = null; + + try { + LifeCycleService lifeCycleService = null; + try { + lifeCycleService = NXCore.getLifeCycleService(); + } catch (Exception e) { + e.printStackTrace(); + } + + String lifeCycleName; + lifeCycleName = lifeCycleService.getLifeCycleNameFor(docTypeName); + nuxeoLifecyle = lifeCycleService.getLifeCycleByName(lifeCycleName); + + result = createCollectionSpaceLifecycle(nuxeoLifecyle); +// result = (Lifecycle)FileTools.getJaxbObjectFromFile(Lifecycle.class, "default-lifecycle.xml"); } catch (Exception e) { // TODO Auto-generated catch block - e.printStackTrace(); + logger.error("Could not retreive life cycle information for Nuxeo doctype: " + docTypeName, e); } return result; @@ -242,5 +345,4 @@ public abstract class DocumentModelHandler COLLECTIONSPACE_CORE_UPDATED_BY, userId); } } - } -- 2.47.3