+ "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 {
//
// (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 ...");
// 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;
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.
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.
*
// 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.
// 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
alreadyProcessedMovementCsids.add(relatedMovementCsid);
}
if (logger.isTraceEnabled()) {
- logger.trace("Movement CSID=" + relatedMovementCsid);
+ logger.trace("Related movement CSID=" + relatedMovementCsid);
}
movementDocModel = getDocModelFromCsid(session, relatedMovementCsid);
if (movementDocModel == null) {
* 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);
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.
* @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,