From 3e6969ce1c119f6af10272be43f7fd9080459052 Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Fri, 6 Dec 2019 15:46:10 -0800 Subject: [PATCH] DRYD-477: Adding support for both post-commit event listeners. --- .../nuxeo-platform-listener/botgarden/pom.xml | 11 +- .../botgarden/CreateVersionListener.java | 68 +-- .../botgarden/DeleteDeadLocationListener.java | 68 +-- .../botgarden/UpdateAccessCodeListener.java | 390 ++++++++++-------- .../botgarden/UpdateDeadFlagListener.java | 153 ++++--- .../botgarden/UpdateLocationListener.java | 110 ++--- .../botgarden/UpdateRareFlagListener.java | 215 +++++----- .../botgarden/UpdateStyledNameListener.java | 113 +++-- .../UpdateFormattedDisplayNameListener.java | 75 ++-- .../services/listener/Reindex.java | 129 +++--- .../services/listener/ReindexSupport.java | 75 ++-- .../listener/UpdateImageDerivatives.java | 98 ++--- .../AbstractUpdateObjectLocationValues.java | 339 ++++----------- .../UpdateObjectLocationAndCrateOnMove.java | 17 +- .../listener/UpdateObjectLocationOnMove.java | 20 +- .../listener/UpdateRelationsOnDelete.java | 169 ++++---- .../nuxeo/nuxeo-platform-thumbnail/pom.xml | 7 +- .../thumbnail/AddThumbnailUnrestricted.java | 1 + .../nuxeo/extension/thumbnail/Thumbnail.java | 3 +- .../thumbnail/ThumbnailConverter.java | 1 + .../thumbnail/UpdateThumbListener.java | 26 +- .../batch/nuxeo/UpdateAccessCodeBatchJob.java | 236 ++++++----- .../batch/nuxeo/UpdateRareFlagBatchJob.java | 6 +- services/common/pom.xml | 6 - .../common/imaging/nuxeo/NuxeoBlobUtils.java | 12 +- .../listener/AbstractCSEventListenerImpl.java | 212 +++++++++- ...AbstractCSEventPostCommitListenerImpl.java | 30 ++ .../AbstractCSEventSyncListenerImpl.java | 7 + .../nuxeo/listener/CSEventListener.java | 17 +- .../nuxeo/util}/ThumbnailConstants.java | 2 +- 30 files changed, 1442 insertions(+), 1174 deletions(-) create mode 100644 services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventPostCommitListenerImpl.java create mode 100644 services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventSyncListenerImpl.java rename {3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail => services/common/src/main/java/org/collectionspace/services/nuxeo/util}/ThumbnailConstants.java (89%) diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/pom.xml b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/pom.xml index 755a5a4d6..db79e6b9b 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/pom.xml +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/pom.xml @@ -6,7 +6,7 @@ org.collectionspace.services.3rdparty.nuxeo.listener org.collectionspace.services - ${revision} + ${revision} UTF-8 @@ -15,16 +15,17 @@ org.collectionspace.services.listener.botgarden http://maven.apache.org - + org.nuxeo.ecm.core nuxeo-core-storage-sql + ${nuxeo.core.version} org.nuxeo.ecm.platform nuxeo-platform-filemanager-api - ${nuxeo.platform.version} + ${nuxeo.platform.version} org.collectionspace.services @@ -43,7 +44,7 @@ - + @@ -67,5 +68,5 @@ - + diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/CreateVersionListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/CreateVersionListener.java index 6424df4e6..e275d9285 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/CreateVersionListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/CreateVersionListener.java @@ -1,51 +1,63 @@ package org.collectionspace.services.listener.botgarden; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.movement.nuxeo.MovementConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.VersioningOption; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class CreateVersionListener extends AbstractCSEventListenerImpl { +public class CreateVersionListener extends AbstractCSEventSyncListenerImpl { public static final String SKIP_PROPERTY = "CreateVersionListener.SKIP"; + static final Log logger = LogFactory.getLog(CreateVersionListener.class); - final Logger logger = LoggerFactory.getLogger(CreateVersionListener.class); - + @Override + public boolean shouldHandleEvent(Event event) { + EventContext eventContext = event.getContext(); + if (isRegistered(event) && eventContext instanceof DocumentEventContext) { + return true; + } + + return false; + } + @Override - public void handleEvent(Event event) { + public void handleCSEvent(Event event) { EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; - if (isRegistered(event) && ec instanceof DocumentEventContext) { - DocumentEventContext context = (DocumentEventContext) ec; - - if (ec.hasProperty(SKIP_PROPERTY) && ((Boolean) ec.getProperty(SKIP_PROPERTY))) { - logger.debug("Skipping create version"); - } - else { - DocumentModel doc = context.getSourceDocument(); + if (ec.hasProperty(SKIP_PROPERTY) && ((Boolean) ec.getProperty(SKIP_PROPERTY))) { + logger.debug("Skipping create version"); + } + else { + DocumentModel doc = context.getSourceDocument(); - logger.debug("docType=" + doc.getType()); + logger.debug("docType=" + doc.getType()); - if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - // Version the document - DocumentRef versionRef = doc.checkIn(VersioningOption.MINOR, null); - DocumentModel versionDoc = context.getCoreSession().getDocument(versionRef); + if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + // Version the document + DocumentRef versionRef = doc.checkIn(VersioningOption.MINOR, null); + DocumentModel versionDoc = context.getCoreSession().getDocument(versionRef); - logger.debug("created version: id=" + versionDoc.getId() + " csid=" + versionDoc.getName()); + logger.debug("created version: id=" + versionDoc.getId() + " csid=" + versionDoc.getName()); - // Check out the document, so it can be modified - doc.checkOut(); - } + // Check out the document, so it can be modified + doc.checkOut(); } } } -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/DeleteDeadLocationListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/DeleteDeadLocationListener.java index 4590b3f06..41146b757 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/DeleteDeadLocationListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/DeleteDeadLocationListener.java @@ -1,48 +1,66 @@ package org.collectionspace.services.listener.botgarden; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.movement.nuxeo.MovementBotGardenConstants; import org.collectionspace.services.movement.nuxeo.MovementConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class DeleteDeadLocationListener extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(DeleteDeadLocationListener.class); +public class DeleteDeadLocationListener extends AbstractCSEventSyncListenerImpl { + static final Log logger = LogFactory.getLog(DeleteDeadLocationListener.class); - /* - * Delete dead locations. - */ @Override - public void handleEvent(Event event) { + public boolean shouldHandleEvent(Event event) { EventContext ec = event.getContext(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { + if (ec instanceof DocumentEventContext) { DocumentEventContext context = (DocumentEventContext) ec; DocumentModel doc = context.getSourceDocument(); if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && + !doc.isVersion() && + !doc.isProxy() && !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, - MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); - - logger.debug("actionCode=" + actionCode); - - if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { - CoreSession session = context.getCoreSession(); - - if (session.getAllowedStateTransitions(doc.getRef()).contains(WorkflowClient.WORKFLOWTRANSITION_DELETE)) { - session.followTransition(doc.getRef(), WorkflowClient.WORKFLOWTRANSITION_DELETE); - } - } + return true; } } + + return false; + } + + /* + * Delete dead locations. + */ + @Override + public void handleCSEvent(Event event) { + EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + + String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, + MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); + + logger.debug("actionCode=" + actionCode); + + if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { + CoreSession session = context.getCoreSession(); + + if (session.getAllowedStateTransitions(doc.getRef()).contains(WorkflowClient.WORKFLOWTRANSITION_DELETE)) { + session.followTransition(doc.getRef(), WorkflowClient.WORKFLOWTRANSITION_DELETE); + } + } + } + + @Override + public Log getLogger() { + return logger; } -} +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateAccessCodeListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateAccessCodeListener.java index a90f6ed59..1a63c5f6c 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateAccessCodeListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateAccessCodeListener.java @@ -8,25 +8,36 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.batch.BatchResource; import org.collectionspace.services.batch.nuxeo.UpdateAccessCodeBatchJob; +import org.collectionspace.services.batch.nuxeo.UpdateAccessCodeBatchJob.UpdateAccessCodeResults; +import org.collectionspace.services.client.BatchClient; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectBotGardenConstants; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants; import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.invocable.InvocationResults; import org.collectionspace.services.common.relation.nuxeo.RelationConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants; import org.collectionspace.services.taxonomy.nuxeo.TaxonConstants; +import org.collectionspace.services.taxonomy.nuxeo.TaxonomyAuthorityConstants; + import org.jboss.resteasy.spi.ResteasyProviderFactory; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * A listener that updates the access code on taxon records when collectionobjects @@ -36,8 +47,8 @@ import org.slf4j.LoggerFactory; * @author ray * */ -public class UpdateAccessCodeListener extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(UpdateAccessCodeListener.class); +public class UpdateAccessCodeListener extends AbstractCSEventSyncListenerImpl { + static final Log logger = LogFactory.getLog(UpdateAccessCodeListener.class); public static final String PREVIOUS_DEAD_FLAG_PROPERTY_NAME = "UpdateAccessCodeListener.previousDeadFlag"; public static final String PREVIOUS_TAXON_NAMES_PROPERTY_NAME = "UpdateAccessCodeListener.previousTaxonNames"; @@ -49,125 +60,113 @@ public class UpdateAccessCodeListener extends AbstractCSEventListenerImpl { private static final String TAXON_FIELD_NAME = TAXON_PATH_ELEMENTS[2]; @Override - public void handleEvent(Event event) { + public boolean shouldHandleEvent(Event event) { + return event.getContext() instanceof DocumentEventContext; + } + + @Override + public void handleCSEvent(Event event) { EventContext ec = event.getContext(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { - DocumentEventContext context = (DocumentEventContext) ec; - DocumentModel doc = context.getSourceDocument(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + String docType = doc.getType(); - logger.debug("docType=" + doc.getType()); + logger.debug("docType=" + docType); - if (doc.getType().startsWith(CollectionObjectConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + if (docType.startsWith(CollectionObjectConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - // Stash the previous dead flag and taxonomic ident values, so they can be retrieved in the documentModified handler. + if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + // Stash the previous dead flag and taxonomic ident values, so they can be retrieved in the documentModified handler. - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - String previousDeadFlag = (String) previousDoc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, - CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); - context.setProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME, previousDeadFlag); + String previousDeadFlag = (String) previousDoc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, + CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); + context.setProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME, previousDeadFlag); - List previousTaxonNames = getTaxonNames(previousDoc); - context.setProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME, previousTaxonNames.toArray(new String[previousTaxonNames.size()])); - } - else { - boolean deadFlagChanged = false; - Set deletedTaxonNames = null; - Set addedTaxonNames = null; - - if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { - // As an optimization, check if the dead flag of the collectionobject has - // changed, or if the taxonomic identification has changed. If so, we need to - // update the access codes of referenced taxon records. - - String previousDeadFlag = (String) context.getProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME); - String currentDeadFlag = (String) doc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, - CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); + List previousTaxonNames = getTaxonNames(previousDoc); + context.setProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME, previousTaxonNames.toArray(new String[previousTaxonNames.size()])); + } + else { + boolean deadFlagChanged = false; + Set deletedTaxonNames = null; + Set addedTaxonNames = null; - if (previousDeadFlag == null) { - previousDeadFlag = ""; - } + String currentDeadFlag = (String) doc.getProperty(CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, + CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); - if (currentDeadFlag == null) { - currentDeadFlag = ""; - } + if (currentDeadFlag == null) { + currentDeadFlag = ""; + } - if (previousDeadFlag.equals(currentDeadFlag)) { - logger.debug("dead flag not changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag); - } - else { - logger.debug("dead flag changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag); - deadFlagChanged = true; - } + if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { + // As an optimization, check if the dead flag of the collectionobject has + // changed, or if the taxonomic identification has changed. If so, we need to + // update the access codes of referenced taxon records. - List previousTaxonNames = Arrays.asList((String[]) context.getProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME)); - List currentTaxonNames = getTaxonNames(doc); + String previousDeadFlag = (String) context.getProperty(PREVIOUS_DEAD_FLAG_PROPERTY_NAME); - deletedTaxonNames = findDeletedTaxonNames(previousTaxonNames, currentTaxonNames); - logger.debug("found deleted taxon names: " + StringUtils.join(deletedTaxonNames, ", ")); + if (previousDeadFlag == null) { + previousDeadFlag = ""; + } - addedTaxonNames = findAddedTaxonNames(previousTaxonNames, currentTaxonNames); - logger.debug("found added taxon names: " + StringUtils.join(addedTaxonNames, ", ")); + if (previousDeadFlag.equals(currentDeadFlag)) { + logger.debug("dead flag not changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag); } - else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + else { + logger.debug("dead flag changed: previousDeadFlag=" + previousDeadFlag + " currentDeadFlag=" + currentDeadFlag); deadFlagChanged = true; } - UpdateAccessCodeBatchJob updater = createUpdater(); + List previousTaxonNames = Arrays.asList((String[]) context.getProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME)); + List currentTaxonNames = getTaxonNames(doc); - if (deadFlagChanged) { - String collectionObjectCsid = doc.getName(); + deletedTaxonNames = findDeletedTaxonNames(previousTaxonNames, currentTaxonNames); + logger.debug("found deleted taxon names: " + StringUtils.join(deletedTaxonNames, ", ")); - try { - // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't - // propagate changes up the taxon hierarchy. Propagation is taken care of by this - // event handler: As taxon records are modified, this handler executes, and updates the - // parent. + addedTaxonNames = findAddedTaxonNames(previousTaxonNames, currentTaxonNames); + logger.debug("found added taxon names: " + StringUtils.join(addedTaxonNames, ", ")); + } + else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + deadFlagChanged = true; + } - InvocationResults results = updater.updateReferencedAccessCodes(collectionObjectCsid, false); + if (deadFlagChanged) { + String collectionObjectCsid = doc.getName(); - logger.debug("updateReferencedAccessCodes complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - else { - // If the dead flag didn't change, we still need to recalculate the access codes of - // any taxonomic idents that were added. - - if (addedTaxonNames != null) { - for (String addedTaxonName : addedTaxonNames) { - logger.debug("updating added taxon: " + addedTaxonName); + try { + // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't + // propagate changes up the taxon hierarchy. Propagation is taken care of by this + // event handler: As taxon records are modified, this handler executes, and updates the + // parent. - try { - InvocationResults results = updater.updateAccessCode(addedTaxonName, false); + InvocationResults results = createUpdater(context).updateReferencedAccessCodes(collectionObjectCsid, false); - logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - } + logger.debug("updateReferencedAccessCodes complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } + catch (Exception e) { + logger.error(e.getMessage(), e); } + } + else { + // If the dead flag didn't change, we still need to recalculate the access codes of + // any taxonomic idents that were added. - if (deletedTaxonNames != null) { - // If any taxonomic idents were removed from the collectionobject, they need to have their - // access codes recalculated. + if (addedTaxonNames != null) { + boolean isDead = currentDeadFlag.equalsIgnoreCase("true"); + boolean knownAlive = !isDead; - for (String deletedTaxonName : deletedTaxonNames) { - logger.debug("updating deleted taxon: " + deletedTaxonName); + for (String addedTaxonName : addedTaxonNames) { + logger.debug("updating added taxon: " + addedTaxonName); try { - InvocationResults results = updater.updateAccessCode(deletedTaxonName, false); + UpdateAccessCodeResults results = createUpdater(context).updateAccessCode(addedTaxonName, false, knownAlive); - logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected()); } catch (Exception e) { logger.error(e.getMessage(), e); @@ -175,124 +174,145 @@ public class UpdateAccessCodeListener extends AbstractCSEventListenerImpl { } } } - } - else if (doc.getType().startsWith(TaxonConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - // Stash the previous access code value, so it can be retrieved in the documentModified handler. + if (deletedTaxonNames != null) { + // If any taxonomic idents were removed from the collectionobject, they need to have their + // access codes recalculated. - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - String previousAccessCode = (String) previousDoc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); + for (String deletedTaxonName : deletedTaxonNames) { + logger.debug("updating deleted taxon: " + deletedTaxonName); - context.setProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME, previousAccessCode); + try { + InvocationResults results = createUpdater(context).updateAccessCode(deletedTaxonName, false); + + logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } + catch (Exception e) { + logger.error(e.getMessage(), e); + } + } } - else { - boolean updateRequired = false; + } + } + else if (docType.startsWith(TaxonConstants.NUXEO_DOCTYPE) && + !docType.startsWith(TaxonomyAuthorityConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { - // As an optimization, check if the access code of the taxon has - // changed. We only need to update the access code of the parent taxon - // record if it has. + if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + // Stash the previous access code value, so it can be retrieved in the documentModified handler. - String previousAccessCode = (String) context.getProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME); - String currentAccessCode = (String) doc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + String previousAccessCode = (String) previousDoc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); - if (previousAccessCode == null) { - previousAccessCode = ""; - } + context.setProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME, previousAccessCode); + } + else { + boolean updateRequired = false; - if (currentAccessCode == null) { - currentAccessCode = ""; - } + if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { + // As an optimization, check if the access code of the taxon has + // changed. We only need to update the access code of the parent taxon + // record if it has. - if (previousAccessCode.equals(currentAccessCode)) { - logger.debug("update not required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode); - } - else { - logger.debug("update required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode); - updateRequired = true; - } + String previousAccessCode = (String) context.getProperty(PREVIOUS_ACCESS_CODE_PROPERTY_NAME); + String currentAccessCode = (String) doc.getProperty(TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); + + if (previousAccessCode == null) { + previousAccessCode = ""; + } + + if (currentAccessCode == null) { + currentAccessCode = ""; + } + + if (previousAccessCode.equals(currentAccessCode)) { + logger.debug("update not required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode); } - else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + else { + logger.debug("update required: previousAccessCode=" + previousAccessCode + " currentAccessCode=" + currentAccessCode); updateRequired = true; } + } + else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + updateRequired = true; + } - if (updateRequired) { - String taxonCsid = doc.getName(); + if (updateRequired) { + String taxonCsid = doc.getName(); - try { - // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't - // propagate changes up the taxon hierarchy. Propagation is taken care of by this - // event handler: As taxon records are modified, this handler executes, and updates the - // parent. + try { + // Pass false for the second parameter to updateReferencedAccessCodes, so that it doesn't + // propagate changes up the taxon hierarchy. Propagation is taken care of by this + // event handler: As taxon records are modified, this handler executes, and updates the + // parent. - InvocationResults results = createUpdater().updateParentAccessCode(taxonCsid, false); + InvocationResults results = createUpdater(context).updateParentAccessCode(taxonCsid, false); - logger.debug("updateParentAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } + logger.debug("updateParentAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } + catch (Exception e) { + logger.error(e.getMessage(), e); } } } - else if (doc.getType().equals(RelationConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy()) { + } + else if (doc.getType().equals(RelationConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy()) { - if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); - String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; - String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME); + if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); + String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; + String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME); - logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType); + logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType); - if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) { - String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); - logger.debug("child added, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid); + if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) { + String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); + String childTaxonCsid = (String) doc.getProperty(RelationConstants.SUBJECT_CSID_SCHEMA_NAME, RelationConstants.SUBJECT_CSID_FIELD_NAME); - try { - InvocationResults results = createUpdater().updateAccessCode(parentTaxonCsid, false); + logger.debug("child added, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid + " childTaxonCsid=" + childTaxonCsid); - logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } + try { + UpdateAccessCodeResults results = createUpdater(context).updateAccessCode(parentTaxonCsid, false, childTaxonCsid); + + logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected()); + } + catch (Exception e) { + logger.error(e.getMessage(), e); } } - else if (event.getName().equals(DocumentEventTypes.ABOUT_TO_REMOVE)) { - String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); - String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; - String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME); + } + else if (event.getName().equals(DocumentEventTypes.ABOUT_TO_REMOVE)) { + String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); + String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; + String relationType = (String) doc.getProperty(RelationConstants.TYPE_SCHEMA_NAME, RelationConstants.TYPE_FIELD_NAME); - logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType); + logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType + " relationType=" + relationType); - if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) { - String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); + if (subjectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && objectDocType.equals(TaxonConstants.NUXEO_DOCTYPE) && relationType.equals(RelationConstants.BROADER_TYPE)) { + String parentTaxonCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); - // Stash the parent taxon csid, so it can be retrieved in the documentRemoved handler. - logger.debug("about to delete taxon hierarchy relation: parentTaxonCsid=" + parentTaxonCsid); - context.setProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME, parentTaxonCsid); - } + // Stash the parent taxon csid, so it can be retrieved in the documentRemoved handler. + logger.debug("about to delete taxon hierarchy relation: parentTaxonCsid=" + parentTaxonCsid); + context.setProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME, parentTaxonCsid); } - else if (event.getName().equals(DocumentEventTypes.DOCUMENT_REMOVED)) { - String parentTaxonCsid = (String) context.getProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME); + } + else if (event.getName().equals(DocumentEventTypes.DOCUMENT_REMOVED)) { + String parentTaxonCsid = (String) context.getProperty(DELETED_RELATION_PARENT_CSID_PROPERTY_NAME); - if (StringUtils.isNotEmpty(parentTaxonCsid)) { - logger.debug("child removed, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid); + if (StringUtils.isNotEmpty(parentTaxonCsid)) { + logger.debug("child removed, updating parent taxon: parentTaxonCsid=" + parentTaxonCsid); - try { - InvocationResults results = createUpdater().updateAccessCode(parentTaxonCsid, false); + try { + InvocationResults results = createUpdater(context).updateAccessCode(parentTaxonCsid, false); - logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } - catch (Exception e) { - logger.error(e.getMessage(), e); - } + logger.debug("updateAccessCode complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } + catch (Exception e) { + logger.error(e.getMessage(), e); } } } @@ -341,12 +361,22 @@ public class UpdateAccessCodeListener extends AbstractCSEventListenerImpl { return addedTaxonNameSet; } - private UpdateAccessCodeBatchJob createUpdater() { + private UpdateAccessCodeBatchJob createUpdater(DocumentEventContext context) throws Exception { ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); + BatchResource batchResource = (BatchResource) resourceMap.get(BatchClient.SERVICE_NAME); + ServiceContext serviceContext = batchResource.createServiceContext(batchResource.getServiceName()); + + serviceContext.setCurrentRepositorySession(new CoreSessionWrapper(context.getCoreSession())); UpdateAccessCodeBatchJob updater = new UpdateAccessCodeBatchJob(); + updater.setServiceContext(serviceContext); updater.setResourceMap(resourceMap); return updater; } + + @Override + public Log getLogger() { + return logger; + } } diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateDeadFlagListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateDeadFlagListener.java index b25bd7a33..3569452ce 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateDeadFlagListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateDeadFlagListener.java @@ -1,104 +1,125 @@ package org.collectionspace.services.listener.botgarden; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.batch.BatchResource; import org.collectionspace.services.batch.nuxeo.UpdateDeadFlagBatchJob; +import org.collectionspace.services.client.BatchClient; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants; import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.invocable.InvocationResults; import org.collectionspace.services.common.relation.nuxeo.RelationConstants; import org.collectionspace.services.movement.nuxeo.MovementBotGardenConstants; import org.collectionspace.services.movement.nuxeo.MovementConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.jboss.resteasy.spi.ResteasyProviderFactory; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateDeadFlagListener extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(UpdateDeadFlagListener.class); +public class UpdateDeadFlagListener extends AbstractCSEventSyncListenerImpl { + static final Log logger = LogFactory.getLog(UpdateDeadFlagListener.class); + @Override + public boolean shouldHandleEvent(Event event) { + return event.getContext() instanceof DocumentEventContext; + } + /* * Set the dead flag and dead date on collectionobjects related to a new or modified movement record. */ @Override - public void handleEvent(Event event) { + public void handleCSEvent(Event event) { EventContext ec = event.getContext(); - - if (isRegistered(event) && ec instanceof DocumentEventContext) { - DocumentEventContext context = (DocumentEventContext) ec; - DocumentModel doc = context.getSourceDocument(); - - logger.debug("docType=" + doc.getType()); - - if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - /* - * Handle the case where a new movement is created with action code revive, and then related - * to a collectionobject. The movement won't have any relations at the time it's created, - * so we need to capture the creation of the relation. - */ - if (doc.getType().equals(RelationConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy()) { - String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); - String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; - - logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType); - - if (subjectDocType.equals(MovementConstants.NUXEO_DOCTYPE) && objectDocType.equals(CollectionObjectConstants.NUXEO_DOCTYPE)) { - String movementCsid = (String) doc.getProperty(RelationConstants.SUBJECT_CSID_SCHEMA_NAME, RelationConstants.SUBJECT_CSID_FIELD_NAME); - String collectionObjectCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); - - try { - InvocationResults results = createUpdater().updateDeadFlag(collectionObjectCsid, movementCsid); - - logger.debug("updateDeadFlag complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + + logger.debug("docType=" + doc.getType()); + + if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + /* + * Handle the case where a new movement is created with action code revive, and then related + * to a collectionobject. The movement won't have any relations at the time it's created, + * so we need to capture the creation of the relation. + */ + if (doc.getType().equals(RelationConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy()) { + String subjectDocType = (String) doc.getProperty(RelationConstants.SUBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.SUBJECT_DOCTYPE_FIELD_NAME); + String objectDocType = (String) doc.getProperty(RelationConstants.OBJECT_DOCTYPE_SCHEMA_NAME, RelationConstants.OBJECT_DOCTYPE_FIELD_NAME);; + + logger.debug("subjectDocType=" + subjectDocType + " objectDocType=" + objectDocType); + + if (subjectDocType.equals(MovementConstants.NUXEO_DOCTYPE) && objectDocType.equals(CollectionObjectConstants.NUXEO_DOCTYPE)) { + String movementCsid = (String) doc.getProperty(RelationConstants.SUBJECT_CSID_SCHEMA_NAME, RelationConstants.SUBJECT_CSID_FIELD_NAME); + String collectionObjectCsid = (String) doc.getProperty(RelationConstants.OBJECT_CSID_SCHEMA_NAME, RelationConstants.OBJECT_CSID_FIELD_NAME); + + try { + InvocationResults results = createUpdater(context).updateDeadFlag(collectionObjectCsid, movementCsid); + + logger.debug("updateDeadFlag complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } catch (Exception e) { + logger.error(e.getMessage(), e); } } } - else { - /* - * Handle document modification. If the modified document was a movement record, and - * its action code is dead or revived, update the dead flag. We don't actually have to - * check the action code here, since it will be checked inside UpdateDeadFlagBatchJob.updateRelatedDeadFlags, - * but it is an optimization. - */ - if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); - - logger.debug("actionCode=" + actionCode); - - if (actionCode != null && (actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE) || actionCode.equals(MovementBotGardenConstants.REVIVED_ACTION_CODE))) { - String movementCsid = doc.getName(); - - try { - InvocationResults results = createUpdater().updateRelatedDeadFlags(movementCsid); - - logger.debug("updateRelatedDeadFlags complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } + } + else { + /* + * Handle document modification. If the modified document was a movement record, and + * its action code is dead or revived, update the dead flag. We don't actually have to + * check the action code here, since it will be checked inside UpdateDeadFlagBatchJob.updateRelatedDeadFlags, + * but it is an optimization. + */ + if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); + + logger.debug("actionCode=" + actionCode); + + if (actionCode != null && (actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE) || actionCode.equals(MovementBotGardenConstants.REVIVED_ACTION_CODE))) { + String movementCsid = doc.getName(); + + try { + InvocationResults results = createUpdater(context).updateRelatedDeadFlags(movementCsid); + + logger.debug("updateRelatedDeadFlags complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } catch (Exception e) { + logger.error(e.getMessage(), e); } } } } - } + } - private UpdateDeadFlagBatchJob createUpdater() { + private UpdateDeadFlagBatchJob createUpdater(DocumentEventContext context) throws Exception { ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); + BatchResource batchResource = (BatchResource) resourceMap.get(BatchClient.SERVICE_NAME); + ServiceContext serviceContext = batchResource.createServiceContext(batchResource.getServiceName()); + + serviceContext.setCurrentRepositorySession(new CoreSessionWrapper(context.getCoreSession())); UpdateDeadFlagBatchJob updater = new UpdateDeadFlagBatchJob(); + updater.setServiceContext(serviceContext); updater.setResourceMap(resourceMap); return updater; } -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateLocationListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateLocationListener.java index b537c6a90..0d3496a77 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateLocationListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateLocationListener.java @@ -1,21 +1,42 @@ package org.collectionspace.services.listener.botgarden; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.movement.nuxeo.MovementBotGardenConstants; import org.collectionspace.services.movement.nuxeo.MovementConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateLocationListener extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(UpdateLocationListener.class); +public class UpdateLocationListener extends AbstractCSEventSyncListenerImpl { + static final Log logger = LogFactory.getLog(UpdateLocationListener.class); + + @Override + public boolean shouldHandleEvent(Event event) { + EventContext ec = event.getContext(); + if (ec instanceof DocumentEventContext) { + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + + if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + return true; + } + } + + return false; + } + /* * Set the currentLocation and previousLocation fields in a Current Location record * to appropriate values. @@ -26,54 +47,51 @@ public class UpdateLocationListener extends AbstractCSEventListenerImpl { * */ @Override - public void handleEvent(Event event) { + public void handleCSEvent(Event event) { EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { - DocumentEventContext context = (DocumentEventContext) ec; - DocumentModel doc = context.getSourceDocument(); - - if (doc.getType().startsWith(MovementConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, - MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); + String actionCode = (String) doc.getProperty(MovementBotGardenConstants.ACTION_CODE_SCHEMA_NAME, + MovementBotGardenConstants.ACTION_CODE_FIELD_NAME); - logger.debug("actionCode=" + actionCode); + logger.debug("actionCode=" + actionCode); - if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - /* - * Special case for a document that is created with an action code of dead. - * In this case, we'll set the currentLocation to none, and the previousLocation to - * the current value of currentLocation, since there isn't a previous value. To do - * this, we can simply save the document, which will cause the beforeDocumentModification - * event to fire, taking us into the other branch of this code, with the current document - * becoming the previous document. - */ - if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { - context.getCoreSession().saveDocument(doc); + if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + /* + * Special case for a document that is created with an action code of dead. + * In this case, we'll set the currentLocation to none, and the previousLocation to + * the current value of currentLocation, since there isn't a previous value. To do + * this, we can simply save the document, which will cause the beforeDocumentModification + * event to fire, taking us into the other branch of this code, with the current document + * becoming the previous document. + */ + if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { + context.getCoreSession().saveDocument(doc); - /* - * The saveDocument call will have caused the document to be versioned via documentModified, - * so we can skip the versioning that would normally happen on documentCreated. - */ - ec.setProperty(CreateVersionListener.SKIP_PROPERTY, true); - } - } - else { - if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { - doc.setProperty(MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME, MovementConstants.NONE_LOCATION); - } + /* + * The saveDocument call will have caused the document to be versioned via documentModified, + * so we can skip the versioning that would normally happen on documentCreated. + */ + ec.setProperty(CreateVersionListener.SKIP_PROPERTY, true); + } + } + else { + if (actionCode != null && actionCode.equals(MovementBotGardenConstants.DEAD_ACTION_CODE)) { + doc.setProperty(MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME, MovementConstants.NONE_LOCATION); + } - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - String previousLocation = (String) previousDoc.getProperty(MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME); + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + String previousLocation = (String) previousDoc.getProperty(MovementConstants.CURRENT_LOCATION_SCHEMA_NAME, MovementConstants.CURRENT_LOCATION_FIELD_NAME); - logger.debug("previousLocation=" + previousLocation); + logger.debug("previousLocation=" + previousLocation); - doc.setProperty(MovementConstants.PREVIOUS_LOCATION_SCHEMA_NAME, MovementConstants.PREVIOUS_LOCATION_FIELD_NAME, previousLocation); - } - } + doc.setProperty(MovementConstants.PREVIOUS_LOCATION_SCHEMA_NAME, MovementConstants.PREVIOUS_LOCATION_FIELD_NAME, previousLocation); } } -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateRareFlagListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateRareFlagListener.java index 6a342b802..72bb3f756 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateRareFlagListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateRareFlagListener.java @@ -3,24 +3,34 @@ package org.collectionspace.services.listener.botgarden; import java.util.List; import java.util.Map; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.batch.BatchResource; import org.collectionspace.services.batch.nuxeo.UpdateRareFlagBatchJob; +import org.collectionspace.services.client.BatchClient; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectBotGardenConstants; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants; import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.invocable.InvocationResults; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants; import org.collectionspace.services.taxonomy.nuxeo.TaxonConstants; +import org.collectionspace.services.taxonomy.nuxeo.TaxonomyAuthorityConstants; + import org.jboss.resteasy.spi.ResteasyProviderFactory; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * A listener that updates the rare flag on collectionobjects when collectionobjects @@ -30,8 +40,8 @@ import org.slf4j.LoggerFactory; * @author ray * */ -public class UpdateRareFlagListener extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(UpdateRareFlagListener.class); +public class UpdateRareFlagListener extends AbstractCSEventSyncListenerImpl { + static final Log logger = LogFactory.getLog(UpdateRareFlagListener.class); public static final String PREVIOUS_TAXON_PROPERTY_NAME = "UpdateRareFlagListener.previousTaxon"; public static final String PREVIOUS_HAS_RARE_CONSERVATION_CATEGORY_PROPERTY_NAME = "UpdateRareFlagListener.previousHasRareConservationCategory"; @@ -40,121 +50,126 @@ public class UpdateRareFlagListener extends AbstractCSEventListenerImpl { private static final String PLANT_ATTRIBUTES_GROUP_LIST_FIELD_NAME = CONSERVATION_CATEGORY_PATH_ELEMENTS[0]; private static final String CONSERVATION_CATEGORY_FIELD_NAME = CONSERVATION_CATEGORY_PATH_ELEMENTS[2]; + @Override + public boolean shouldHandleEvent(Event event) { + return event.getContext() instanceof DocumentEventContext; + } + @Override - public void handleEvent(Event event) { + public void handleCSEvent(Event event) { EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + String docType = doc.getType(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { - DocumentEventContext context = (DocumentEventContext) ec; - DocumentModel doc = context.getSourceDocument(); + logger.debug("docType=" + docType); - logger.debug("docType=" + doc.getType()); + if (docType.startsWith(CollectionObjectConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - if (doc.getType().startsWith(CollectionObjectConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + // Stash the previous primary taxonomic ident, so it can be retrieved in the documentModified handler. - if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - // Stash the previous primary taxonomic ident, so it can be retrieved in the documentModified handler. + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + String previousTaxon = (String) previousDoc.getProperty(CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, + CollectionObjectBotGardenConstants.PRIMARY_TAXON_FIELD_NAME); - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - String previousTaxon = (String) previousDoc.getProperty(CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, + context.setProperty(PREVIOUS_TAXON_PROPERTY_NAME, previousTaxon); + } + else { + boolean updateRequired = false; + + if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { + // A collectionobject was modified. As an optimization, check if the primary taxonomic determination + // of the collectionobject has changed. We only need to update the rare flag if it has. + + String previousTaxon = (String) context.getProperty(PREVIOUS_TAXON_PROPERTY_NAME); + String currentTaxon = (String) doc.getProperty(CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, CollectionObjectBotGardenConstants.PRIMARY_TAXON_FIELD_NAME); - context.setProperty(PREVIOUS_TAXON_PROPERTY_NAME, previousTaxon); - } - else { - boolean updateRequired = false; - - if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { - // A collectionobject was modified. As an optimization, check if the primary taxonomic determination - // of the collectionobject has changed. We only need to update the rare flag if it has. - - String previousTaxon = (String) context.getProperty(PREVIOUS_TAXON_PROPERTY_NAME); - String currentTaxon = (String) doc.getProperty(CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, - CollectionObjectBotGardenConstants.PRIMARY_TAXON_FIELD_NAME); - - if (previousTaxon == null) { - previousTaxon = ""; - } - - if (currentTaxon == null) { - currentTaxon = ""; - } - - if (previousTaxon.equals(currentTaxon)) { - logger.debug("update not required: previousTaxon=" + previousTaxon + " currentTaxon=" + currentTaxon); - } - else { - logger.debug("update required: previousTaxon=" + previousTaxon + " currentTaxon=" + currentTaxon); - updateRequired = true; - } + if (previousTaxon == null) { + previousTaxon = ""; } - else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - // A collectionobject was created. Always update the rare flag. + if (currentTaxon == null) { + currentTaxon = ""; + } + + if (previousTaxon.equals(currentTaxon)) { + logger.debug("update not required: previousTaxon=" + previousTaxon + " currentTaxon=" + currentTaxon); + } + else { + logger.debug("update required: previousTaxon=" + previousTaxon + " currentTaxon=" + currentTaxon); updateRequired = true; } + } + else if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + // A collectionobject was created. Always update the rare flag. + + updateRequired = true; + } - if (updateRequired) { - String collectionObjectCsid = doc.getName(); + if (updateRequired) { + String collectionObjectCsid = doc.getName(); - try { - InvocationResults results = createUpdater().updateRareFlag(collectionObjectCsid); + try { + InvocationResults results = createUpdater(context).updateRareFlag(collectionObjectCsid); - logger.debug("updateRareFlag complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } + logger.debug("updateRareFlag complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } catch (Exception e) { + logger.error(e.getMessage(), e); } } } - else if (doc.getType().startsWith(TaxonConstants.NUXEO_DOCTYPE) && - !doc.isVersion() && - !doc.isProxy() && - !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + } + else if (docType.startsWith(TaxonConstants.NUXEO_DOCTYPE) && + !docType.startsWith(TaxonomyAuthorityConstants.NUXEO_DOCTYPE) && + !doc.isVersion() && + !doc.isProxy() && + !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { - if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - // Stash whether there was previously a non-empty conservation category, so it can be retrieved in the documentModified handler. + if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + // Stash whether there was previously a non-empty conservation category, so it can be retrieved in the documentModified handler. - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - boolean previousHasRareConservationCategory = hasRareConservationCategory(previousDoc); + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + boolean previousHasRareConservationCategory = hasRareConservationCategory(previousDoc); - context.setProperty(PREVIOUS_HAS_RARE_CONSERVATION_CATEGORY_PROPERTY_NAME, new Boolean(previousHasRareConservationCategory)); - } - else { - boolean updateRequired = false; - - if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { - // A taxon record was modified. As an optimization, check if there is now a rare - // conservation category when there wasn't before, or vice versa. We only need to update - // the rare flags of referencing collectionobjects if there was a change. - - boolean previousHasRareConservationCategory = (Boolean) context.getProperty(PREVIOUS_HAS_RARE_CONSERVATION_CATEGORY_PROPERTY_NAME); - boolean currentHasRareConservationCategory = hasRareConservationCategory(doc); - - if (previousHasRareConservationCategory == currentHasRareConservationCategory) { - logger.debug("update not required: previousHasRareConservationCategory=" + previousHasRareConservationCategory + - " currentHasRareConservationCategory=" + currentHasRareConservationCategory); - } - else { - logger.debug("update required: previousHasRareConservationCategory=" + previousHasRareConservationCategory + - " currentHasRareConservationCategory=" + currentHasRareConservationCategory); - updateRequired = true; - } + context.setProperty(PREVIOUS_HAS_RARE_CONSERVATION_CATEGORY_PROPERTY_NAME, new Boolean(previousHasRareConservationCategory)); + } + else { + boolean updateRequired = false; + + if (event.getName().equals(DocumentEventTypes.DOCUMENT_UPDATED)) { + // A taxon record was modified. As an optimization, check if there is now a rare + // conservation category when there wasn't before, or vice versa. We only need to update + // the rare flags of referencing collectionobjects if there was a change. + + boolean previousHasRareConservationCategory = (Boolean) context.getProperty(PREVIOUS_HAS_RARE_CONSERVATION_CATEGORY_PROPERTY_NAME); + boolean currentHasRareConservationCategory = hasRareConservationCategory(doc); + + if (previousHasRareConservationCategory == currentHasRareConservationCategory) { + logger.debug("update not required: previousHasRareConservationCategory=" + previousHasRareConservationCategory + + " currentHasRareConservationCategory=" + currentHasRareConservationCategory); } + else { + logger.debug("update required: previousHasRareConservationCategory=" + previousHasRareConservationCategory + + " currentHasRareConservationCategory=" + currentHasRareConservationCategory); + updateRequired = true; + } + } - if (updateRequired) { - String taxonCsid = doc.getName(); + if (updateRequired) { + String taxonCsid = doc.getName(); + String vocabularyCsid = (String) doc.getProperty(TaxonConstants.IN_AUTHORITY_SCHEMA_NAME, TaxonConstants.IN_AUTHORITY_FIELD_NAME); - try { - InvocationResults results = createUpdater().updateReferencingRareFlags(taxonCsid); + try { + InvocationResults results = createUpdater(context).updateReferencingRareFlags(taxonCsid, vocabularyCsid); - logger.debug("updateReferencingRareFlags complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } + logger.debug("updateReferencingRareFlags complete: numAffected=" + results.getNumAffected() + " userNote=" + results.getUserNote()); + } catch (Exception e) { + logger.error(e.getMessage(), e); } } } @@ -189,12 +204,22 @@ public class UpdateRareFlagListener extends AbstractCSEventListenerImpl { return hasRareConservationCategory; } - private UpdateRareFlagBatchJob createUpdater() { + private UpdateRareFlagBatchJob createUpdater(DocumentEventContext context) throws Exception { ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); + BatchResource batchResource = (BatchResource) resourceMap.get(BatchClient.SERVICE_NAME); + ServiceContext serviceContext = batchResource.createServiceContext(batchResource.getServiceName()); + + serviceContext.setCurrentRepositorySession(new CoreSessionWrapper(context.getCoreSession())); UpdateRareFlagBatchJob updater = new UpdateRareFlagBatchJob(); + updater.setServiceContext(serviceContext); updater.setResourceMap(resourceMap); return updater; } + + @Override + public Log getLogger() { + return logger; + } } diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateStyledNameListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateStyledNameListener.java index c9656ea9f..4400383f4 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateStyledNameListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateStyledNameListener.java @@ -1,32 +1,39 @@ package org.collectionspace.services.listener.botgarden; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.collectionspace.services.batch.BatchResource; import org.collectionspace.services.batch.nuxeo.FormatVoucherNameBatchJob; +import org.collectionspace.services.client.BatchClient; +import org.collectionspace.services.client.PoxPayloadIn; +import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.ResourceMap; +import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.loanout.nuxeo.LoanoutBotGardenConstants; import org.collectionspace.services.loanout.nuxeo.LoanoutConstants; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateStyledNameListener extends AbstractCSEventListenerImpl { +public class UpdateStyledNameListener extends AbstractCSEventSyncListenerImpl { public static final String RUN_AFTER_MODIFIED_PROPERTY = "UpdateStyledNameListener.RUN_AFTER_MODIFIED"; + static final Log logger = LogFactory.getLog(UpdateStyledNameListener.class); - final Logger logger = LoggerFactory.getLogger(UpdateStyledNameListener.class); - - @Override - public void handleEvent(Event event) { + @Override + public boolean shouldHandleEvent(Event event) { EventContext ec = event.getContext(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { + if (ec instanceof DocumentEventContext) { DocumentEventContext context = (DocumentEventContext) ec; DocumentModel doc = context.getSourceDocument(); @@ -36,57 +43,79 @@ public class UpdateStyledNameListener extends AbstractCSEventListenerImpl { !doc.isVersion() && !doc.isProxy() && !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + return true; + } + } + + return false; + } + + @Override + public void handleCSEvent(Event event) { + EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); - if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + logger.debug("docType=" + doc.getType()); - String previousLabelRequested = (String) previousDoc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, - LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); - String labelRequested = (String) doc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, - LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); + if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - logger.debug("previousLabelRequested=" + previousLabelRequested + " labelRequested=" + labelRequested); + String previousLabelRequested = (String) previousDoc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, + LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); + String labelRequested = (String) doc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, + LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); - if ((previousLabelRequested == null || previousLabelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_NO_VALUE)) && - labelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_YES_VALUE)) { - // The label request is changing from no to yes, so we should update the styled name. - ec.setProperty(RUN_AFTER_MODIFIED_PROPERTY, true); - } - } - else { - boolean doUpdate = false; + logger.debug("previousLabelRequested=" + previousLabelRequested + " labelRequested=" + labelRequested); + + if ((previousLabelRequested == null || previousLabelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_NO_VALUE)) && + labelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_YES_VALUE)) { + // The label request is changing from no to yes, so we should update the styled name. + ec.setProperty(RUN_AFTER_MODIFIED_PROPERTY, true); + } + } + else { + boolean doUpdate = false; - if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - String labelRequested = (String) doc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, - LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); + if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + String labelRequested = (String) doc.getProperty(LoanoutBotGardenConstants.LABEL_REQUESTED_SCHEMA_NAME, + LoanoutBotGardenConstants.LABEL_REQUESTED_FIELD_NAME); - doUpdate = (labelRequested != null && labelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_YES_VALUE)); - } else { - doUpdate = ec.hasProperty(RUN_AFTER_MODIFIED_PROPERTY) && ((Boolean) ec.getProperty(RUN_AFTER_MODIFIED_PROPERTY)); - } + doUpdate = (labelRequested != null && labelRequested.equals(LoanoutBotGardenConstants.LABEL_REQUESTED_YES_VALUE)); + } else { + doUpdate = ec.hasProperty(RUN_AFTER_MODIFIED_PROPERTY) && ((Boolean) ec.getProperty(RUN_AFTER_MODIFIED_PROPERTY)); + } - if (doUpdate) { - logger.debug("Updating styled name"); + if (doUpdate) { + logger.debug("Updating styled name"); - String voucherCsid = doc.getName(); + String voucherCsid = doc.getName(); - try { - createFormatter().formatVoucherName(voucherCsid); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } + try { + createFormatter(context).formatVoucherName(voucherCsid); + } catch (Exception e) { + logger.error(e.getMessage(), e); } } } } - private FormatVoucherNameBatchJob createFormatter() { + private FormatVoucherNameBatchJob createFormatter(DocumentEventContext context) throws Exception { ResourceMap resourceMap = ResteasyProviderFactory.getContextData(ResourceMap.class); + BatchResource batchResource = (BatchResource) resourceMap.get(BatchClient.SERVICE_NAME); + ServiceContext serviceContext = batchResource.createServiceContext(batchResource.getServiceName()); + + serviceContext.setCurrentRepositorySession(new CoreSessionWrapper(context.getCoreSession())); FormatVoucherNameBatchJob formatter = new FormatVoucherNameBatchJob(); + formatter.setServiceContext(serviceContext); formatter.setResourceMap(resourceMap); return formatter; } -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/naturalhistory/src/main/java/org/collectionspace/services/listener/naturalhistory/UpdateFormattedDisplayNameListener.java b/3rdparty/nuxeo/nuxeo-platform-listener/naturalhistory/src/main/java/org/collectionspace/services/listener/naturalhistory/UpdateFormattedDisplayNameListener.java index d2ddc1940..3b8b4608c 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/naturalhistory/src/main/java/org/collectionspace/services/listener/naturalhistory/UpdateFormattedDisplayNameListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/naturalhistory/src/main/java/org/collectionspace/services/listener/naturalhistory/UpdateFormattedDisplayNameListener.java @@ -5,23 +5,27 @@ import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.common.api.TaxonFormatter; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants; import org.collectionspace.services.taxonomy.nuxeo.TaxonConstants; +import org.collectionspace.services.taxonomy.nuxeo.TaxonomyAuthorityConstants; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateFormattedDisplayNameListener extends AbstractCSEventListenerImpl { +public class UpdateFormattedDisplayNameListener extends AbstractCSEventSyncListenerImpl { public static final String RUN_AFTER_MODIFIED_PROPERTY = "UpdateFormattedDisplayNameListener.RUN_AFTER_MODIFIED"; + static final Log logger = LogFactory.getLog(UpdateFormattedDisplayNameListener.class); private static final String[] DISPLAY_NAME_PATH_ELEMENTS = TaxonConstants.DISPLAY_NAME_FIELD_NAME.split("/"); private static final String TERM_GROUP_LIST_FIELD_NAME = DISPLAY_NAME_PATH_ELEMENTS[0]; @@ -30,40 +34,54 @@ public class UpdateFormattedDisplayNameListener extends AbstractCSEventListenerI private static final String[] FORMATTED_DISPLAY_NAME_PATH_ELEMENTS = TaxonConstants.FORMATTED_DISPLAY_NAME_FIELD_NAME.split("/"); private static final String FORMATTED_DISPLAY_NAME_FIELD_NAME = FORMATTED_DISPLAY_NAME_PATH_ELEMENTS[2]; - final Logger logger = LoggerFactory.getLogger(UpdateFormattedDisplayNameListener.class); - @Override - public void handleEvent(Event event) { + @Override + public boolean shouldHandleEvent(Event event) { EventContext ec = event.getContext(); - if (isRegistered(event) && ec instanceof DocumentEventContext) { + if (ec instanceof DocumentEventContext) { DocumentEventContext context = (DocumentEventContext) ec; DocumentModel doc = context.getSourceDocument(); + String docType = doc.getType(); - logger.debug("docType=" + doc.getType()); + logger.debug("docType=" + docType); - if (doc.getType().startsWith(TaxonConstants.NUXEO_DOCTYPE) && + if (docType.startsWith(TaxonConstants.NUXEO_DOCTYPE) && + !docType.startsWith(TaxonomyAuthorityConstants.NUXEO_DOCTYPE) && !doc.isVersion() && !doc.isProxy() && !doc.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) { + return true; + } + } - String refName = (String) doc.getProperty(TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME); - RefName.AuthorityItem item = RefName.AuthorityItem.parse(refName); - String parentShortId = item.getParentShortIdentifier(); - - logger.debug("parentShortId=" + parentShortId); + return false; + } - if (!parentShortId.equals(TaxonBotGardenConstants.COMMON_VOCABULARY_SHORTID)) { - if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { - // Save the document, to get the BEFORE_DOC_UPDATE branch to run. - doc.getCoreSession().saveDocument(doc); - } - else if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + @Override + public void handleCSEvent(Event event) { + EventContext ec = event.getContext(); + DocumentEventContext context = (DocumentEventContext) ec; + DocumentModel doc = context.getSourceDocument(); + + String docType = doc.getType(); + logger.debug("docType=" + docType); + + String refName = (String) doc.getProperty(TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME); + RefName.AuthorityItem item = RefName.AuthorityItem.parse(refName); + String parentShortId = item.getParentShortIdentifier(); + + logger.debug("parentShortId=" + parentShortId); + + if (!parentShortId.equals(TaxonBotGardenConstants.COMMON_VOCABULARY_SHORTID)) { + if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED)) { + // Save the document, to get the BEFORE_DOC_UPDATE branch to run. + doc.getCoreSession().saveDocument(doc); + } + else if (event.getName().equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + DocumentModel previousDoc = (DocumentModel) context.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - updateFormattedDisplayNames(doc, previousDoc); - } - } + updateFormattedDisplayNames(doc, previousDoc); } } } @@ -110,4 +128,9 @@ public class UpdateFormattedDisplayNameListener extends AbstractCSEventListenerI return displayNames; } */ -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java index 285ffeac9..3523b8a14 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java @@ -1,16 +1,18 @@ package org.collectionspace.services.listener; -import java.util.Iterator; import java.util.List; import org.apache.commons.collections.ListUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.nuxeo.listener.AbstractCSEventPostCommitListenerImpl; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.LifeCycleConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventBundle; -import org.nuxeo.ecm.core.event.PostCommitEventListener; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; import org.nuxeo.elasticsearch.ElasticSearchComponent; import org.nuxeo.elasticsearch.api.ElasticSearchService; @@ -23,23 +25,45 @@ import org.nuxeo.runtime.api.Framework; * be reindexed; for example, if a related record denormalizes data from the updated record at * index time. */ -public class Reindex implements PostCommitEventListener { +public class Reindex extends AbstractCSEventPostCommitListenerImpl { + private final static Log logger = LogFactory.getLog(Reindex.class); + // FIXME: This listener runs asynchronously post-commit, so that reindexing records after a - // save does not hold up the save. In order to make it async, this class does not extend - // AbstractCSEventListenerImpl, because AbstractCSEventListenerImpl does not implement - // PostCommitEventListener (DRYD-477). Therefore this listener is not able to use the - // isRegistered method of AbstractCSEventListenerImpl to determine if it has been registered to - // run for the current tenant. Instead, it relies on the ReindexSupport listener, which does - // extend AbstractCSEventListenerImpl, to set a property in the event context that is used to - // determine if this listener should run. This means that this listener will be considered to - // be registered if and only if the ReindexSupport listener is registered. - - public static final String IS_REGISTERED_KEY = "Reindex.IS_REGISTERED"; + // save does not hold up the save. + public static final String PREV_COVERAGE_KEY = "Reindex.PREV_COVERAGE"; public static final String PREV_PUBLISH_TO_KEY = "Reindex.PREV_PUBLISH_TO"; + public static final String ELASTICSEARCH_ENABLED_PROP = "elasticsearch.enabled"; + + @Override + public boolean shouldHandleEventBundle(EventBundle eventBundle) { + if (Framework.isBooleanPropertyTrue(ELASTICSEARCH_ENABLED_PROP) && eventBundle.size() > 0) { + return true; + } + + return false; + } + + @Override + public boolean shouldHandleEvent(Event event) { + DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); + DocumentModel doc = eventContext.getSourceDocument(); + String docType = doc.getType(); + + if (docType.startsWith("Media")) { + return true; + } + + return false; + } + + @Override + @SuppressWarnings("unchecked") + public void handleCSEvent(Event event) { + DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); + DocumentModel doc = eventContext.getSourceDocument(); + String eventName = event.getName(); - @Override - public void handleEvent(EventBundle events) { // When a media record is created, reindex the material item that is referenced by its // coverage field. @@ -51,55 +75,42 @@ public class Reindex implements PostCommitEventListener { // TODO: Make this configurable. This is currently hardcoded to the needs of the material // profile/Material Order application. + + if ( + eventName.equals(DocumentEventTypes.DOCUMENT_CREATED) || + eventName.equals(DocumentEventTypes.DOCUMENT_UPDATED) + ) { + String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY); + String coverage = (String) doc.getProperty("media_common", "coverage"); - if (Framework.isBooleanPropertyTrue("elasticsearch.enabled") && events.size() > 0) { - Iterator iter = events.iterator(); - - while (iter.hasNext()) { - Event event = iter.next(); - DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); - Boolean isRegistered = (Boolean) eventContext.getProperty(IS_REGISTERED_KEY); + List prevPublishTo = (List) eventContext.getProperty(PREV_PUBLISH_TO_KEY); + List publishTo = (List) doc.getProperty("media_materials", "publishToList"); - if (isRegistered != null && isRegistered == true) { - DocumentModel doc = eventContext.getSourceDocument(); - String docType = doc.getType(); - String eventName = event.getName(); - - if (docType.startsWith("Media")) { - if ( - eventName.equals(DocumentEventTypes.DOCUMENT_CREATED) || - eventName.equals(DocumentEventTypes.DOCUMENT_UPDATED) - ) { - String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY); - String coverage = (String) doc.getProperty("media_common", "coverage"); - - List prevPublishTo = (List) eventContext.getProperty(PREV_PUBLISH_TO_KEY); - List publishTo = (List) doc.getProperty("media_materials", "publishToList"); - - if (doc.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) { - reindex(doc.getRepositoryName(), coverage); - } - else if ( - !ListUtils.isEqualList(prevPublishTo, publishTo) || - !StringUtils.equals(prevCoverage, coverage) - ) { - if (!StringUtils.equals(prevCoverage, coverage)) { - reindex(doc.getRepositoryName(), prevCoverage); - } - - reindex(doc.getRepositoryName(), coverage); - } - } - else if (eventName.equals(DocumentEventTypes.DOCUMENT_REMOVED)) { - String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY); - - reindex(doc.getRepositoryName(), prevCoverage); - } - } + if (doc.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) { + reindex(doc.getRepositoryName(), coverage); + } + else if ( + !ListUtils.isEqualList(prevPublishTo, publishTo) || + !StringUtils.equals(prevCoverage, coverage) + ) { + if (!StringUtils.equals(prevCoverage, coverage)) { + reindex(doc.getRepositoryName(), prevCoverage); } + + reindex(doc.getRepositoryName(), coverage); } } - } + else if (eventName.equals(DocumentEventTypes.DOCUMENT_REMOVED)) { + String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY); + + reindex(doc.getRepositoryName(), prevCoverage); + } + } + + @Override + protected Log getLogger() { + return logger; + } private void reindex(String repositoryName, String refName) { if (StringUtils.isEmpty(refName)) { diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java index 313e227d4..6281328c3 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java @@ -3,7 +3,11 @@ package org.collectionspace.services.listener; import java.io.Serializable; import java.util.List; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.event.CoreEventConstants; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; @@ -13,7 +17,7 @@ import org.nuxeo.runtime.api.Framework; /** * Event listener that stores the values of fields of interest before documents are updated or - * deleted. This is necessary because the previous/deleted doument model will not be available + * deleted. This is necessary because the previous/deleted document model will not be available * to a post-modification/deletion event listener. Storing the previous/deleted values allows * the post-modification/deletion event listener to take action if a field value was changed, * or if a document was deleted that had a certain field value. @@ -24,10 +28,26 @@ import org.nuxeo.runtime.api.Framework; * a single class that implements both PostCommitEventListener and EventListener (such a listener * will only run synchronously). */ -public class ReindexSupport extends AbstractCSEventListenerImpl { +public class ReindexSupport extends AbstractCSEventSyncListenerImpl { + final static Log logger = LogFactory.getLog(ReindexSupport.class); @Override - public void handleEvent(Event event) { + public boolean shouldHandleEvent(Event event) { + if (Framework.isBooleanPropertyTrue(Reindex.ELASTICSEARCH_ENABLED_PROP) && event instanceof DocumentEventContext) { + DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); + DocumentModel doc = eventContext.getSourceDocument(); + String docType = doc.getType(); + if (docType.startsWith("Media")) { + return true; + } + } + + return false; + } + + @Override + @SuppressWarnings("unchecked") + public void handleCSEvent(Event event) { // When a media record is about to be updated, store the value of the coverage and // publishToList fields. @@ -35,37 +55,26 @@ public class ReindexSupport extends AbstractCSEventListenerImpl { // TODO: Make this configurable. This is currently hardcoded to the needs of the material // profile/Material Order application. + DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); + DocumentModel doc = eventContext.getSourceDocument(); + String eventName = event.getName(); - if (isRegistered(event)) { - DocumentEventContext eventContext = (DocumentEventContext) event.getContext(); - - // Set a property if this listener is registered for the current tenant. This allows - // the Reindex listener to determine if it should run (since it is async, it cannot - // extend AbstractCSEventListenerImpl, so it cannot use the isRegistered method). - - eventContext.setProperty(Reindex.IS_REGISTERED_KEY, true); + if (eventName.equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { + DocumentModel previousDoc = (DocumentModel) eventContext.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); + String coverage = (String) previousDoc.getProperty("media_common", "coverage"); + List publishTo = (List) previousDoc.getProperty("media_materials", "publishToList"); - if (Framework.isBooleanPropertyTrue("elasticsearch.enabled")) { - DocumentModel doc = eventContext.getSourceDocument(); - String docType = doc.getType(); - String eventName = event.getName(); - - if (docType.startsWith("Media")) { - if (eventName.equals(DocumentEventTypes.BEFORE_DOC_UPDATE)) { - DocumentModel previousDoc = (DocumentModel) eventContext.getProperty(CoreEventConstants.PREVIOUS_DOCUMENT_MODEL); - String coverage = (String) previousDoc.getProperty("media_common", "coverage"); - List publishTo = (List) previousDoc.getProperty("media_materials", "publishToList"); - - eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage); - eventContext.setProperty(Reindex.PREV_PUBLISH_TO_KEY, (Serializable) publishTo); - } - else if (eventName.equals(DocumentEventTypes.ABOUT_TO_REMOVE)) { - String coverage = (String) doc.getProperty("media_common", "coverage"); - - eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage); - } - } - } + eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage); + eventContext.setProperty(Reindex.PREV_PUBLISH_TO_KEY, (Serializable) publishTo); } + else if (eventName.equals(DocumentEventTypes.ABOUT_TO_REMOVE)) { + String coverage = (String) doc.getProperty("media_common", "coverage"); + eventContext.setProperty(Reindex.PREV_COVERAGE_KEY, coverage); + } + } + + @Override + public Log getLogger() { + return logger; } } diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java index e04a63615..c1531c162 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java @@ -2,68 +2,53 @@ package org.collectionspace.services.listener; import java.io.Serializable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.common.api.CommonAPI; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.collectionspace.services.nuxeo.util.NuxeoUtils; + import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.blobholder.BlobHolder; import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder; -//import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; -import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -//import org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants; import org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateImageDerivatives extends AbstractCSEventListenerImpl { +public class UpdateImageDerivatives extends AbstractCSEventSyncListenerImpl { // All Nuxeo sessions that get passed around to CollectionSpace code need to // be wrapped inside of a CoreSessionWrapper. For example: - // CoreSessionInterface coreSession = new - // CoreSessionWrapper(docEventContext.getCoreSession()); - - private final static Logger logger = LoggerFactory.getLogger(UpdateImageDerivatives.class); - + // CoreSessionInterface coreSession = new CoreSessionWrapper(docEventContext.getCoreSession()); + private static final Log logger = LogFactory.getLog(UpdateImageDerivatives.class); + + @Override + public boolean shouldHandleEvent(Event event) { + return event.getContext() instanceof DocumentEventContext; + } + @Override - public void handleEvent(Event event) { - if (logger.isTraceEnabled()) { - logger.trace(String.format("Entering handleEvent in '%s'...", getClass().getName())); - } + public void handleCSEvent(Event event) { + DocumentEventContext docEventContext = (DocumentEventContext) event.getContext(); + DocumentModel docModel = docEventContext.getSourceDocument(); - if (shouldProcessEvent(event) == true) { - DocumentEventContext docEventContext = (DocumentEventContext) event.getContext(); - DocumentModel docModel = docEventContext.getSourceDocument(); + String source = (String)docModel.getProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME, + CommonAPI.NUXEO_DUBLINCORE_SOURCE); - String eventType = event.getName(); + if (source != null && source.equalsIgnoreCase(CommonAPI.URL_SOURCED_PICTURE)) { + CoreSessionInterface nuxeoSession = new CoreSessionWrapper(docEventContext.getCoreSession()); + purgeOriginalImage(docModel, nuxeoSession); + nuxeoSession.save(); + } else { if (logger.isTraceEnabled()) { - logger.trace(String.format("A(n) '%s' event was received by the %s event listener.", - eventType, getClass().getName())); - //logg - } - - String source = (String)docModel.getProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME, - CommonAPI.NUXEO_DUBLINCORE_SOURCE); - - if (source != null && source.equalsIgnoreCase(CommonAPI.URL_SOURCED_PICTURE)) { - CoreSessionInterface nuxeoSession = new CoreSessionWrapper(docEventContext.getCoreSession()); - purgeOriginalImage(docModel, nuxeoSession); - nuxeoSession.save(); - } else { - if (logger.isTraceEnabled()) { - logger.trace(String.format("The Nuxeo document titled '%s' did not need processing by the '%s' Nuxeo listener.", - docModel.getTitle(), getClass().getName())); - } + logger.trace(String.format("The Nuxeo document titled '%s' did not need processing by the '%s' Nuxeo listener.", + docModel.getTitle(), getClass().getName())); } - } - - if (logger.isTraceEnabled()) { - logger.trace(String.format("Exiting handleEvent in '%s'.", getClass().getName())); - } + } } private void purgeOriginalImage(DocumentModel docModel, CoreSessionInterface nuxeoSession) { @@ -72,7 +57,7 @@ public class UpdateImageDerivatives extends AbstractCSEventListenerImpl { // just disassociates the blob content (aka, the original image) from the document. // docModel.setPropertyValue("file:content", (Serializable) null); - + // // Removing this facet ensures the original derivatives are unchanged when // we call the save method. If we didn't remove the face, then all the @@ -86,12 +71,12 @@ public class UpdateImageDerivatives extends AbstractCSEventListenerImpl { // Nuxeo will still tread this document as a Picture document. // NuxeoUtils.addFacet(docModel, ImagingDocumentConstants.PICTURE_FACET); - + // // Finally, we need to remove the actual blob/image bits that are store on disk. // DocumentBlobHolder docBlobHolder = (DocumentBlobHolder) docModel.getAdapter(BlobHolder.class); - Blob blob = docBlobHolder.getBlob(); + Blob blob = docBlobHolder.getBlob(); if (blob == null) { logger.error(String.format("Could not get blob for original image. Trying to delete original for: '%s'", docModel.getTitle())); @@ -100,23 +85,14 @@ public class UpdateImageDerivatives extends AbstractCSEventListenerImpl { logger.debug(String.format("Started thread '%s' to delete file of blob '%s'.", thread.getId(), blob.getFilename())); } - + if (logger.isTraceEnabled()) { - logger.trace(String.format("Exiting handleEvent in '%s'.", getClass().getName())); - } + logger.trace(String.format("Exiting handleEvent in '%s'.", getClass().getName())); + } } - private boolean shouldProcessEvent(Event event) { - boolean result = false; - - EventContext eventContext = event.getContext(); - if (eventContext != null) { - if (isRegistered(event) && eventContext instanceof DocumentEventContext) { - result = true; - } - } - - return result; + @Override + public Log getLogger() { + return logger; } - -} +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java index 1d60b06ca..f81ab0705 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java @@ -2,11 +2,9 @@ package org.collectionspace.services.listener; import java.util.GregorianCalendar; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.collectionspace.services.client.LocationAuthorityClient; -import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.document.DocumentException; @@ -15,8 +13,9 @@ import org.collectionspace.services.common.api.RefName; import org.collectionspace.services.movement.nuxeo.MovementConstants; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; import org.collectionspace.services.nuxeo.util.NuxeoUtils; + import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; @@ -24,23 +23,19 @@ import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEventListenerImpl { - private final static Logger logger = LoggerFactory.getLogger(AbstractUpdateObjectLocationValues.class); +public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEventSyncListenerImpl { // FIXME: Make the following message, or its equivalent, a constant usable by all event listeners private final static String NO_FURTHER_PROCESSING_MESSAGE = "This event listener will not continue processing this event ..."; - + private final static GregorianCalendar EARLIEST_COMPARISON_DATE = new GregorianCalendar(1600, 1, 1); private final static String RELATIONS_COMMON_SCHEMA = "relations_common"; // FIXME: Get from external constant - + private final static String COLLECTIONOBJECT_DOCTYPE = CollectionObjectConstants.NUXEO_DOCTYPE; private final static String RELATION_DOCTYPE = RelationConstants.NUXEO_DOCTYPE;//"Relation"; // FIXME: Get from external constant private final static String MOVEMENT_DOCTYPE = MovementConstants.NUXEO_DOCTYPE; - + private final static String SUBJECT_CSID_PROPERTY = "subjectCsid"; // FIXME: Get from external constant private final static String OBJECT_CSID_PROPERTY = "objectCsid"; // FIXME: Get from external constant private final static String SUBJECT_DOCTYPE_PROPERTY = "subjectDocumentType"; // FIXME: Get from external constant @@ -54,111 +49,45 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent protected final static String COLLECTIONSPACE_CORE_SCHEMA = "collectionspace_core"; // FIXME: Get from external constant protected final static String CREATED_AT_PROPERTY = "createdAt"; // FIXME: Get from external constant protected final static String UPDATED_AT_PROPERTY = "updatedAt"; // FIXME: Get from external constant - + // Use this meta URN/refname to mark computed locations that are indeterminate private final static String INDETERMINATE_ID = "indeterminate"; protected final static String INDETERMINATE_LOCATION = RefName.buildAuthorityItem(INDETERMINATE_ID, LocationAuthorityClient.SERVICE_NAME, INDETERMINATE_ID, INDETERMINATE_ID, "~Indeterminate Location~").toString(); - // SQL clauses - private final static String NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT = - "AND ecm:isCheckedInVersion = 0" - + " AND ecm:isProxy = 0 "; - private final static String ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT = - "AND (ecm:currentLifeCycleState <> 'deleted') " - + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT; - // Used to set/get temp values in a DocumentModel instance private static final String IGNORE_LOCATION_UPDATE_EVENT_LABEL = "IGNORE_LOCATION_UPDATE_EVENT"; - + public enum EventNotificationDocumentType { // Document type about which we've received a notification - MOVEMENT, RELATION, COLLECTIONOBJECT; } - private static void logEvent(Event event, String message) { - logEvent(event, message, false); - } - - private static void logEvent(Event event, String message, boolean forceLogging) { - if (logger.isDebugEnabled() || forceLogging) { - DocumentEventContext docEventContext = (DocumentEventContext) event.getContext(); - DocumentModel docModel = docEventContext.getSourceDocument(); - String eventType = event.getName(); - String csid = NuxeoUtils.getCsid(docModel); - - logger.debug(String.format("### %s:", message != null ? message : "Unspecified")); - logger.debug(String.format("### \t-Event type: %s", eventType)); - - logger.debug("### \t-Target documment:"); - logger.debug(String.format("### \t\tCSID=%s", csid)); - logger.debug(String.format("### \t\tDocType=%s", docModel.getDocumentType().getName())); - - if (documentMatchesType(docModel, RELATION_DOCTYPE)) { - String subjectDocType = (String) docModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_DOCTYPE_PROPERTY); - String objectDocType = (String) docModel.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_DOCTYPE_PROPERTY); - String subjectCsid = (String) docModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_CSID_PROPERTY); - String objectCsid = (String) docModel.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_CSID_PROPERTY); - logger.debug(String.format("\tRelation info subject=%s:%s\tobject=%s:%s", - subjectCsid, subjectDocType, objectCsid, objectDocType)); - } else if (documentMatchesType(docModel, MOVEMENT_DOCTYPE)) { - String currentLocation = (String) docModel.getProperty(MOVEMENTS_COMMON_SCHEMA, CURRENT_LOCATION_ELEMENT_NAME); - GregorianCalendar locationDate = (GregorianCalendar) docModel.getProperty(MOVEMENTS_COMMON_SCHEMA, LOCATION_DATE_PROPERTY); - logger.debug("### \t-Movement Info:"); - logger.debug(String.format("### \t\tCSID=%s", csid)); - logger.debug(String.format("### \t\tlocation=%s", currentLocation != null ? currentLocation : "null")); - if (locationDate != null) { - logger.debug(String.format("### \t\tdate=%1$tm-%1$te-%1$tY", locationDate != null ? locationDate : "")); - } else { - logger.debug(String.format("### \t\tdate=")); - } - } else { - logger.debug(String.format("### Ignoring Update Location event: %s", eventType)); - } - } - } - - /* - * Figure out if we should ignore this event. - */ - private boolean shouldIgnoreEvent(DocumentEventContext docEventContext, String ignoreEventLabel) { - boolean result = false; - - Boolean shouldIgnoreEvent = (Boolean) docEventContext.getProperties().get(DOCMODEL_CONTEXT_PROPERTY_PREFIX + ignoreEventLabel); + public boolean shouldHandleEvent(Event event) { + // Ensure we have all the event data we need to proceed. + if (event.getContext() instanceof DocumentEventContext == false) { + return false; + } + // + // This event handler itself sometimes triggers additional events. To prevent unnecessary cascading event handling, this event + // handler sets a temp flag in the document model's context indicating we should ignore cascading events. This method checks that flag and + // exits if it is set. + DocumentEventContext docEventContext = (DocumentEventContext) event.getContext(); + Boolean shouldIgnoreEvent = (Boolean) getContextPropertyValue(docEventContext, IGNORE_LOCATION_UPDATE_EVENT_LABEL); if (shouldIgnoreEvent != null && shouldIgnoreEvent) { - result = true; + return false; } - return result; + return true; } - + @Override - public void handleEvent(Event event) { - // Ensure we have all the event data we need to proceed. - if (isRegistered(event) == false || !(event.getContext() instanceof DocumentEventContext)) { - if (logger.isTraceEnabled() == true) { - logEvent(event, "Update Location", true); - } - return; - } - - Map params = this.getParams(event); // Will be null if no params were configured. - logEvent(event, "Update Location"); - + public void handleCSEvent(Event event) { DocumentEventContext docEventContext = (DocumentEventContext) event.getContext(); - DocumentModel eventDocModel = docEventContext.getSourceDocument(); + DocumentModel eventDocModel = docEventContext.getSourceDocument(); String eventType = event.getName(); boolean isAboutToBeRemovedEvent = eventType.equals(DocumentEventTypes.ABOUT_TO_REMOVE); - - // - // This event handler itself sometimes triggers additional events. To prevent unnecessary cascading event handling, this event - // handler sets a flag in the document model indicating we should ignore cascading events. This method checks that flag and - // exits if it is set. - if (shouldIgnoreEvent(docEventContext, IGNORE_LOCATION_UPDATE_EVENT_LABEL) == true) { - return; - } - + // // Ensure this event relates to a relationship record (between cataloging and movement records) or a movement record. If so, get the CSID // of the corresponding movement record. Otherwise, exit. @@ -177,8 +106,8 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // Otherwise, get a Movement CSID directly from the Movement record. eventMovementCsid = NuxeoUtils.getCsid(eventDocModel); if (Tools.isBlank(eventMovementCsid)) { - logger.warn("Could not obtain CSID for Movement record from document event."); - logger.warn(NO_FURTHER_PROCESSING_MESSAGE); + getLogger().warn("Could not obtain CSID for Movement record from document event."); + getLogger().warn(NO_FURTHER_PROCESSING_MESSAGE); return; } } else if (documentMatchesType(eventDocModel, COLLECTIONOBJECT_DOCTYPE) && @@ -206,7 +135,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // // Get a list of all the CollectionObject records affected by this event. - // + // CoreSessionInterface session = new CoreSessionWrapper(docEventContext.getCoreSession()); // NOTE: All Nuxeo sessions that get passed around to CollectionSpace code need to be wrapped inside of a CoreSessionWrapper Set collectionObjectCsids = new HashSet<>(); if (notificationDocumentType == EventNotificationDocumentType.RELATION) { @@ -227,15 +156,14 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent if (collectionObjectCsids.isEmpty() == true) { return; } - + // // Now iterate through the list of affected CollectionObjects found. // For each CollectionObject, obtain its most recent, related Movement record, // and update update the Computed Current Location field if needed. // DocumentModel collectionObjectDocModel; - DocumentModel mostRecentMovementDocModel; - for (String collectionObjectCsid : collectionObjectCsids) { + for (String collectionObjectCsid : collectionObjectCsids) { collectionObjectDocModel = getCurrentDocModelFromCsid(session, collectionObjectCsid); if (isActiveDocument(collectionObjectDocModel) == true) { DocumentModel movementDocModel = getCurrentDocModelFromCsid(session, eventMovementCsid); @@ -249,7 +177,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // Update the CollectionObject's Computed Current Location field with the Movement record's location // boolean didLocationChange = updateCollectionObjectLocation(collectionObjectDocModel, movementDocModel, mostRecentLocation); - + // // If the location changed, save/persist the change to the repository and log the change. // @@ -257,23 +185,23 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent persistLocationChange(session, collectionObjectDocModel); // // Log an INFO message if we've changed the cataloging record's location - // - if (logger.isInfoEnabled()) { + // + if (getLogger().isInfoEnabled()) { String computedCurrentLocationRefName = (String) collectionObjectDocModel.getProperty(COLLECTIONOBJECTS_COMMON_SCHEMA, COMPUTED_CURRENT_LOCATION_PROPERTY); - logger.info(String.format("Updating cataloging record=%s current location to %s", + getLogger().info(String.format("Updating cataloging record=%s current location to %s", NuxeoUtils.getCsid(collectionObjectDocModel), computedCurrentLocationRefName)); } } } } } - + // // Disable update/documentModified events and persist the location change. // private void persistLocationChange(CoreSessionInterface session, DocumentModel collectionObjectDocModel) { - + // // Set a flag in the document model indicating that we want to ignore the update event that // will be triggered by this save/persist request. @@ -282,7 +210,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // // Save/Persist the document to the DB session.saveDocument(collectionObjectDocModel); - + // // Clear the flag we set to ignore events triggered by our save request. clearDocModelContextProperty(collectionObjectDocModel, IGNORE_LOCATION_UPDATE_EVENT_LABEL); @@ -296,7 +224,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent * @throws ClientException * @return the CSIDs of the CollectionObject records, if any, which are * related to the Movement record. - * @throws DocumentException + * @throws DocumentException */ private Set getCollectionObjectCsidsRelatedToMovement(String movementCsid, CoreSessionInterface coreSession) throws ClientException { @@ -323,18 +251,18 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent + ")" + ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT, RELATION_DOCTYPE, RELATIONS_COMMON_SCHEMA, movementCsid, COLLECTIONOBJECT_DOCTYPE); - + DocumentModelList relationDocModels = null; try { relationDocModels = coreSession.query(query); } catch (DocumentException e) { - logger.error(e.getMessage()); + getLogger().error(e); } - + if (relationDocModels == null || relationDocModels.isEmpty()) { return csids; } - + // Iterate through the list of Relation records found and build // a list of CollectionObject CSIDs, by extracting the relevant CSIDs // from those Relation records. @@ -345,120 +273,21 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent csids.add(csid); } } - + return csids; } - -// FIXME: Generic methods like many of those below might be split off from -// this specific event listener/handler, into an event handler utilities -// class, base classes, or otherwise. -// -// FIXME: Identify whether the equivalent of the documentMatchesType utility -// method is already implemented and substitute a call to the latter if so. -// This may well already exist. - /** - * Identifies whether a document matches a supplied document type. - * - * @param docModel a document model. - * @param docType a document type string. - * @return true if the document matches the supplied document type; false if - * it does not. - */ - protected static boolean documentMatchesType(DocumentModel docModel, String docType) { - if (docModel == null || Tools.isBlank(docType)) { - return false; - } - if (docModel.getType().startsWith(docType)) { - return true; - } else { - return false; - } - } - - protected static boolean isActiveDocument(DocumentModel docModel) { - return isActiveDocument(docModel, false, null); - } - - /** - * Identifies whether a document is an active document; currently, whether - * it is not in a 'deleted' workflow state. - * - * @param docModel - * @return true if the document is an active document; false if it is not. - */ - protected static boolean isActiveDocument(DocumentModel docModel, boolean isAboutToBeRemovedEvent, String aboutToBeRemovedCsid) { - boolean isActiveDocument = false; - - if (docModel != null) { - if (!docModel.getCurrentLifeCycleState().contains(WorkflowClient.WORKFLOWSTATE_DELETED)) { - isActiveDocument = true; - } - // - // If doc model is the target of the "aboutToBeRemoved" event, mark it as not active. - // - if (isAboutToBeRemovedEvent && Tools.notBlank(aboutToBeRemovedCsid)) { - if (NuxeoUtils.getCsid(docModel).equalsIgnoreCase(aboutToBeRemovedCsid)) { - isActiveDocument = false; - } - } - } - - return isActiveDocument; - } - - /** - * Returns the current document model for a record identified by a CSID. - * - * Excludes documents which have been versioned (i.e. are a non-current - * version of a document), are a proxy for another document, or are - * un-retrievable via their CSIDs. - * - * @param session a repository session. - * @param csid a CollectionObject identifier (CSID) - * @return a document model for the document identified by the supplied - * CSID. - */ - protected static DocumentModel getCurrentDocModelFromCsid(CoreSessionInterface session, String csid) { - DocumentModelList docModelList = null; - - if (Tools.isEmpty(csid)) { - return null; - } - - try { - final String query = "SELECT * FROM " - + NuxeoUtils.BASE_DOCUMENT_TYPE - + " WHERE " - + NuxeoUtils.getByNameWhereClause(csid) - + " " - + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT; - docModelList = session.query(query); - } catch (Exception e) { - logger.warn("Exception in query to get active document model for CSID: " + csid, e); - } - - if (docModelList == null || docModelList.isEmpty()) { - logger.warn("Could not get active document models for CSID=" + csid); - return null; - } else if (docModelList.size() != 1) { - logger.error("Found more than 1 active document with CSID=" + csid); - return null; - } - - return docModelList.get(0); - } - + // // Returns true if this event is for the creation of a new relationship record // private static boolean isCreatingNewRelationship(Event event) { boolean result = false; - + DocumentModel docModel = ((DocumentEventContext)event.getContext()).getSourceDocument(); if (event.getName().equals(DocumentEventTypes.DOCUMENT_CREATED) && documentMatchesType(docModel, RELATION_DOCTYPE)) { result = true; } - + return result; } @@ -495,7 +324,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent * @throws ClientException * @return the most recent Movement record related to the CollectionObject * identified by the supplied CSID. - * @throws DocumentException + * @throws DocumentException */ protected String getMostRecentLocation(Event event, CoreSessionInterface session, String collectionObjectCsid, @@ -504,7 +333,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // Assume we can determine the most recent location by creating an indeterminate result // String result = INDETERMINATE_LOCATION; - + // // Get active Relation records involving Movement records related to this CollectionObject. // @@ -519,31 +348,31 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent + ")" + ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT, RELATION_DOCTYPE, RELATIONS_COMMON_SCHEMA, collectionObjectCsid, MOVEMENT_DOCTYPE); - logger.trace("query=" + query); + getLogger().trace("query=" + query); DocumentModelList relationDocModels; try { relationDocModels = session.query(query); } catch (DocumentException e) { - logger.error(e.getMessage()); + getLogger().error(e); return null; } - + if (isCreatingNewRelationship(event) == true) { DocumentModel newRelation = ((DocumentEventContext)event.getContext()).getSourceDocument(); relationDocModels.add(newRelation); } - + // // Remove redundant document models from the list. // - relationDocModels = removeRedundantRelations(relationDocModels); - + relationDocModels = removeRedundantRelations(relationDocModels); + // // Remove relationships that are with inactive movement records // relationDocModels = removeInactiveRelations(session, relationDocModels, isAboutToBeRemovedEvent, eventMovementCsid); - + // // If there are no candidate relationships after we removed the duplicates and inactive ones, // throw an exception. @@ -551,7 +380,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent if (relationDocModels == null || relationDocModels.size() == 0) { return result; } - + // // If there is only one related movement record, then return it as the most recent // movement record -but only if it's current location element is not empty. @@ -560,17 +389,17 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent DocumentModel relationDocModel = relationDocModels.get(0); DocumentModel movementDocModel = getMovementDocModelFromRelation(session, relationDocModel); String location = (String) movementDocModel.getProperty(MOVEMENTS_COMMON_SCHEMA, CURRENT_LOCATION_ELEMENT_NAME); - + if (Tools.isBlank(location) == false) { result = location; } else { // currentLocation must be set - logger.error(String.format("Movement record=%s is missing its required location value and so is excluded from the computation of cataloging record=%s's current location.", + getLogger().error(String.format("Movement record=%s is missing its required location value and so is excluded from the computation of cataloging record=%s's current location.", NuxeoUtils.getCsid(movementDocModel), collectionObjectCsid)); } return result; } - + // // Iterate through the list (>2) of related movement records, to find the related // Movement record with the most recent location date. @@ -590,18 +419,18 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent } movementDocModel = getCurrentDocModelFromCsid(session, relatedMovementCsid); String location = (String) movementDocModel.getProperty(MOVEMENTS_COMMON_SCHEMA, CURRENT_LOCATION_ELEMENT_NAME); - + // // If the current Movement record lacks a location date, it cannot // be established as the most recent Movement record; skip over it. // GregorianCalendar locationDate = (GregorianCalendar) movementDocModel.getProperty(MOVEMENTS_COMMON_SCHEMA, LOCATION_DATE_PROPERTY); if (locationDate == null) { - logger.info(String.format("Movement record=%s has no location date and so is excluded from computation of cataloging record=%s current location.", + getLogger().info(String.format("Movement record=%s has no location date and so is excluded from computation of cataloging record=%s current location.", NuxeoUtils.getCsid(movementDocModel), collectionObjectCsid)); continue; } - + GregorianCalendar updatedDate = (GregorianCalendar) movementDocModel.getProperty(COLLECTIONSPACE_CORE_SCHEMA, UPDATED_AT_PROPERTY); if (locationDate.after(mostRecentLocationDate)) { mostRecentLocationDate = locationDate; @@ -619,17 +448,17 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent } } } - + return result; } - + // // This method assumes that the relation passed into this method is between a Movement record // and a CollectionObject (cataloging) record. // - private static DocumentModel getMovementDocModelFromRelation(CoreSessionInterface session, DocumentModel relationDocModel) { + private DocumentModel getMovementDocModelFromRelation(CoreSessionInterface session, DocumentModel relationDocModel) { String movementCsid = null; - + String subjectDocType = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_DOCTYPE_PROPERTY); if (subjectDocType.endsWith(MOVEMENT_DOCTYPE)) { movementCsid = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_CSID_PROPERTY); @@ -642,11 +471,11 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // // Compares two Relation document models to see if they're either identical or - // reciprocal equivalents. + // reciprocal equivalents. // private static boolean compareRelationDocModels(DocumentModel r1, DocumentModel r2) { boolean result = false; - + String r1_subjectDocType = (String) r1.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_DOCTYPE_PROPERTY); String r1_objectDocType = (String) r1.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_DOCTYPE_PROPERTY); String r1_subjectCsid = (String) r1.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_CSID_PROPERTY); @@ -656,13 +485,13 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent String r2_objectDocType = (String) r2.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_DOCTYPE_PROPERTY); String r2_subjectCsid = (String) r2.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_CSID_PROPERTY); String r2_objectCsid = (String) r2.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_CSID_PROPERTY); - + // Check to see if they're identical if (r1_subjectDocType.equalsIgnoreCase(r2_subjectDocType) && r1_objectDocType.equalsIgnoreCase(r2_objectDocType) && r1_subjectCsid.equalsIgnoreCase(r2_subjectCsid) && r1_objectCsid.equalsIgnoreCase(r2_objectCsid)) { return true; } - + // Check to see if they're reciprocal if (r1_subjectDocType.equalsIgnoreCase(r2_objectDocType) && r1_objectDocType.equalsIgnoreCase(r2_subjectDocType) && r1_subjectCsid.equalsIgnoreCase(r2_objectCsid) && r1_objectCsid.equalsIgnoreCase(r2_subjectCsid)) { @@ -677,7 +506,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent // private static DocumentModelList removeRedundantRelations(DocumentModelList relationDocModelList) { DocumentModelList resultList = null; - + if (relationDocModelList != null && relationDocModelList.size() > 0) { resultList = new DocumentModelListImpl(); for (DocumentModel relationDocModel : relationDocModelList) { @@ -686,21 +515,20 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent } } } - - // TODO Auto-generated method stub + return resultList; } - + // // Return just the list of active relationships with active Movement records. A value of 'true' for the 'isAboutToBeRemovedEvent' // argument indicates that relationships with the 'movementCsid' record should be considered inactive. // - private static DocumentModelList removeInactiveRelations(CoreSessionInterface session, + private DocumentModelList removeInactiveRelations(CoreSessionInterface session, DocumentModelList relationDocModelList, boolean isAboutToBeRemovedEvent, String eventMovementCsid) { DocumentModelList resultList = null; - + if (relationDocModelList != null && relationDocModelList.size() > 0) { resultList = new DocumentModelListImpl(); for (DocumentModel relationDocModel : relationDocModelList) { @@ -709,29 +537,28 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent if (isActiveDocument(movementDocModel, isAboutToBeRemovedEvent, eventMovementCsid) == true) { resultList.add(relationDocModel); } else { - logger.debug(String.format("Disqualified relationship=%s with Movement record=%s from current location computation.", + getLogger().debug(String.format("Disqualified relationship=%s with Movement record=%s from current location computation.", NuxeoUtils.getCsid(relationDocModel), movementCsid)); } } } - + return resultList; } - // // Check to see if the Relation (or its equivalent reciprocal) is already in the list. // private static boolean existsInResultList(DocumentModelList relationDocModelList, DocumentModel relationDocModel) { boolean result = false; - + for (DocumentModel target : relationDocModelList) { if (compareRelationDocModels(relationDocModel, target) == true) { result = true; break; } } - + return result; } @@ -743,7 +570,7 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent * @param desiredDocType a desired document type. * @param relatedDocType a related document type. * @throws ClientException - * + * * @return the CSID from the desired document type in the relation. Returns * null if the Relation record does not involve both the desired * and related document types. @@ -753,13 +580,13 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent String csid = null; String subjectDocType = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_DOCTYPE_PROPERTY); String objectDocType = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_DOCTYPE_PROPERTY); - + if (subjectDocType.startsWith(desiredDocType) && objectDocType.startsWith(relatedDocType)) { // Use startsWith() method, because customized tenant type names differ in their suffix. csid = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_CSID_PROPERTY); } else if (subjectDocType.startsWith(relatedDocType) && objectDocType.startsWith(desiredDocType)) { csid = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, OBJECT_CSID_PROPERTY); } - + return csid; } @@ -779,4 +606,4 @@ public abstract class AbstractUpdateObjectLocationValues extends AbstractCSEvent protected abstract boolean updateCollectionObjectLocation(DocumentModel collectionObjectDocModel, DocumentModel movmentDocModel, String movementRecordsLocation); -} +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationAndCrateOnMove.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationAndCrateOnMove.java index 03e708619..cd593de64 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationAndCrateOnMove.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationAndCrateOnMove.java @@ -1,15 +1,18 @@ package org.collectionspace.services.listener; import java.io.Serializable; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.collectionspace.services.common.api.RefNameUtils; import org.collectionspace.services.common.api.Tools; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class UpdateObjectLocationAndCrateOnMove extends UpdateObjectLocationOnMove { - private final Logger logger = LoggerFactory.getLogger(UpdateObjectLocationAndCrateOnMove.class); + + // FIXME: We might experiment here with using log4j instead of Apache Commons Logging; + // am using the latter to follow Ray's pattern for now + private final Log logger = LogFactory.getLog(UpdateObjectLocationAndCrateOnMove.class); // FIXME: Get values below from external constants private final static String COLLECTIONOBJECTS_ANTHROPOLOGY_SCHEMA = "collectionobjects_anthropology"; private final static String MOVEMENTS_ANTHROPOLOGY_SCHEMA = "movements_anthropology"; @@ -22,14 +25,14 @@ public class UpdateObjectLocationAndCrateOnMove extends UpdateObjectLocationOnMo String mostRecentLocation) throws ClientException { boolean flag = super.updateCollectionObjectLocation(collectionObjectDocModel, movementDocModel, mostRecentLocation); collectionObjectDocModel = updateComputedCrateValue(collectionObjectDocModel, movementDocModel); - + return flag; } private DocumentModel updateComputedCrateValue(DocumentModel collectionObjectDocModel, DocumentModel movementDocModel) throws ClientException { - + // Get the current crate value from the Movement (the "new" value) String crateRefName = (String) movementDocModel.getProperty(MOVEMENTS_ANTHROPOLOGY_SCHEMA, CRATE_PROPERTY); @@ -81,7 +84,7 @@ public class UpdateObjectLocationAndCrateOnMove extends UpdateObjectLocationOnMo logger.trace("crate refName does NOT require updating."); } } - + return collectionObjectDocModel; } -} +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationOnMove.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationOnMove.java index 600481927..dfdde2be4 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationOnMove.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationOnMove.java @@ -1,14 +1,17 @@ package org.collectionspace.services.listener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.common.api.RefNameUtils; import org.collectionspace.services.common.api.Tools; + import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class UpdateObjectLocationOnMove extends AbstractUpdateObjectLocationValues { - private final Logger logger = LoggerFactory.getLogger(UpdateObjectLocationOnMove.class); + + private final Log logger = LogFactory.getLog(UpdateObjectLocationOnMove.class); @Override protected boolean updateCollectionObjectLocation(DocumentModel collectionObjectDocModel, @@ -28,7 +31,7 @@ public class UpdateObjectLocationOnMove extends AbstractUpdateObjectLocationValu movementRecordsLocation)); return result; } - + // Get the computed current location value of the CollectionObject. String existingComputedCurrentLocation = (String) collectionObjectDocModel.getProperty(COLLECTIONOBJECTS_COMMON_SCHEMA, COMPUTED_CURRENT_LOCATION_PROPERTY); @@ -39,7 +42,12 @@ public class UpdateObjectLocationOnMove extends AbstractUpdateObjectLocationValu COMPUTED_CURRENT_LOCATION_PROPERTY, movementRecordsLocation); result = true; // We've updated the location field. } - + return result; } -} + + @Override + public Log getLogger() { + return logger; + } +} \ No newline at end of file diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updaterelationsondelete/src/main/java/org/collectionspace/services/listener/UpdateRelationsOnDelete.java b/3rdparty/nuxeo/nuxeo-platform-listener/updaterelationsondelete/src/main/java/org/collectionspace/services/listener/UpdateRelationsOnDelete.java index bc54278a2..81bc6b154 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updaterelationsondelete/src/main/java/org/collectionspace/services/listener/UpdateRelationsOnDelete.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updaterelationsondelete/src/main/java/org/collectionspace/services/listener/UpdateRelationsOnDelete.java @@ -4,123 +4,106 @@ import java.util.ArrayList; import java.util.IllegalFormatException; import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.document.DocumentException; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper; -import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl; +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; + import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.impl.LifeCycleFilter; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class UpdateRelationsOnDelete extends AbstractCSEventListenerImpl { - final Logger logger = LoggerFactory.getLogger(UpdateRelationsOnDelete.class); +public class UpdateRelationsOnDelete extends AbstractCSEventSyncListenerImpl { + // FIXME: We might experiment here with using log4j instead of Apache Commons Logging; + // am using the latter to follow Ray's pattern for now + final Log logger = LogFactory.getLog(UpdateRelationsOnDelete.class); + // FIXME: Get these constant values from external sources rather than redeclaring here final static String RELATION_DOCTYPE = "Relation"; final static String RELATIONS_COMMON_SUBJECT_CSID_FIELD = "relations_common:subjectCsid"; final static String RELATIONS_COMMON_OBJECT_CSID_FIELD = "relations_common:objectCsid"; @Override - public void handleEvent(Event event) { - logger.trace("In handleEvent in UpdateRelationsOnDelete ..."); - + public boolean shouldHandleEvent(Event event) { EventContext eventContext = event.getContext(); - if (isRegistered(event) && isDocumentSoftDeletedEvent(eventContext)) { - - logger.trace("A soft deletion event was received by UpdateRelationsOnDelete ..."); - - DocumentEventContext docContext = (DocumentEventContext) eventContext; - DocumentModel docModel = docContext.getSourceDocument(); - - // Exclude soft deletion events involving Relation records themselves - // from handling by this event handler. - if (docModel != null && docModel.getType().startsWith(RELATION_DOCTYPE)) { - return; - } - - // Retrieve a list of relation records, where the soft deleted - // document provided in the context of the current event is - // either the subject or object of any relation - - // Build a query string - String csid = docModel.getName(); - - String queryString; - try { - queryString = - String.format("SELECT * FROM Relation WHERE ecm:isProxy = 0 AND (%1$s='%3$s' OR %2$s='%3$s')", - RELATIONS_COMMON_SUBJECT_CSID_FIELD, RELATIONS_COMMON_OBJECT_CSID_FIELD, csid); - logger.trace("Query string=" + queryString); - } catch (IllegalFormatException ife) { - logger.warn("Construction of formatted query string failed: ", ife); - logger.warn("Actions in this event listener will NOT be performed, as a result of a previous Exception."); - return; - } - - // Create a filter to exclude from the list results any records - // that have already been soft deleted or are locked - List workflowStatesToFilter = new ArrayList(); - workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_DELETED); - workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED); - workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED); - workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED); - - LifeCycleFilter workflowStateFilter = new LifeCycleFilter(null, workflowStatesToFilter); - - // Perform the filtered query - CoreSessionInterface session = new CoreSessionWrapper(docModel.getCoreSession()); - DocumentModelList matchingDocuments; - try { - matchingDocuments = session.query(queryString.toString(), workflowStateFilter); - } catch (DocumentException ce) { - logger.error("Error attempting to retrieve relation records where " - + "record of type '" + docModel.getType() + "' with CSID " + csid - + " is the subject or object of any relation: " + ce.getMessage()); - return; - } - - // Cycle through the list results, soft deleting each matching relation record - logger.info("Attempting to soft delete " + matchingDocuments.size() + " relation records pertaining to a soft deleted record."); - for (DocumentModel doc : matchingDocuments) { - doc.followTransition(WorkflowClient.WORKFLOWTRANSITION_DELETE); - } - + // Event must be a soft-delete event + if (isDocumentSoftDeletedEvent(eventContext)) { + return true; } - + + // Exclude soft deletion events involving Relation records themselves + // from handling by this event handler. + DocumentEventContext docContext = (DocumentEventContext) eventContext; + DocumentModel docModel = docContext.getSourceDocument(); + if (docModel != null && docModel.getType().startsWith(RELATION_DOCTYPE)) { + return false; + } + + return false; } + + @Override + public void handleCSEvent(Event event) { + EventContext eventContext = event.getContext(); + DocumentEventContext docContext = (DocumentEventContext) eventContext; + DocumentModel docModel = docContext.getSourceDocument(); + + // Retrieve a list of relation records, where the soft deleted + // document provided in the context of the current event is + // either the subject or object of any relation + String csid = docModel.getName(); + String queryString; + try { + queryString = + String.format("SELECT * FROM Relation WHERE ecm:isProxy = 0 AND (%1$s='%3$s' OR %2$s='%3$s')", + RELATIONS_COMMON_SUBJECT_CSID_FIELD, RELATIONS_COMMON_OBJECT_CSID_FIELD, csid); + logger.trace("Query string=" + queryString); + } catch (IllegalFormatException ife) { + logger.warn("Construction of formatted query string failed: ", ife); + logger.warn("Actions in this event listener will NOT be performed, as a result of a previous Exception."); + return; + } + + // Create a filter to exclude from the list results any records + // that have already been soft deleted or are locked + List workflowStatesToFilter = new ArrayList(); + workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_DELETED); + workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED); + workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED); + workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED); + + LifeCycleFilter workflowStateFilter = new LifeCycleFilter(null, workflowStatesToFilter); + + // Perform the filtered query + CoreSessionInterface session = new CoreSessionWrapper(docModel.getCoreSession()); + DocumentModelList matchingDocuments; + try { + matchingDocuments = session.query(queryString.toString(), workflowStateFilter); + } catch (DocumentException ce) { + logger.error("Error attempting to retrieve relation records where " + + "record of type '" + docModel.getType() + "' with CSID " + csid + + " is the subject or object of any relation: " + ce.getMessage()); + return; + } - // FIXME: Generic methods like the following might be split off - // into an event utilities class. - ADR 2012-12-05 - - /** - * Identifies whether a supplied event concerns a document that has - * been transitioned to the 'deleted' workflow state. - * - * @param eventContext an event context - * - * @return true if this event concerns a document that has - * been transitioned to the 'deleted' workflow state. - */ - private boolean isDocumentSoftDeletedEvent(EventContext eventContext) { - boolean isSoftDeletedEvent = false; - - if (eventContext instanceof DocumentEventContext) { - if (eventContext.getProperties().containsKey(WorkflowClient.WORKFLOWTRANSITION_TO) - && - (eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_DELETED) - || - eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED))) { - isSoftDeletedEvent = true; - } + // Cycle through the list results, soft deleting each matching relation record + logger.info("Attempting to soft delete " + matchingDocuments.size() + " relation records pertaining to a soft deleted record."); + for (DocumentModel doc : matchingDocuments) { + doc.followTransition(WorkflowClient.WORKFLOWTRANSITION_DELETE); } + } - return isSoftDeletedEvent; + @Override + public Log getLogger() { + return this.logger; } } diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/pom.xml b/3rdparty/nuxeo/nuxeo-platform-thumbnail/pom.xml index f8b76a51b..d789ae67a 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/pom.xml +++ b/3rdparty/nuxeo/nuxeo-platform-thumbnail/pom.xml @@ -28,14 +28,17 @@ org.nuxeo.ecm.core nuxeo-core-convert - ${nuxeo.core.version} org.nuxeo.ecm.platform nuxeo-platform-imaging-core - ${nuxeo.platform.version} provided + + org.collectionspace.services + org.collectionspace.services.common + ${project.version} + diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/AddThumbnailUnrestricted.java b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/AddThumbnailUnrestricted.java index bc52169c5..d4aaaa01b 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/AddThumbnailUnrestricted.java +++ b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/AddThumbnailUnrestricted.java @@ -8,6 +8,7 @@ import java.io.Serializable; import java.util.Calendar; import java.util.GregorianCalendar; +import org.collectionspace.services.nuxeo.util.ThumbnailConstants; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.CoreSession; diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/Thumbnail.java b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/Thumbnail.java index c76f8426d..a4a40bc67 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/Thumbnail.java +++ b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/Thumbnail.java @@ -1,7 +1,6 @@ package org.collectionspace.services.nuxeo.extension.thumbnail; -import java.io.Serializable; - +import org.collectionspace.services.nuxeo.util.ThumbnailConstants; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConverter.java b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConverter.java index bfeb4fd4d..8446ee5c3 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConverter.java +++ b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConverter.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.Serializable; import java.util.Map; +import org.collectionspace.services.nuxeo.util.ThumbnailConstants; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.blobholder.BlobHolder; import org.nuxeo.ecm.core.api.impl.blob.FileBlob; diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/UpdateThumbListener.java b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/UpdateThumbListener.java index fa9e5f22f..d74c86d7a 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/UpdateThumbListener.java +++ b/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/UpdateThumbListener.java @@ -1,5 +1,11 @@ package org.collectionspace.services.nuxeo.extension.thumbnail; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.collectionspace.services.nuxeo.listener.AbstractCSEventSyncListenerImpl; +import org.collectionspace.services.nuxeo.util.ThumbnailConstants; + import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; @@ -7,12 +13,19 @@ import org.nuxeo.ecm.core.api.blobholder.BlobHolder; import org.nuxeo.ecm.core.api.event.DocumentEventTypes; import org.nuxeo.ecm.core.event.Event; import org.nuxeo.ecm.core.event.EventContext; -import org.nuxeo.ecm.core.event.EventListener; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; -public class UpdateThumbListener implements EventListener { - - public void handleEvent(Event event) throws ClientException { +public class UpdateThumbListener extends AbstractCSEventSyncListenerImpl { + final Log logger = LogFactory.getLog(UpdateThumbListener.class); + + @Override + public boolean shouldHandleEvent(Event event) { + EventContext ec = event.getContext(); + + return ec instanceof DocumentEventContext; + } + + public void handleCSEvent(Event event) throws ClientException { EventContext ec = event.getContext(); if (ec instanceof DocumentEventContext) { DocumentEventContext context = (DocumentEventContext) ec; @@ -40,4 +53,9 @@ public class UpdateThumbListener implements EventListener { } } } + + @Override + public Log getLogger() { + return logger; + } } diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateAccessCodeBatchJob.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateAccessCodeBatchJob.java index 50acfd79f..e49339fd4 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateAccessCodeBatchJob.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateAccessCodeBatchJob.java @@ -10,6 +10,7 @@ import org.collectionspace.services.client.TaxonomyAuthorityClient; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectBotGardenConstants; import org.collectionspace.services.collectionobject.nuxeo.CollectionObjectConstants; import org.collectionspace.services.common.api.RefName; +import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.invocable.InvocationResults; import org.collectionspace.services.common.vocabulary.AuthorityResource; import org.collectionspace.services.taxonomy.nuxeo.TaxonBotGardenConstants; @@ -20,10 +21,10 @@ import org.slf4j.LoggerFactory; /** * A batch job that sets the access code on taxonomy records. The single CSID context is supported. - * + * * If the document is a taxon record, the access codes of the taxon record and all of its descendant * (narrower context) records are updated. - * + * * If the document is a collectionobject, the access codes of all taxon records referenced by the * collectionobject's taxonomic identification are updated, and propagated up the taxon * hierarchy to the ancestors (broader contexts) of each taxon record. @@ -40,21 +41,21 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { public UpdateAccessCodeBatchJob() { this.setSupportedInvocationModes(Arrays.asList(INVOCATION_MODE_SINGLE)); } - + @Override public void run() { setCompletionStatus(STATUS_MIN_PROGRESS); - + try { if (this.requestIsForInvocationModeSingle()) { String csid = getInvocationContext().getSingleCSID(); - + if (StringUtils.isEmpty(csid)) { throw new Exception("Missing context csid"); } - + String docType = getInvocationContext().getDocType(); - + if (docType.equals(TaxonConstants.NUXEO_DOCTYPE)) { setResults(updateAccessCode(csid, true)); //setResults(updateParentAccessCode(csid, true)); @@ -64,31 +65,31 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { } else { throw new Exception("Unsupported document type: " + docType); - } + } } else { throw new Exception("Unsupported invocation mode: " + this.getInvocationContext().getMode()); } - + setCompletionStatus(STATUS_COMPLETE); } catch(Exception e) { setCompletionStatus(STATUS_ERROR); setErrorInfo(new InvocationError(INT_ERROR_STATUS, e.getMessage())); - } + } } - - + + /** * Updates the access code of the specified taxon record. - * + * * @param taxonRefNameOrCsid The refname or csid of the taxon record. * @param deep If true, update the access codes of all descendant (narrower context) * taxon records. On a deep update, the access codes of all descendant * records are updated first, before calculating the access code of the parent. * This ensures that the access codes of children are up-to-date, and can be * used to calculate an up-to-date value for the parent. - * + * * If false, only the specified taxon record is updated. The calculation * of the access code uses the access codes of child taxon records, so * an accurate result depends on the accuracy of the children's access codes. @@ -96,31 +97,31 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { * @throws URISyntaxException * @throws DocumentException */ - public InvocationResults updateAccessCode(String taxonRefNameOrCsid, boolean deep) throws URISyntaxException, DocumentException { + public InvocationResults updateAccessCode(String taxonRefNameOrCsid, boolean deep) throws URISyntaxException, DocumentException, Exception { UpdateAccessCodeResults updateResults = updateAccessCode(taxonRefNameOrCsid, deep, false); - + InvocationResults results = new InvocationResults(); results.setNumAffected(updateResults.getNumAffected()); results.setUserNote(updateResults.isChanged() ? "access code changed to " + updateResults.getAccessCode() : "access code not changed"); - + return results; } - + /** * Updates the access code of the parent (broader context) of the specified taxon record. - * + * * @param taxonCsid The csid of the taxon record. * @param propagate If true, propagate the access code up the taxon hierarchy to * all ancestors of the taxon record. The propagation stops when * the new value of the access code is the same as the old value, * or when a root node (a node with no broader context) is reached. - * + * * If false, update only the access code of the parent. * @return The results of the invocation. * @throws URISyntaxException * @throws DocumentException */ - public InvocationResults updateParentAccessCode(String taxonCsid, boolean propagate) throws URISyntaxException, DocumentException { + public InvocationResults updateParentAccessCode(String taxonCsid, boolean propagate) throws URISyntaxException, DocumentException, Exception { PoxPayloadOut taxonPayload = findTaxonByCsid(taxonCsid); String taxonRefName = getFieldValue(taxonPayload, TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME); String accessCode = getFieldValue(taxonPayload, TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); @@ -128,75 +129,82 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { logger.debug("updating parent access code: taxonRefName=" + taxonRefName + " propagate=" + propagate + " accessCode=" + accessCode); UpdateAccessCodeResults updateResults = updateParentAccessCode(taxonCsid, accessCode, propagate); - + InvocationResults results = new InvocationResults(); results.setNumAffected(updateResults.getNumAffected()); results.setUserNote(results.getNumAffected() + " access codes changed"); - + return results; } - + /** * Updates the access codes of all taxon records that are referenced in the taxonomic identification * field of the specified collectionobject. - * + * * @param collectionObjectCsid The csid of the collectionobject. * @param propagate If true, propagate the access code up the taxon hierarchy to * the ancestors of each referenced taxon record. The propagation stops when * the new value of the access code is the same as the old value, * or when a root node (a node with no broader context) is reached. - * + * * If false, update only the access codes of the taxon records * that are directly referenced. * @return The results of the invocation. * @throws URISyntaxException * @throws DocumentException */ - public InvocationResults updateReferencedAccessCodes(String collectionObjectCsid, boolean propagate) throws URISyntaxException, DocumentException { + public InvocationResults updateReferencedAccessCodes(String collectionObjectCsid, boolean propagate) throws URISyntaxException, DocumentException, Exception { PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid); - - String deadFlag = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, + + String deadFlag = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); boolean isAlive = (deadFlag == null) || (!deadFlag.equalsIgnoreCase("true")); logger.debug("updating referenced access codes: collectionObjectCsid=" + collectionObjectCsid + " propagate=" + propagate + " isAlive=" + isAlive); - List taxonRefNames = getFieldValues(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, + List taxonRefNames = getFieldValues(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, CollectionObjectBotGardenConstants.TAXON_FIELD_NAME); long numAffected = 0; - + for (String taxonRefName : taxonRefNames) { PoxPayloadOut taxonPayload = findTaxonByRefName(taxonRefName); - UpdateAccessCodeResults updateResults = updateAccessCode(taxonPayload, false, isAlive); - - if (updateResults.isChanged()) { - numAffected += updateResults.getNumAffected(); - - if (propagate) { - UpdateAccessCodeResults parentUpdateResults = updateParentAccessCode(getCsid(taxonPayload), updateResults.getAccessCode(), true); - - numAffected += parentUpdateResults.getNumAffected(); + if (taxonPayload != null) { + UpdateAccessCodeResults updateResults = updateAccessCode(taxonPayload, false, isAlive); + if (updateResults.isChanged()) { + numAffected += updateResults.getNumAffected(); + + if (propagate) { + UpdateAccessCodeResults parentUpdateResults = updateParentAccessCode(getCsid(taxonPayload), updateResults.getAccessCode(), true); + + numAffected += parentUpdateResults.getNumAffected(); + } + } + } else { + if (Tools.isBlank(taxonRefName) == false) { + String msg = String.format("%s found that cataloging/object record CSID=%s references taxon '%s' which could not be found.", + getClass().getName(), collectionObjectCsid, taxonRefName); + logger.warn(msg); } } } - + InvocationResults results = new InvocationResults(); results.setNumAffected(numAffected); results.setUserNote(numAffected + " access codes changed"); - + return results; } - + /** * Updates the access code of the specified taxon record. The access code is determined by * examining all collectionobjects that have a taxonomic identification that matches the - * refname of the taxon record, as well as the access codes of child (narrower context) + * refname of the taxon record, as well as the access codes of child (narrower context) * taxon records. If all referencing collectionobjects are dead (as determined * by the dead flag), and all child taxon records are dead (as determined by their access * codes), then the access code is set to Dead. If any matching collectionobjects * are not dead, or any child taxons are not dead, and the access code is currently Dead, * the access code is set to Unrestricted. Otherwise, the access code is not changed. - * + * * @param taxonPayload The services payload of the taxon record. * @param deep If true, update the access code of all descendant taxon records. * On a deep update, the access codes of all descendant @@ -216,59 +224,59 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { * to Unrestricted without examining any other records. * @return The results of the update. * @throws DocumentException - * @throws URISyntaxException + * @throws URISyntaxException */ - public UpdateAccessCodeResults updateAccessCode(PoxPayloadOut taxonPayload, boolean deep, boolean knownAlive) throws URISyntaxException, DocumentException { + public UpdateAccessCodeResults updateAccessCode(PoxPayloadOut taxonPayload, boolean deep, boolean knownAlive) throws URISyntaxException, DocumentException, Exception { UpdateAccessCodeResults results = new UpdateAccessCodeResults(); boolean foundAlive = knownAlive; - + String taxonCsid = getCsid(taxonPayload); String taxonRefName = getFieldValue(taxonPayload, TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME); String accessCode = getFieldValue(taxonPayload, TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); logger.debug("updating access code: taxonRefName=" + taxonRefName + " deep=" + deep + " knownAlive=" + knownAlive); - + if (accessCode == null) { accessCode = ""; } - + List childTaxonCsids = findNarrower(taxonCsid); - + if (deep) { long numChildrenChanged = 0; - + // Update the access code on all the children, and track whether any are alive. - + for (String childTaxonCsid : childTaxonCsids) { UpdateAccessCodeResults childResults = updateAccessCode(childTaxonCsid, true, false); - + if (!childResults.isSoftDeleted()) { String childAccessCode = childResults.getAccessCode(); boolean isChildAlive = !childAccessCode.equals(TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE); - + if (isChildAlive) { foundAlive = true; } - + if (childResults.isChanged()) { numChildrenChanged++; } } } - + results.setNumAffected(numChildrenChanged); } else { if (!foundAlive) { // Check if any of the children are alive. - + for (String childTaxonCsid : childTaxonCsids) { PoxPayloadOut childTaxonPayload = findTaxonByCsid(childTaxonCsid); - - String childAccessCode = getFieldValue(childTaxonPayload, TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, + + String childAccessCode = getFieldValue(childTaxonPayload, TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); boolean isChildAlive = !childAccessCode.equals(TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE); - + if (isChildAlive) { foundAlive = true; break; @@ -276,43 +284,43 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { } } } - + if (!foundAlive) { // Check if any examples of this taxon are alive. - + RefName.AuthorityItem item = RefName.AuthorityItem.parse(taxonRefName); String vocabularyShortId = item.getParentShortIdentifier(); - - List collectionObjectCsids = findReferencingCollectionObjects(TaxonomyAuthorityClient.SERVICE_NAME, vocabularyShortId, taxonCsid, + + List collectionObjectCsids = findReferencingCollectionObjects(TaxonomyAuthorityClient.SERVICE_NAME, vocabularyShortId, taxonCsid, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME + ":" + TAXON_FIELD_NAME_WITHOUT_PATH); - + for (String collectionObjectCsid : collectionObjectCsids) { PoxPayloadOut collectionObjectPayload = findCollectionObjectByCsid(collectionObjectCsid); - - String deadFlag = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, + + String deadFlag = getFieldValue(collectionObjectPayload, CollectionObjectBotGardenConstants.DEAD_FLAG_SCHEMA_NAME, CollectionObjectBotGardenConstants.DEAD_FLAG_FIELD_NAME); boolean isDead = (deadFlag != null) && (deadFlag.equalsIgnoreCase("true")); - + if (!isDead) { foundAlive = true; break; } } } - + String newAccessCode; // The access code only needs to be changed if: // // 1. There is a living example of the taxon, but the access code is dead. // 2. There are no living examples, but the access code is not dead. - // - // Otherwise, the access code should stay the same. In particular, if there is a + // + // Otherwise, the access code should stay the same. In particular, if there is a // living example, and the access code is not dead, the current value of unrestricted // or restricted should be retained. if (foundAlive && (StringUtils.isEmpty(accessCode) || accessCode.equals(TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE))) { - newAccessCode = TaxonBotGardenConstants.ACCESS_CODE_UNRESTRICTED_VALUE; + newAccessCode = TaxonBotGardenConstants.ACCESS_CODE_UNRESTRICTED_VALUE; } else if (!foundAlive) { newAccessCode = TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE; @@ -320,24 +328,24 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { else { newAccessCode = accessCode; } - + if (!newAccessCode.equals(accessCode)) { String inAuthority = getFieldValue(taxonPayload, TaxonConstants.IN_AUTHORITY_SCHEMA_NAME, TaxonConstants.IN_AUTHORITY_FIELD_NAME); setAccessCode(inAuthority, taxonCsid, newAccessCode); - + results.setChanged(true); results.setNumAffected(results.getNumAffected() + 1); } results.setAccessCode(newAccessCode); - + return results; } - + /** * Updates the access code of the taxon record with the specified refname or csid. - * + * * @param taxonRefNameOrCsid * @param deep * @param knownAlive @@ -345,55 +353,79 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { * @throws URISyntaxException * @throws DocumentException */ - public UpdateAccessCodeResults updateAccessCode(String taxonRefNameOrCsid, boolean deep, boolean knownAlive) throws URISyntaxException, DocumentException { + public UpdateAccessCodeResults updateAccessCode(String taxonRefNameOrCsid, boolean deep, boolean knownAlive) throws URISyntaxException, DocumentException, Exception { PoxPayloadOut taxonPayload; - - if (RefName.AuthorityItem.parse(taxonRefNameOrCsid) == null) { + + if (RefName.AuthorityItem.parse(taxonRefNameOrCsid) == null) { taxonPayload = findTaxonByCsid(taxonRefNameOrCsid); } else { taxonPayload = findTaxonByRefName(taxonRefNameOrCsid); } - + return updateAccessCode(taxonPayload, deep, knownAlive); } - + + /** + * Updates the access code of the taxon record with the specified refname or csid, when a new + * child taxon is known to have been added. + * + * @param taxonRefNameOrCsid + * @param deep + * @param newChildCsid The csid of the newly added child. + * @return + * @throws URISyntaxException + * @throws DocumentException + */ + public UpdateAccessCodeResults updateAccessCode(String taxonRefNameOrCsid, boolean deep, String newChildTaxonCsid) throws URISyntaxException, DocumentException, Exception { + PoxPayloadOut newChildTaxonPayload = findTaxonByCsid(newChildTaxonCsid); + String newChildTaxonAccessCode = getFieldValue(newChildTaxonPayload, TaxonBotGardenConstants.ACCESS_CODE_SCHEMA_NAME, TaxonBotGardenConstants.ACCESS_CODE_FIELD_NAME); + + if (newChildTaxonAccessCode == null) { + newChildTaxonAccessCode = ""; + } + + boolean knownAlive = !newChildTaxonAccessCode.equals(TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE); + + return updateAccessCode(taxonRefNameOrCsid, deep, knownAlive); + } + /** * Updates the access code of the parent (broader context) of the specified taxon record, * whose access code is assumed to be a specified value. - * + * * @param taxonCsid The csid of the taxon record. * @param accessCode The access code of the taxon record. * @param propagate If true, propagate the access code up the taxon hierarchy to * all ancestors of the taxon record. The propagation stops when * the new value of the access code is the same as the old value, * or when a root node (a node with no broader context) is reached. - * + * * If false, update only the access code of the parent. * @return The results of the update. * @throws URISyntaxException * @throws DocumentException */ - public UpdateAccessCodeResults updateParentAccessCode(String taxonCsid, String accessCode, boolean propagate) throws URISyntaxException, DocumentException { + public UpdateAccessCodeResults updateParentAccessCode(String taxonCsid, String accessCode, boolean propagate) throws URISyntaxException, DocumentException, Exception { UpdateAccessCodeResults results = new UpdateAccessCodeResults(); String parentTaxonCsid = findBroader(taxonCsid); long numAffected = 0; - + logger.debug("updating parent access code: taxonCsid=" + taxonCsid + " accessCode=" + accessCode + " propagate=" + propagate); if (parentTaxonCsid != null) { boolean isAlive = (accessCode == null) || !accessCode.equals(TaxonBotGardenConstants.ACCESS_CODE_DEAD_VALUE); - UpdateAccessCodeResults parentUpdateResults = updateAccessCode(parentTaxonCsid, false, isAlive); - + UpdateAccessCodeResults parentUpdateResults = updateAccessCode(parentTaxonCsid, false, isAlive); + if (parentUpdateResults.isChanged()) { // Except for numAffected, the result fields are probably not all that useful in this situation. // Set the changed flag to whether the immediate parent was changed, and the access code to // the immediate parent's. - + results.setAccessCode(parentUpdateResults.getAccessCode()); results.setChanged(true); - + numAffected += parentUpdateResults.getNumAffected(); if (propagate) { @@ -402,22 +434,22 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { } } } - + results.setNumAffected(numAffected); - + return results; } - + /** * Sets the access code of the specified taxon record to the specified value. - * + * * @param authorityCsid The csid of the authority containing the taxon record. * @param taxonCsid The csid of the taxon record. * @param accessCode The value of the access code. - * @throws URISyntaxException + * @throws URISyntaxException */ private void setAccessCode(String authorityCsid, String taxonCsid, String accessCode) throws URISyntaxException { - String updatePayload = + String updatePayload = "" + "" + "" + @@ -426,10 +458,10 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { ""; AuthorityResource resource = (AuthorityResource) getResourceMap().get(TaxonomyAuthorityClient.SERVICE_NAME); - resource.updateAuthorityItem(getResourceMap(), createUriInfo(), authorityCsid, taxonCsid, updatePayload); + resource.updateAuthorityItem(getServiceContext(), getResourceMap(), createUriInfo(), authorityCsid, taxonCsid, updatePayload); } - - private class UpdateAccessCodeResults { + + public class UpdateAccessCodeResults { private boolean isSoftDeleted = false; private boolean isChanged = false; private String accessCode = null; @@ -453,11 +485,11 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob { public void setChanged(boolean isChanged) { this.isChanged = isChanged; } - + public String getAccessCode() { return accessCode; } - + public void setAccessCode(String accessCode) { this.accessCode = accessCode; } diff --git a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateRareFlagBatchJob.java b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateRareFlagBatchJob.java index ef437856c..85c4ca5eb 100644 --- a/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateRareFlagBatchJob.java +++ b/services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateRareFlagBatchJob.java @@ -110,7 +110,7 @@ public class UpdateRareFlagBatchJob extends AbstractBatchJob { * @throws URISyntaxException * @throws DocumentException */ - public InvocationResults updateReferencingRareFlags(String taxonCsid) throws URISyntaxException, DocumentException { + public InvocationResults updateReferencingRareFlags(String taxonCsid, String vocabularyCsid) throws URISyntaxException, DocumentException { PoxPayloadOut taxonPayload = findTaxonByCsid(taxonCsid); String taxonRefName = getFieldValue(taxonPayload, TaxonConstants.REFNAME_SCHEMA_NAME, TaxonConstants.REFNAME_FIELD_NAME); @@ -144,6 +144,10 @@ public class UpdateRareFlagBatchJob extends AbstractBatchJob { return results; } + public InvocationResults updateReferencingRareFlags(String taxonCsid) throws URISyntaxException, DocumentException, Exception { + return updateReferencingRareFlags(taxonCsid, null); + } + /** * Updates the rare flag of the specified collectionobject. * diff --git a/services/common/pom.xml b/services/common/pom.xml index 795355272..080cc0a69 100644 --- a/services/common/pom.xml +++ b/services/common/pom.xml @@ -19,11 +19,6 @@ org.collectionspace.services.config ${project.version} - - org.collectionspace.services - org.collectionspace.services.3rdparty.nuxeo.thumbnail - ${project.version} - org.collectionspace.services org.collectionspace.services.common-api @@ -165,7 +160,6 @@ org.apache.tomcat tomcat-servlet-api - ${tomcat.version} provided diff --git a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java index b922307c1..19d763aee 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java @@ -30,10 +30,8 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStream; -import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -55,7 +53,6 @@ import org.nuxeo.ecm.platform.filemanager.service.FileManagerService; import org.nuxeo.ecm.platform.filemanager.service.extension.FileImporter; import org.nuxeo.ecm.platform.filemanager.utils.FileManagerUtils; import org.nuxeo.ecm.platform.types.TypeManager; -import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.ecm.core.api.blobholder.BlobHolder; @@ -67,12 +64,13 @@ import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.PropertyException; -import org.nuxeo.ecm.core.api.VersioningOption; import org.nuxeo.ecm.core.blob.BlobManager; import org.nuxeo.ecm.core.blob.BlobProvider; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.io.IOUtils; + import org.collectionspace.services.client.PoxPayloadIn; import org.collectionspace.services.client.PoxPayloadOut; import org.collectionspace.services.common.FileUtilities; @@ -95,8 +93,8 @@ import org.collectionspace.services.jaxb.BlobJAXBSchema; import org.collectionspace.services.nuxeo.client.java.CommonList; import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; import org.collectionspace.services.nuxeo.client.java.NuxeoRepositoryClientImpl; -import org.collectionspace.services.nuxeo.extension.thumbnail.ThumbnailConstants; import org.collectionspace.services.nuxeo.util.NuxeoUtils; +import org.collectionspace.services.nuxeo.util.ThumbnailConstants; import org.collectionspace.services.config.service.ListResultField; /** @@ -515,7 +513,7 @@ public class NuxeoBlobUtils { result.setMeasuredPartGroupList(measuredPartGroupList); } } - + // Check to see if a thumbnail preview was created by Nuxeo if (documentModel.hasFacet(ThumbnailConstants.THUMBNAIL_FACET)) { String errorMsg = null; @@ -531,7 +529,7 @@ public class NuxeoBlobUtils { logger.debug(errorMsg, e); } } - + if (errorMsg == null) { logger.info("A thumbnail preview was created for this document blob: " + thumbnailName); } else { diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventListenerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventListenerImpl.java index 32501945e..91a28caf5 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventListenerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventListenerImpl.java @@ -6,20 +6,34 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.logging.Log; +import org.collectionspace.services.client.workflow.WorkflowClient; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.config.tenant.EventListenerConfig; import org.collectionspace.services.config.tenant.Param; +import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface; +import org.collectionspace.services.nuxeo.util.NuxeoUtils; import org.nuxeo.common.collections.ScopeType; import org.nuxeo.common.collections.ScopedMap; import org.nuxeo.ecm.core.api.DocumentModel; +import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.event.Event; +import org.nuxeo.ecm.core.event.EventContext; +import org.nuxeo.ecm.core.event.impl.DocumentEventContext; public abstract class AbstractCSEventListenerImpl implements CSEventListener { private static Map> mapOfrepositoryNames = new HashMap>(); // private static Map>> eventListenerParamsMap = new HashMap>>(); // >> private static Map nameMap = new HashMap(); - - public static final String DOCMODEL_CONTEXT_PROPERTY_PREFIX = ScopeType.DEFAULT.getScopePrefix(); + + // SQL clauses + private final static String NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT = + "AND ecm:isCheckedInVersion = 0" + + " AND ecm:isProxy = 0 "; + protected final static String ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT = + "AND (ecm:currentLifeCycleState <> 'deleted') " + + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT; + static final String DOCMODEL_CONTEXT_PROPERTY_PREFIX = ScopeType.DEFAULT.getScopePrefix(); public AbstractCSEventListenerImpl() { // Intentionally left blank @@ -31,31 +45,64 @@ public abstract class AbstractCSEventListenerImpl implements CSEventListener { @Override public boolean isRegistered(Event event) { boolean result = false; - + if (event != null && event.getContext() != null) { result = getRepositoryNameList().contains(event.getContext().getRepositoryName()); } - + return result; } + + /* + * This method is meant to be the bottleneck for handling a Nuxeo document event. + */ + final public void handleEvent(Event event) { + getLogger().trace(String.format("Eventlistener '%s' presenented with '%s' event.", + getClass().getName(), event.getName())); + boolean isRegistered = isRegistered(event); + try { + if (isRegistered && shouldHandleEvent(event)) { + handleCSEvent(event); + getLogger().debug(String.format("Eventlistener '%s' accepted '%s' event.", + getClass().getName(), event.getName())); + } else { + if (isRegistered) { + getLogger().debug(String.format("Eventlistener '%s' declined to handle '%s' event.", + getClass().getName(), event.getName())); + } else { + getLogger().trace(String.format("Eventlistener '%s' was not registered in the service bindings for the tenant with repo '%s'.", + getClass().getName(), event.getContext().getRepositoryName())); + } + } + } catch (Exception e) { + String errMsg = String.format("Eventlistener '%s' presenented with '%s' event but encountered an error: %s", + getClass().getName(), event.getName(), e.getMessage()); + if (getLogger().isTraceEnabled()) { + getLogger().error(errMsg, e); + } else { + getLogger().error(errMsg); + } + } + } + /** * An event listener can be registered by multiple tenants, so we keep track of that here. - * + * * @return - the list of tenants/repositories that an event listener is registered with. */ protected List getRepositoryNameList() { String key = this.getClass().getName(); List result = mapOfrepositoryNames.get(key); - + if (result == null) synchronized(this) { result = new ArrayList(); mapOfrepositoryNames.put(key, result); } - + return result; } - + /** * The list of parameters (specified in a tenant's bindings) for event listeners * @return @@ -65,20 +112,20 @@ public abstract class AbstractCSEventListenerImpl implements CSEventListener { } /** - * Returns 'true' if this collection changed as a result of the call. + * Returns 'true' if this collection changed as a result of the call. */ @Override public boolean register(String respositoryName, EventListenerConfig eventListenerConfig) { boolean result = false; - + // Using the repositoryName as a qualifier, register this event listener's name as specified in the tenant bindings. setName(respositoryName, eventListenerConfig.getId()); - + // Register this event listener with the given repository name if (getRepositoryNameList().add(respositoryName)) { result = true; } - + if (eventListenerConfig.getParamList() != null) { // Set this event listeners parameters, if any. Params are qualified with the repositoryName since multiple tenants might be registering the same event listener but with different params. List paramList = eventListenerConfig.getParamList().getParam(); // values from the tenant bindings that we need to copy into the event listener @@ -111,10 +158,10 @@ public abstract class AbstractCSEventListenerImpl implements CSEventListener { } } } - + return result; } - + protected void setName(String repositoryName, String eventListenerName) { nameMap.put(repositoryName, eventListenerName); } @@ -130,11 +177,18 @@ public abstract class AbstractCSEventListenerImpl implements CSEventListener { } return result; } - + @Override public String getName(String repositoryName) { return nameMap.get(repositoryName); } + + // + // Return a property in the document model's transient context. + // + protected Serializable getContextPropertyValue(DocumentEventContext docEventContext, String key) { + return docEventContext.getProperties().get(key); + } // // Set a property in the document model's transient context. @@ -142,16 +196,138 @@ public abstract class AbstractCSEventListenerImpl implements CSEventListener { @Override public void setDocModelContextProperty(DocumentModel collectionObjectDocModel, String key, Serializable value) { ScopedMap contextData = collectionObjectDocModel.getContextData(); - contextData.putIfAbsent(DOCMODEL_CONTEXT_PROPERTY_PREFIX + key, value); + contextData.putIfAbsent(DOCMODEL_CONTEXT_PROPERTY_PREFIX + key, value); } - + // // Clear a property from the docModel's context // @Override public void clearDocModelContextProperty(DocumentModel docModel, String key) { ScopedMap contextData = docModel.getContextData(); - contextData.remove(DOCMODEL_CONTEXT_PROPERTY_PREFIX + key); + contextData.remove(DOCMODEL_CONTEXT_PROPERTY_PREFIX + key); } + // + // Derived classes need to implement. + // + abstract protected Log getLogger(); + + //FIXME: Does not include all the sync-related "delete" workflow states + /** + * Identifies whether a supplied event concerns a document that has + * been transitioned to the 'deleted' workflow state. + * + * @param eventContext an event context + * + * @return true if this event concerns a document that has + * been transitioned to the 'deleted' workflow state. + */ + protected boolean isDocumentSoftDeletedEvent(EventContext eventContext) { + boolean isSoftDeletedEvent = false; + + if (eventContext instanceof DocumentEventContext) { + if (eventContext.getProperties().containsKey(WorkflowClient.WORKFLOWTRANSITION_TO) + && + (eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_DELETED) + || + eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED))) { + isSoftDeletedEvent = true; + } + } + + return isSoftDeletedEvent; + } + + /** + * Identifies whether a document matches a supplied document type. + * + * @param docModel a document model. + * @param docType a document type string. + * @return true if the document matches the supplied document type; false if + * it does not. + */ + protected static boolean documentMatchesType(DocumentModel docModel, String docType) { + if (docModel == null || Tools.isBlank(docType)) { + return false; + } + if (docModel.getType().startsWith(docType)) { + return true; + } else { + return false; + } + } + + /** + * Identifies whether a document is an active document; currently, whether + * it is not in a 'deleted' workflow state. + * + * @param docModel + * @return true if the document is an active document; false if it is not. + */ + protected static boolean isActiveDocument(DocumentModel docModel) { + return isActiveDocument(docModel, false, null); + } + + protected static boolean isActiveDocument(DocumentModel docModel, boolean isAboutToBeRemovedEvent, String aboutToBeRemovedCsid) { + boolean isActiveDocument = false; + + if (docModel != null) { + if (!docModel.getCurrentLifeCycleState().contains(WorkflowClient.WORKFLOWSTATE_DELETED)) { + isActiveDocument = true; + } + // + // If doc model is the target of the "aboutToBeRemoved" event, mark it as not active. + // + if (isAboutToBeRemovedEvent && Tools.notBlank(aboutToBeRemovedCsid)) { + if (NuxeoUtils.getCsid(docModel).equalsIgnoreCase(aboutToBeRemovedCsid)) { + isActiveDocument = false; + } + } + } + + return isActiveDocument; + } + + /** + * Returns the current document model for a record identified by a CSID. + * + * Excludes documents which have been versioned (i.e. are a non-current + * version of a document), are a proxy for another document, or are + * un-retrievable via their CSIDs. + * + * @param session a repository session. + * @param csid a CollectionObject identifier (CSID) + * @return a document model for the document identified by the supplied + * CSID. + */ + protected DocumentModel getCurrentDocModelFromCsid(CoreSessionInterface session, String csid) { + DocumentModelList docModelList = null; + + if (Tools.isEmpty(csid)) { + return null; + } + + try { + final String query = "SELECT * FROM " + + NuxeoUtils.BASE_DOCUMENT_TYPE + + " WHERE " + + NuxeoUtils.getByNameWhereClause(csid) + + " " + + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT; + docModelList = session.query(query); + } catch (Exception e) { + getLogger().warn("Exception in query to get active document model for CSID: " + csid, e); + } + + if (docModelList == null || docModelList.isEmpty()) { + getLogger().warn("Could not get active document models for CSID=" + csid); + return null; + } else if (docModelList.size() != 1) { + getLogger().error("Found more than 1 active document with CSID=" + csid); + return null; + } + + return docModelList.get(0); + } } diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventPostCommitListenerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventPostCommitListenerImpl.java new file mode 100644 index 000000000..f0171530e --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventPostCommitListenerImpl.java @@ -0,0 +1,30 @@ +package org.collectionspace.services.nuxeo.listener; + +import java.util.Iterator; + +import org.nuxeo.ecm.core.event.Event; +import org.nuxeo.ecm.core.event.EventBundle; +import org.nuxeo.ecm.core.event.PostCommitEventListener; + +public abstract class AbstractCSEventPostCommitListenerImpl extends AbstractCSEventListenerImpl implements PostCommitEventListener { + + /** + * Subclasses need to override and return 'true' if they want to handle the event bundle + * @param eventBundle + * @return + */ + public abstract boolean shouldHandleEventBundle(EventBundle eventBundle); + + /* + * Process all the events in the bundle + */ + @Override + public final void handleEvent(EventBundle eventBundle) { + if (shouldHandleEventBundle(eventBundle)) { + Iterator iter = eventBundle.iterator(); + while (iter.hasNext()) { + this.handleEvent(iter.next()); + } + } + } +} diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventSyncListenerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventSyncListenerImpl.java new file mode 100644 index 000000000..32e1d1d8d --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventSyncListenerImpl.java @@ -0,0 +1,7 @@ +package org.collectionspace.services.nuxeo.listener; + +import org.nuxeo.ecm.core.event.EventListener; + +public abstract class AbstractCSEventSyncListenerImpl extends AbstractCSEventListenerImpl implements EventListener { + // Intentionally blank. Needed so we can "implement" Nuxeo's synchronous EvenListener class +} diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/CSEventListener.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/CSEventListener.java index 22b28680d..c3da8464d 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/CSEventListener.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/listener/CSEventListener.java @@ -6,9 +6,8 @@ import java.util.Map; import org.collectionspace.services.config.tenant.EventListenerConfig; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.event.Event; -import org.nuxeo.ecm.core.event.EventListener; -public interface CSEventListener extends EventListener { +public interface CSEventListener { /** * Register ourself as an event listener for the named repository -the repo name corresponds to a specific tenant. * @param respositoryName - The name of the Nuxeo repository which links us to a CollectionSpace tenant. @@ -17,6 +16,18 @@ public interface CSEventListener extends EventListener { */ boolean register(String respositoryName, EventListenerConfig eventListenerConfig); + /** + * If the listener wants to handle the event, it should return 'true'. + * @param event + * @return + */ + boolean shouldHandleEvent(Event event); + + /** + * Processing of the event. + */ + void handleCSEvent(Event event); + /** * Determines if we are a registered event listener for the given event. * @param event @@ -51,5 +62,5 @@ public interface CSEventListener extends EventListener { * Returns the name of the event listener as defined during registration -see register() method. * @return */ - String getName(String repositoryName); + String getName(String repositoryName); } diff --git a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConstants.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/util/ThumbnailConstants.java similarity index 89% rename from 3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConstants.java rename to services/common/src/main/java/org/collectionspace/services/nuxeo/util/ThumbnailConstants.java index 2a75074c1..1690ba335 100644 --- a/3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConstants.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/util/ThumbnailConstants.java @@ -1,4 +1,4 @@ -package org.collectionspace.services.nuxeo.extension.thumbnail; +package org.collectionspace.services.nuxeo.util; public class ThumbnailConstants { public static final String THUMBNAIL_SIZE_PARAMETER_NAME = "size"; -- 2.47.3