]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-6717: Event listener that updates computed current location in Cataloging...
authorAron Roberts <aron@socrates.berkeley.edu>
Wed, 4 Sep 2013 00:35:00 +0000 (17:35 -0700)
committerAron Roberts <aron@socrates.berkeley.edu>
Wed, 4 Sep 2013 00:35:00 +0000 (17:35 -0700)
3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java
services/IntegrationTests/src/test/resources/test-data/xmlreplay/listener/listener-update-object-loc.xml

index d66777a73b679a37693f717abb88680d35755841..f1a8e776d8a8c79fdb0a2dee397c9f95fcda3c8c 100644 (file)
@@ -42,10 +42,12 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
     protected final static String CURRENT_LOCATION_PROPERTY = "currentLocation"; // FIXME: Get from external constant
     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
+    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') "
-            + "AND ecm:isProxy = 0 "
-            + "AND ecm:isCheckedInVersion = 0";
+            + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT;
 
     public enum EventNotificationDocumentType {
         // Document type about which we've received a notification
@@ -167,13 +169,19 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
             if (logger.isTraceEnabled()) {
                 logger.trace("CollectionObject CSID=" + collectionObjectCsid);
             }
-            // Verify that the CollectionObject is retrievable.
-            collectionObjectDocModel = getDocModelFromCsid(coreSession, collectionObjectCsid);
+            // Verify that the CollectionObject is both retrievable and active.
+            collectionObjectDocModel = getCurrentDocModelFromCsid(coreSession, collectionObjectCsid);
             if (collectionObjectDocModel == null) {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("CollectionObject is not current (i.e. is a non-current version), is a proxy, or is unretrievable.");
+                }
                 continue;
             }
             // Verify that the CollectionObject record is active.
             if (!isActiveDocument(collectionObjectDocModel)) {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("CollectionObject is inactive (i.e. deleted or in an otherwise inactive lifestyle state).");
+                }
                 continue;
             }
             // Get the CollectionObject's most recent, related Movement.
@@ -270,13 +278,8 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
     }
 
     /**
-     * Identifies whether a document is an active document; that is, if it is
-     * not a versioned record; not a proxy (symbolic link to an actual record);
-     * and not in the 'deleted' workflow state.
-     *
-     * (A note relating the latter: Nuxeo appears to send 'documentModified'
-     * events even on workflow transitions, such when records are 'soft deleted'
-     * by being transitioned to the 'deleted' workflow state.)
+     * Identifies whether a document is an active document; currently, whether
+     * it is not in the 'deleted' workflow state.
      *
      * @param docModel
      * @return true if the document is an active document; false if it is not.
@@ -287,9 +290,7 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
         }
         boolean isActiveDocument = false;
         try {
-            if (!docModel.isVersion()
-                    && !docModel.isProxy()
-                    && !docModel.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
+            if (!docModel.getCurrentLifeCycleState().equals(WorkflowClient.WORKFLOWSTATE_DELETED)) {
                 isActiveDocument = true;
             }
         } catch (ClientException ce) {
@@ -299,28 +300,35 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
     }
 
     /**
-     * Returns a document model for a record identified by a CSID.
+     * 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 collectionObjectCsid a CollectionObject identifier (CSID)
-     * @return a document model for the record identified by the supplied CSID.
+     * @return a document model for the document identified by the supplied
+     * CSID.
      */
-    protected static DocumentModel getDocModelFromCsid(CoreSession session, String collectionObjectCsid) {
+    protected static DocumentModel getCurrentDocModelFromCsid(CoreSession session, String collectionObjectCsid) {
         DocumentModelList collectionObjectDocModels = null;
         try {
             final String query = "SELECT * FROM "
                     + NuxeoUtils.BASE_DOCUMENT_TYPE
                     + " WHERE "
-                    + NuxeoUtils.getByNameWhereClause(collectionObjectCsid);
+                    + NuxeoUtils.getByNameWhereClause(collectionObjectCsid)
+                    + " "
+                    + NONVERSIONED_NONPROXY_DOCUMENT_WHERE_CLAUSE_FRAGMENT;
             collectionObjectDocModels = session.query(query);
         } catch (Exception e) {
-            logger.warn("Exception in query to get document model for CollectionObject: ", e);
+            logger.warn("Exception in query to get active document model for CollectionObject: ", e);
         }
         if (collectionObjectDocModels == null || collectionObjectDocModels.isEmpty()) {
-            logger.warn("Could not get document models for CollectionObject(s).");
+            logger.warn("Could not get active document models for CollectionObject(s).");
             return null;
         } else if (collectionObjectDocModels.size() != 1) {
-            logger.debug("Found more than 1 document with CSID=" + collectionObjectCsid);
+            logger.debug("Found more than 1 active document with CSID=" + collectionObjectCsid);
             return null;
         }
         return collectionObjectDocModels.get(0);
@@ -419,17 +427,17 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
             if (logger.isTraceEnabled()) {
                 logger.trace("Related movement CSID=" + relatedMovementCsid);
             }
-            movementDocModel = getDocModelFromCsid(session, relatedMovementCsid);
+            movementDocModel = getCurrentDocModelFromCsid(session, relatedMovementCsid);
             if (movementDocModel == null) {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("Movement is not current (i.e. is a non-current version), is a proxy, or is unretrievable.");
+                }
                 continue;
             }
-
-            // Verify that the Movement record is active. This will also exclude
-            // versioned Movement records from the computation of the current
-            // location, for tenants that are versioning such records.
+            // Verify that the Movement record is active.
             if (!isActiveDocument(movementDocModel)) {
                 if (logger.isTraceEnabled()) {
-                    logger.trace("Skipping this inactive Movement record ...");
+                    logger.trace("Movement is inactive (i.e. is deleted or in another inactive lifestyle state).");
                 }
                 continue;
             }
@@ -441,7 +449,7 @@ public abstract class AbstractUpdateObjectLocationValues implements EventListene
                 continue;
             }
             GregorianCalendar creationDate =
-                        (GregorianCalendar) movementDocModel.getProperty(COLLECTIONSPACE_CORE_SCHEMA, CREATED_AT_PROPERTY);
+                    (GregorianCalendar) movementDocModel.getProperty(COLLECTIONSPACE_CORE_SCHEMA, CREATED_AT_PROPERTY);
             if (locationDate.after(mostRecentLocationDate)) {
                 mostRecentLocationDate = locationDate;
                 if (creationDate != null) {
index 1aeec652b8a1de8e101b837ebcbda4f78083a291..fd1202e681e2b124b5a5bfd00db0d4cd20f4399d 100644 (file)
@@ -3,6 +3,7 @@
     <auths>
         <!-- IMPORTANT: THESE ARE STICKY :: THEY STICK AROUND UNTIL RESET, IN EXEC ORDER OF THIS FILE. -->
         <auth ID="admin@core.collectionspace.org">YWRtaW5AY29yZS5jb2xsZWN0aW9uc3BhY2Uub3JnOkFkbWluaXN0cmF0b3I=</auth>
+        <auth ID="admin@lifesci.collectionspace.org">YWRtaW5AbGlmZXNjaS5jb2xsZWN0aW9uc3BhY2Uub3JnOkFkbWluaXN0cmF0b3I=</auth>
     </auths>
         
     <!-- This tests the UpdateObjectLocationOnMoveEventListener -->
         </test>
         
     </testGroup>
-    
+    <!-- These tests verify that updates to the computed current location values -->
+    <!-- in CollectionObject records succeed, even in tenants where Movement -->
+    <!-- records are configured to be versioned. See CSPACE-6171 for more details. -->    
+    <testGroup ID="updateObjectLocationOnMoveInVersioningEnabledTenant" autoDeletePOSTS="true">
+
+        <test ID="createCollectionObjectInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/collectionobjects</uri>
+            <filename>listener/collectionobject.xml</filename>
+            <expectedCodes>201</expectedCodes>
+        </test>
+        
+        <test ID="createMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/movements</uri>
+            <filename>listener/movement.xml</filename>
+            <vars>
+                <var ID="currentLocation">urn:cspace:core.collectionspace.org:locationauthorities:name(offsite_sla):item:name(Ecatepec13582155455560)'Ecatepec, Mexico'</var>
+                <var ID="locationDate">2000-01-01</var>
+            </vars>
+            <expectedCodes>201</expectedCodes>
+        </test>
+        
+        <test ID="relateCollectionObjectToMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>POST</method>
+            <uri>/cspace-services/relations</uri>
+            <filename>listener/relation.xml</filename>
+            <vars>
+                <var ID="subjectCsid">${createCollectionObjectInVersioningTenant.CSID}</var>
+                <var ID="subjectDocumentType">CollectionObject</var>
+                <var ID="objectCsid">${createMovementInVersioningTenant.CSID}</var>
+                <var ID="objectDocumentType">Movement</var>
+            </vars>
+            <expectedCodes>201</expectedCodes>
+        </test>
+        
+        <!-- See comment on updateMovement1 in the updateObjectLocationOnMoveEventListener -->
+        <!-- test group for an explanation of why this update is needed, after -->
+        <!-- creating a new relation -->
+        <test ID="updateMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>PUT</method>
+            <uri>/cspace-services/movements/${createMovementInVersioningTenant.CSID}</uri>
+            <filename>listener/movement.xml</filename>
+            <vars>
+                <var ID="currentLocation">${createMovementInVersioningTenant.currentLocation}</var>
+                <var ID="locationDate">${createMovementInVersioningTenant.locationDate}</var>
+            </vars>
+            <expectedCodes>200</expectedCodes>
+        </test>
+        
+        <test ID="readCollectionObjectAfterRelatingToMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>GET</method>
+            <uri>/cspace-services/collectionobjects/${createCollectionObjectInVersioningTenant.CSID}</uri>
+            <response>
+                <expected level="ADDOK" />
+                <filename>listener/res/collectionobject.res.xml</filename>
+                <vars>
+                    <var ID="computedCurrentLocationValue">${createMovementInVersioningTenant.currentLocation}</var>
+                </vars>
+            </response>
+            <expectedCodes>200</expectedCodes>
+        </test>
+        
+        <test ID="modifyMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>PUT</method>
+            <uri>/cspace-services/movements/${createMovementInVersioningTenant.CSID}</uri>
+            <filename>listener/movement.xml</filename>
+            <vars>
+                <var ID="currentLocation">urn:cspace:core.collectionspace.org:locationauthorities:name(offsite_sla):item:name(Guadalajara13582155455562)'Guadalajara, Mexico'</var>
+                <var ID="locationDate">2000-01-02</var>
+            </vars>
+            <expectedCodes>200</expectedCodes>
+        </test>
+        
+        <test ID="readCollectionObjectAfterModifyingMovementInVersioningTenant" auth="admin@lifesci.collectionspace.org">
+            <method>GET</method>
+            <uri>/cspace-services/collectionobjects/${createCollectionObjectInVersioningTenant.CSID}</uri>
+            <response>
+                <expected level="ADDOK" />
+                <filename>listener/res/collectionobject.res.xml</filename>
+                <vars>
+                    <var ID="computedCurrentLocationValue">${modifyMovementInVersioningTenant.currentLocation}</var>
+                </vars>
+            </response>
+            <expectedCodes>200</expectedCodes>
+        </test>
+        
+    </testGroup>
+        
     <!-- Some of the following tests pertain to CSPACE-5793, not yet -->
     <!-- resolved as of this writing. - ADR 2013-02-14 -->
     
         </test>
         
     </testGroup>
-    
+        
 </xmlReplay>