1 package org.collectionspace.services.listener;
3 import java.util.ArrayList;
4 import java.util.IllegalFormatException;
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9 import org.collectionspace.services.client.workflow.WorkflowClient;
10 import org.collectionspace.services.common.document.DocumentException;
11 import org.collectionspace.services.nuxeo.client.java.CoreSessionInterface;
12 import org.collectionspace.services.nuxeo.client.java.CoreSessionWrapper;
13 import org.collectionspace.services.nuxeo.listener.AbstractCSEventListenerImpl;
14 import org.nuxeo.ecm.core.api.DocumentModel;
15 import org.nuxeo.ecm.core.api.DocumentModelList;
16 import org.nuxeo.ecm.core.api.impl.LifeCycleFilter;
17 import org.nuxeo.ecm.core.event.Event;
18 import org.nuxeo.ecm.core.event.EventContext;
19 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
21 public class UpdateRelationsOnDelete extends AbstractCSEventListenerImpl {
23 // FIXME: We might experiment here with using log4j instead of Apache Commons Logging;
24 // am using the latter to follow Ray's pattern for now
25 final Log logger = LogFactory.getLog(UpdateRelationsOnDelete.class);
27 // FIXME: Get these constant values from external sources rather than redeclaring here
28 final static String RELATION_DOCTYPE = "Relation";
29 final static String RELATIONS_COMMON_SUBJECT_CSID_FIELD = "relations_common:subjectCsid";
30 final static String RELATIONS_COMMON_OBJECT_CSID_FIELD = "relations_common:objectCsid";
33 public void handleEvent(Event event) {
34 logger.trace("In handleEvent in UpdateRelationsOnDelete ...");
36 EventContext eventContext = event.getContext();
38 if (isRegistered(event) && isDocumentSoftDeletedEvent(eventContext)) {
40 logger.trace("A soft deletion event was received by UpdateRelationsOnDelete ...");
42 DocumentEventContext docContext = (DocumentEventContext) eventContext;
43 DocumentModel docModel = docContext.getSourceDocument();
45 // Exclude soft deletion events involving Relation records themselves
46 // from handling by this event handler.
47 if (docModel != null && docModel.getType().startsWith(RELATION_DOCTYPE)) {
51 // Retrieve a list of relation records, where the soft deleted
52 // document provided in the context of the current event is
53 // either the subject or object of any relation
55 // Build a query string
56 String csid = docModel.getName();
61 String.format("SELECT * FROM Relation WHERE ecm:isProxy = 0 AND (%1$s='%3$s' OR %2$s='%3$s')",
62 RELATIONS_COMMON_SUBJECT_CSID_FIELD, RELATIONS_COMMON_OBJECT_CSID_FIELD, csid);
63 logger.trace("Query string=" + queryString);
64 } catch (IllegalFormatException ife) {
65 logger.warn("Construction of formatted query string failed: ", ife);
66 logger.warn("Actions in this event listener will NOT be performed, as a result of a previous Exception.");
70 // Create a filter to exclude from the list results any records
71 // that have already been soft deleted or are locked
72 List<String> workflowStatesToFilter = new ArrayList<String>();
73 workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_DELETED);
74 workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED);
75 workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED);
76 workflowStatesToFilter.add(WorkflowClient.WORKFLOWSTATE_REPLICATED_DELETED);
78 LifeCycleFilter workflowStateFilter = new LifeCycleFilter(null, workflowStatesToFilter);
80 // Perform the filtered query
81 CoreSessionInterface session = new CoreSessionWrapper(docModel.getCoreSession());
82 DocumentModelList matchingDocuments;
84 matchingDocuments = session.query(queryString.toString(), workflowStateFilter);
85 } catch (DocumentException ce) {
86 logger.error("Error attempting to retrieve relation records where "
87 + "record of type '" + docModel.getType() + "' with CSID " + csid
88 + " is the subject or object of any relation: " + ce.getMessage());
92 // Cycle through the list results, soft deleting each matching relation record
93 logger.info("Attempting to soft delete " + matchingDocuments.size() + " relation records pertaining to a soft deleted record.");
94 for (DocumentModel doc : matchingDocuments) {
95 doc.followTransition(WorkflowClient.WORKFLOWTRANSITION_DELETE);
102 // FIXME: Generic methods like the following might be split off
103 // into an event utilities class. - ADR 2012-12-05
106 * Identifies whether a supplied event concerns a document that has
107 * been transitioned to the 'deleted' workflow state.
109 * @param eventContext an event context
111 * @return true if this event concerns a document that has
112 * been transitioned to the 'deleted' workflow state.
114 private boolean isDocumentSoftDeletedEvent(EventContext eventContext) {
115 boolean isSoftDeletedEvent = false;
117 if (eventContext instanceof DocumentEventContext) {
118 if (eventContext.getProperties().containsKey(WorkflowClient.WORKFLOWTRANSITION_TO)
120 (eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_DELETED)
122 eventContext.getProperties().get(WorkflowClient.WORKFLOWTRANSITION_TO).equals(WorkflowClient.WORKFLOWSTATE_LOCKED_DELETED))) {
123 isSoftDeletedEvent = true;
127 return isSoftDeletedEvent;