From: Aron Roberts Date: Tue, 30 Apr 2013 20:36:25 +0000 (-0700) Subject: CSPACE-5984,PAHMA-789: In the UpdateObjectLocationOnMove event handler, when receivin... X-Git-Url: https://git.aero2k.de/?a=commitdiff_plain;h=b4da9cf19cc8788145b73b17719cac3c7f7b4123;p=tmp%2Fjakarta-migration.git CSPACE-5984,PAHMA-789: In the UpdateObjectLocationOnMove event handler, when receiving an event notification related to a Relation record, process only the CollectionObject that is the subject or object of the relation. --- diff --git a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java index a046d53db..6ca3d6672 100644 --- a/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java +++ b/3rdparty/nuxeo/nuxeo-platform-listener/updateobjectlocationonmove/src/main/java/org/collectionspace/services/listener/AbstractUpdateObjectLocationValues.java @@ -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 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 collectionObjectCsids = new HashSet(); - 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 getCollectionObjectCsidsRelatedToMovement(String movementCsid, + CoreSession coreSession) throws ClientException { + + Set 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 alreadyProcessedMovementCsids = new HashSet(); - String relatedMovementCsid = ""; + DocumentModel movementDocModel; + Set 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,