]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-5984,PAHMA-789: In the UpdateObjectLocationOnMove event handler, when receivin...
authorAron Roberts <aron@socrates.berkeley.edu>
Tue, 30 Apr 2013 20:36:25 +0000 (13:36 -0700)
committerAron Roberts <aron@socrates.berkeley.edu>
Tue, 30 Apr 2013 20:36:25 +0000 (13:36 -0700)
3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java

index a046d53db85ef816abf766a7c428449c40161fda..6ca3d667252f74c663de1ab01854ae5f77988a30 100644 (file)
@@ -45,6 +45,12 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
             + "AND ecm:isProxy = 0 "
             + "AND ecm:isCheckedInVersion = 0";
 
+    public enum EventNotificationDocumentType {
+        // Document type about which we've received a notification
+
+        MOVEMENT, RELATION;
+    }
+
     @Override
     public void handleEvent(Event event) throws ClientException {
 
@@ -70,31 +76,38 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
 
         //
         // (The rest of the code flow below is then identical to that which
-        // is followed when this document event involves a Movement record.)
+        // is followed when this document event involves a Movement record.
         String movementCsid = "";
+        Enum notificationDocumentType;
         if (documentMatchesType(docModel, RELATION_DOCTYPE)) {
             if (logger.isTraceEnabled()) {
                 logger.trace("An event involving a Relation document was received by UpdateObjectLocationOnMove ...");
             }
             // Get a Movement CSID from the Relation record. (If we can't
             // get it, then we don't have a pertinent relation record.)
-            movementCsid = getCsidForDesiredDocType(docModel, MOVEMENT_DOCTYPE, COLLECTIONOBJECT_DOCTYPE);
+            movementCsid = getCsidForDesiredDocTypeFromRelation(docModel, MOVEMENT_DOCTYPE, COLLECTIONOBJECT_DOCTYPE);
             if (Tools.isBlank(movementCsid)) {
                 logger.warn("Could not obtain CSID for Movement record from document event.");
                 logger.warn(NO_FURTHER_PROCESSING_MESSAGE);
                 return;
             }
+            notificationDocumentType = EventNotificationDocumentType.RELATION;
         } else if (documentMatchesType(docModel, MOVEMENT_DOCTYPE)) {
+            // Otherwise, get a Movement CSID directly from the Movement record.
             if (logger.isTraceEnabled()) {
                 logger.trace("An event involving a Movement document was received by UpdateObjectLocationOnMove ...");
             }
-            // Otherwise, get a Movement CSID directly from the Movement record.
+            // FIXME: exclude creation events for Movement records here, if we can
+            // identify that we'l still be properly handling creation events
+            // that include a relations list as part of the creation payload,
+            // perhaps because that may trigger a separate event notification.
             movementCsid = NuxeoUtils.getCsid(docModel);
             if (Tools.isBlank(movementCsid)) {
                 logger.warn("Could not obtain CSID for Movement record from document event.");
                 logger.warn(NO_FURTHER_PROCESSING_MESSAGE);
                 return;
             }
+            notificationDocumentType = EventNotificationDocumentType.MOVEMENT;
         } else {
             if (logger.isTraceEnabled()) {
                 logger.trace("This event did not involve a document relevant to UpdateObjectLocationOnMove ...");
@@ -117,52 +130,24 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
         // scope to handle only transitions into the 'soft deleted' state,
         // we can add additional checks for doing so at this point in the code.
 
+        // For debugging
         if (logger.isTraceEnabled()) {
             logger.trace("Movement CSID=" + movementCsid);
+            logger.trace("Notification document type=" + notificationDocumentType.name());
         }
 
-        // Find CollectionObject records that are related to this Movement record:
-        //
-        // Via an NXQL query, get a list of active relation records where:
-        // * This movement record's CSID is the subject CSID of the relation,
-        //   and its object document type is a CollectionObject doctype;
-        // or
-        // * This movement record's CSID is the object CSID of the relation,
-        //   and its subject document type is a CollectionObject doctype.
         CoreSession coreSession = docEventContext.getCoreSession();
-        // Some values below are hard-coded for readability, rather than
-        // being obtained from constants.
-        String query = String.format(
-                "SELECT * FROM %1$s WHERE " // collectionspace_core:tenantId = 1 "
-                + "("
-                + "  (%2$s:subjectCsid = '%3$s' "
-                + "  AND %2$s:objectDocumentType = '%4$s') "
-                + " OR "
-                + "  (%2$s:objectCsid = '%3$s' "
-                + "  AND %2$s:subjectDocumentType = '%4$s') "
-                + ")"
-                + ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT,
-                RELATION_DOCTYPE, RELATIONS_COMMON_SCHEMA, movementCsid, COLLECTIONOBJECT_DOCTYPE);
-        DocumentModelList relationDocModels = coreSession.query(query);
-        if (relationDocModels == null || relationDocModels.isEmpty()) {
-            // Encountering a Movement record that is not related to any
-            // CollectionObject is potentially a normal occurrence, so no
-            // error messages are logged here when we stop handling this event.
-            return;
-        }
+        Set<String> collectionObjectCsids = new HashSet<>();
 
-        // Iterate through the list of Relation records found and build
-        // a list of CollectionObject CSIDs, by extracting the relevant CSIDs
-        // from those Relation records.
-        String csid;
-        Set<String> collectionObjectCsids = new HashSet<String>();
-        for (DocumentModel relationDocModel : relationDocModels) {
-            csid = getCsidForDesiredDocType(relationDocModel, COLLECTIONOBJECT_DOCTYPE, MOVEMENT_DOCTYPE);
-            if (Tools.notBlank(csid)) {
-                collectionObjectCsids.add(csid);
-            }
+        if (notificationDocumentType == EventNotificationDocumentType.RELATION) {
+            String relatedCollectionObjectCsid =
+                    getCsidForDesiredDocTypeFromRelation(docModel, COLLECTIONOBJECT_DOCTYPE, MOVEMENT_DOCTYPE);
+            collectionObjectCsids.add(relatedCollectionObjectCsid);
+        } else if (notificationDocumentType == EventNotificationDocumentType.MOVEMENT) {
+            collectionObjectCsids.addAll(getCollectionObjectCsidsRelatedToMovement(movementCsid, coreSession));
         }
-        if (collectionObjectCsids == null || collectionObjectCsids.isEmpty()) {
+
+        if (collectionObjectCsids.isEmpty()) {
             logger.warn("Could not obtain any CSIDs of related CollectionObject records.");
             logger.warn(NO_FURTHER_PROCESSING_MESSAGE);
             return;
@@ -171,7 +156,6 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
                 logger.trace("Found " + collectionObjectCsids.size() + " CSIDs of related CollectionObject records.");
             }
         }
-
         // Iterate through the list of CollectionObject CSIDs found.
         // For each CollectionObject, obtain its most recent, related Movement,
         // and update relevant field(s) with values from that Movement record.
@@ -200,16 +184,70 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
                     updateCollectionObjectValuesFromMovement(collectionObjectDocModel, mostRecentMovementDocModel);
             coreSession.saveDocument(collectionObjectDocModel);
         }
+    }
 
+    /**
+     * Returns the CSIDs of CollectionObject records that are related to a
+     * Movement record.
+     *
+     * @param movementCsid the CSID of a Movement record.
+     * @param coreSession a repository session.
+     * @throws ClientException
+     * @return the CSIDs of the CollectionObject records, if any, which are
+     * related to the Movement record.
+     */
+    private Set<String> getCollectionObjectCsidsRelatedToMovement(String movementCsid,
+            CoreSession coreSession) throws ClientException {
+
+        Set<String> csids = new HashSet<>();
+
+        // Via an NXQL query, get a list of active relation records where:
+        // * This movement record's CSID is the subject CSID of the relation,
+        //   and its object document type is a CollectionObject doctype;
+        // or
+        // * This movement record's CSID is the object CSID of the relation,
+        //   and its subject document type is a CollectionObject doctype.
+        //
+        // Some values below are hard-coded for readability, rather than
+        // being obtained from constants.
+        String query = String.format(
+                "SELECT * FROM %1$s WHERE " // collectionspace_core:tenantId = 1 "
+                + "("
+                + "  (%2$s:subjectCsid = '%3$s' "
+                + "  AND %2$s:objectDocumentType = '%4$s') "
+                + " OR "
+                + "  (%2$s:objectCsid = '%3$s' "
+                + "  AND %2$s:subjectDocumentType = '%4$s') "
+                + ")"
+                + ACTIVE_DOCUMENT_WHERE_CLAUSE_FRAGMENT,
+                RELATION_DOCTYPE, RELATIONS_COMMON_SCHEMA, movementCsid, COLLECTIONOBJECT_DOCTYPE);
+        DocumentModelList relationDocModels = coreSession.query(query);
+        if (relationDocModels == null || relationDocModels.isEmpty()) {
+            // Encountering a Movement record that is not related to any
+            // CollectionObject is potentially a normal occurrence, so no
+            // error messages are logged here when we stop handling this event.
+            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.
+        String csid;
+        for (DocumentModel relationDocModel : relationDocModels) {
+            csid = getCsidForDesiredDocTypeFromRelation(relationDocModel, COLLECTIONOBJECT_DOCTYPE, MOVEMENT_DOCTYPE);
+            if (Tools.notBlank(csid)) {
+                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.
+// 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.
      *
@@ -290,8 +328,7 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
     // getting the most recent Movement record related to a CollectionObject,
     // augmented by procedural code.
     //
-    // Should be replaced by a more performant method, based entirely, or nearly so,
-    // on a query.
+    // Could be replaced by a potentially more performant method, based on a query.
     //
     // E.g. the following is a sample CMIS query for retrieving Movement records
     // related to a CollectionObject, which might serve as the basis for that query.
@@ -348,9 +385,9 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
         // Iterate through related movement records, to find the related
         // Movement record with the most recent location date.
         GregorianCalendar mostRecentLocationDate = EARLIEST_COMPARISON_DATE;
-        DocumentModel movementDocModel = null;
-        Set<String> alreadyProcessedMovementCsids = new HashSet<String>();
-        String relatedMovementCsid = "";
+        DocumentModel movementDocModel;
+        Set<String> alreadyProcessedMovementCsids = new HashSet<>();
+        String relatedMovementCsid;
         for (DocumentModel relationDocModel : relationDocModels) {
             // Due to the 'OR' operator in the query above, related Movement
             // record CSIDs may reside in either the subject or object CSID fields
@@ -374,7 +411,7 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
                 alreadyProcessedMovementCsids.add(relatedMovementCsid);
             }
             if (logger.isTraceEnabled()) {
-                logger.trace("Movement CSID=" + relatedMovementCsid);
+                logger.trace("Related movement CSID=" + relatedMovementCsid);
             }
             movementDocModel = getDocModelFromCsid(session, relatedMovementCsid);
             if (movementDocModel == null) {
@@ -416,7 +453,7 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
      * and related document types, or if the desired document type is at both
      * ends of the relation.
      */
-    protected static String getCsidForDesiredDocType(DocumentModel relationDocModel,
+    protected static String getCsidForDesiredDocTypeFromRelation(DocumentModel relationDocModel,
             String desiredDocType, String relatedDocType) throws ClientException {
         String csid = "";
         String subjectDocType = (String) relationDocModel.getProperty(RELATIONS_COMMON_SCHEMA, SUBJECT_DOCTYPE_PROPERTY);
@@ -432,8 +469,8 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
         return csid;
     }
 
-    // Can be extended by sub-classes to update different/multiple values;
-    // e.g. values for moveable locations ("crates").
+    // The following method can be extended by sub-classes to update
+    // different/multiple values; e.g. values for moveable locations ("crates").
     /**
      * Updates a CollectionObject record with selected values from a Movement
      * record.
@@ -441,6 +478,8 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
      * @param collectionObjectDocModel a document model for a CollectionObject
      * record.
      * @param movementDocModel a document model for a Movement record.
+     * @return a potentially updated document model for the CollectionObject
+     * record.
      * @throws ClientException
      */
     protected abstract DocumentModel updateCollectionObjectValuesFromMovement(DocumentModel collectionObjectDocModel,