]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-477: Adding support for both post-commit event listeners.
authorRichard Millet <remillet@gmail.com>
Fri, 6 Dec 2019 23:46:10 +0000 (15:46 -0800)
committerRichard Millet <remillet@gmail.com>
Fri, 6 Dec 2019 23:46:10 +0000 (15:46 -0800)
30 files changed:
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/pom.xml
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/CreateVersionListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/DeleteDeadLocationListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateAccessCodeListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateDeadFlagListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateLocationListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateRareFlagListener.java
3rdparty/nuxeo/nuxeo-platform-listener/botgarden/src/main/java/org/collectionspace/services/listener/botgarden/UpdateStyledNameListener.java
3rdparty/nuxeo/nuxeo-platform-listener/naturalhistory/src/main/java/org/collectionspace/services/listener/naturalhistory/UpdateFormattedDisplayNameListener.java
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/Reindex.java
3rdparty/nuxeo/nuxeo-platform-listener/reindex/src/main/java/org/collectionspace/services/listener/ReindexSupport.java
3rdparty/nuxeo/nuxeo-platform-listener/updateimagederivatives/src/main/java/org/collectionspace/services/listener/UpdateImageDerivatives.java
3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java
3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationAndCrateOnMove.java
3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/UpdateObjectLocationOnMove.java
3rdparty/nuxeo/nuxeo-platform-listener/updaterelationsondelete/src/main/java/org/collectionspace/services/listener/UpdateRelationsOnDelete.java
3rdparty/nuxeo/nuxeo-platform-thumbnail/pom.xml
3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/AddThumbnailUnrestricted.java
3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/Thumbnail.java
3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConverter.java
3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/UpdateThumbListener.java
services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateAccessCodeBatchJob.java
services/batch/service/src/main/java/org/collectionspace/services/batch/nuxeo/UpdateRareFlagBatchJob.java
services/common/pom.xml
services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java
services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventListenerImpl.java
services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventPostCommitListenerImpl.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/nuxeo/listener/AbstractCSEventSyncListenerImpl.java [new file with mode: 0644]
services/common/src/main/java/org/collectionspace/services/nuxeo/listener/CSEventListener.java
services/common/src/main/java/org/collectionspace/services/nuxeo/util/ThumbnailConstants.java [moved from 3rdparty/nuxeo/nuxeo-platform-thumbnail/src/main/java/org/collectionspace/services/nuxeo/extension/thumbnail/ThumbnailConstants.java with 89% similarity]

index 755a5a4d6d4845bd1e51cd8aadada2c102bffd1d..db79e6b9bfbab822b12dea382efefb3091ecf963 100644 (file)
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>org.collectionspace.services.3rdparty.nuxeo.listener</artifactId>
         <groupId>org.collectionspace.services</groupId>
-        <version>${revision}</version>
+        <version>${revision}</version>        
     </parent>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <name>org.collectionspace.services.listener.botgarden</name>
     <url>http://maven.apache.org</url>
 
-
+        
        <dependencies>
         <dependency>
             <groupId>org.nuxeo.ecm.core</groupId>
             <artifactId>nuxeo-core-storage-sql</artifactId>
+            <version>${nuxeo.core.version}</version>
         </dependency>
            <dependency>
              <groupId>org.nuxeo.ecm.platform</groupId>
              <artifactId>nuxeo-platform-filemanager-api</artifactId>
-                 <version>${nuxeo.platform.version}</version>
+                 <version>${nuxeo.platform.version}</version>        
            </dependency>
            <dependency>
             <groupId>org.collectionspace.services</groupId>
@@ -43,7 +44,7 @@
         </dependency>
        </dependencies>
 
-
+       
     <build>
         <resources>
             <resource>
@@ -67,5 +68,5 @@
             </plugin>
         </plugins>
     </build>
-
+       
 </project>
index 6424df4e68beb9b1dca703412e6cb0cc5d6fabe6..e275d928523a1f0015cfe99fd83444c2aa64528d 100644 (file)
@@ -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
index 4590b3f0687e162cbee45b6c98240d302bed2ebf..41146b757e451f5cc107f0cd464f5f53c0694695 100644 (file)
@@ -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
index a90f6ed59ee71b135f5992b86a099ea96806f9c6..1a63c5f6ce7fa49822503dd91aa522cc83225131 100644 (file)
@@ -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<String> previousTaxonNames = getTaxonNames(previousDoc);
-                                       context.setProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME, previousTaxonNames.toArray(new String[previousTaxonNames.size()]));
-                               }
-                               else {
-                                       boolean deadFlagChanged = false;
-                                       Set<String> deletedTaxonNames = null;
-                                       Set<String> 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<String> previousTaxonNames = getTaxonNames(previousDoc);
+                               context.setProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME, previousTaxonNames.toArray(new String[previousTaxonNames.size()]));
+                       }
+                       else {
+                               boolean deadFlagChanged = false;
+                               Set<String> deletedTaxonNames = null;
+                               Set<String> 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<String> previousTaxonNames = Arrays.asList((String[]) context.getProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME));
-                                               List<String> 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<String> previousTaxonNames = Arrays.asList((String[]) context.getProperty(PREVIOUS_TAXON_NAMES_PROPERTY_NAME));
+                                       List<String> 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<PoxPayloadIn, PoxPayloadOut> 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;
+       }
 }
index b25bd7a33b31202d6e953073396a8090b08ee806..3569452ce1c5396c9ffdc409b8c02cc9b7b97f62 100644 (file)
 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<PoxPayloadIn, PoxPayloadOut> 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
index b537c6a901418a7e81847306b15b8b46deab6e05..0d3496a77d6d97cbb191ace55c31446e7564b5ed 100644 (file)
@@ -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 {
         * </ui>
         */
        @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
index 6a342b80295f8715f62f204124909c5101da72b9..72bb3f756b0225070ae99eabf7e6ae9a56ce9424 100644 (file)
@@ -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<PoxPayloadIn, PoxPayloadOut> 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;
+       }
 }
index c9656ea9f2c25a9787b0b1c4f47fd0ddecd405c6..4400383f4dc671f929370c4b2d5eb3880550e020 100644 (file)
@@ -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<PoxPayloadIn, PoxPayloadOut> 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
index d2ddc19404a85633a004d8adfe58b82669ebd278..3b8b4608c51c6aed7381354fb6a08e8827231927 100644 (file)
@@ -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
index 285ffeac9ed7fc73593b9dcec1507b2dd69c60be..3523b8a1465f997aff01cf21592379372bea593f 100644 (file)
@@ -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<Event> iter = events.iterator();
-
-            while (iter.hasNext()) {
-                Event event = iter.next();
-                DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
-                Boolean isRegistered = (Boolean) eventContext.getProperty(IS_REGISTERED_KEY);
+            List<String> prevPublishTo = (List<String>) eventContext.getProperty(PREV_PUBLISH_TO_KEY);
+            List<String> publishTo = (List<String>) 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<String> prevPublishTo = (List<String>) eventContext.getProperty(PREV_PUBLISH_TO_KEY);
-                            List<String> publishTo = (List<String>) 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)) {
index 313e227d45dd596dd8fbf32a279e64a35bcf0c56..6281328c3d462c8fccc964784e85c674aeaa7f47 100644 (file)
@@ -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<String> publishTo = (List<String>) 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<String> publishTo = (List<String>) 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;
     }
 }
index e04a6361523f7654d11a5738b0f471540d71f5ce..c1531c162118c4dfee32ecd386119eef1aed57d4 100644 (file)
@@ -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
index 1d60b06ca6b9dadefb4a4aea4a70425573254b84..f81ab0705c84cecd2c3dcf026294af839e08d378 100644 (file)
@@ -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=<empty>"));
-                       }
-               } 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<String, String> 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<String> 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<String> 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
index 03e70861939be68261eae57d8dd8ed979cc4af62..cd593de6425bff88d9eddb2a00d14b2fbd23812d 100644 (file)
@@ -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
index 6004819270287ae57d8ce788d8d2f5349756767a..dfdde2be4c13ba87d3207e52ab37aa9c9482f729 100644 (file)
@@ -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
index bc54278a2672e3c2417a328bee07258437eadf28..81bc6b154b759c5bdbfa976b190d401539d81bc8 100644 (file)
@@ -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<String> workflowStatesToFilter = new ArrayList<String>();
-            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<String> workflowStatesToFilter = new ArrayList<String>();
+        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;
     }
 }
index f8b76a51b6af2c31bef912ea987365753a4271a5..d789ae67a69d5b47ac7e71d0c57a08434492ae3b 100644 (file)
         <dependency>
             <groupId>org.nuxeo.ecm.core</groupId>
             <artifactId>nuxeo-core-convert</artifactId>
-            <version>${nuxeo.core.version}</version>
         </dependency>
         <dependency>
           <groupId>org.nuxeo.ecm.platform</groupId>
           <artifactId>nuxeo-platform-imaging-core</artifactId>
-          <version>${nuxeo.platform.version}</version>
           <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.collectionspace.services</groupId>
+            <artifactId>org.collectionspace.services.common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
        </dependencies>
 
     <build>
index bc52169c5a16ce7d0316d8d2a6b4e5da0070b683..d4aaaa01bc7071cc49a5287d4b93e5a76cda76eb 100644 (file)
@@ -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;
index c76f8426d0462eef2fecd53f27623a089facad5d..a4a40bc67f1981b481b5efe7a522c458b3cb590a 100644 (file)
@@ -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;
 
index bfeb4fd4d639ae744fa099e73acf498b12452015..8446ee5c308276f8c9f81f3080e66c488f2f193d 100644 (file)
@@ -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;
index fa9e5f22fad48237e020cb1186105c68d5b9aef1..d74c86d7a2ecd90940d8e7060f569a63373cc53b 100644 (file)
@@ -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;
+    }
 }
index 50acfd79ff16717b096b5566a38ae61625f68c9d..e49339fd489979ce4d46b6abd74efe32f5b52ded 100644 (file)
@@ -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<String> taxonRefNames = getFieldValues(collectionObjectPayload, CollectionObjectBotGardenConstants.TAXON_SCHEMA_NAME, 
+               List<String> 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<String> 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<String> collectionObjectCsids = findReferencingCollectionObjects(TaxonomyAuthorityClient.SERVICE_NAME, vocabularyShortId, taxonCsid, 
+
+                       List<String> 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 =
                                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                                "<document name=\"taxon\">" +
                                        "<ns2:taxon_naturalhistory xmlns:ns2=\"http://collectionspace.org/services/taxonomy/domain/naturalhistory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
@@ -426,10 +458,10 @@ public class UpdateAccessCodeBatchJob extends AbstractBatchJob {
                                "</document>";
 
                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;
                }
index ef437856c59cb54635fba99253d3d27d1136ea1c..85c4ca5eb8a6fea70d09a1d95f426777103a9bd7 100644 (file)
@@ -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.
         * 
index 7953552725453627084710cd364f0df5070f2378..080cc0a6969a847fdf8ccf3a7b70243f463e1645 100644 (file)
                        <artifactId>org.collectionspace.services.config</artifactId>
                        <version>${project.version}</version>
                </dependency>
-               <dependency>
-                       <groupId>org.collectionspace.services</groupId>
-                       <artifactId>org.collectionspace.services.3rdparty.nuxeo.thumbnail</artifactId>
-                       <version>${project.version}</version>
-               </dependency>
                <dependency>
                        <groupId>org.collectionspace.services</groupId>
                        <artifactId>org.collectionspace.services.common-api</artifactId>
                <dependency>
                        <groupId>org.apache.tomcat</groupId>
                        <artifactId>tomcat-servlet-api</artifactId>
-                       <version>${tomcat.version}</version>
                        <scope>provided</scope>
                </dependency>
 
index b922307c1fedffa4f41da7a39ab79e804d274cae..19d763aee40401c7b4c83919c3f18573556adae9 100644 (file)
@@ -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 {
index 32501945ebb38d1bdab54fe70e0509e9bfb5823b..91a28caf57458a5eaabbec3351bfa7128accdc87 100644 (file)
@@ -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<String, List<String>> mapOfrepositoryNames = new HashMap<String, List<String>>(); // <className, repositoryName>
        private static Map<String, Map<String, Map<String, String>>> eventListenerParamsMap = new HashMap<String, Map<String, Map<String, String>>>();  // <repositoryName, Map<EventListenerId, Map<key, value>>>
        private static Map<String, String> nameMap = new HashMap<String, String>();
-
-       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<String> getRepositoryNameList() {
                String key = this.getClass().getName();
                List<String> result = mapOfrepositoryNames.get(key);
-
+               
                if (result == null) synchronized(this) {
                        result = new ArrayList<String>();
                        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<Param> 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 (file)
index 0000000..f017153
--- /dev/null
@@ -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<Event> 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 (file)
index 0000000..32e1d1d
--- /dev/null
@@ -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
+}
index 22b28680d233a90bcb921f0d9ce992984f0f3b73..c3da8464d164f3f57e5918cb2512140170799abb 100644 (file)
@@ -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);  
 }