1 package org.collectionspace.services.nuxeo.listener.relation;
3 import java.util.ArrayList;
4 import java.util.Iterator;
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.collectionspace.services.common.document.DocumentFilter;
9 import org.nuxeo.ecm.core.api.ClientException;
10 import org.nuxeo.ecm.core.api.CoreSession;
11 import org.nuxeo.ecm.core.api.DocumentModel;
12 import org.nuxeo.ecm.core.api.DocumentModelList;
13 import org.nuxeo.ecm.core.api.impl.LifeCycleFilter;
14 import org.nuxeo.ecm.core.event.Event;
15 import org.nuxeo.ecm.core.event.EventContext;
16 import org.nuxeo.ecm.core.event.EventListener;
17 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
19 public class RelationSubOrObjDeletionListener implements EventListener {
21 // FIXME: Consider adding the following constant to
22 // org.collectionspace.services.common.workflow.jaxb.WorkflowJAXBSchema
23 // and referencing it from there.
24 private static final String WORKFLOWTRANSITION_TO = "to";
25 // FIXME: Consider substituting existing constant WorkflowClient.WORKFLOWSTATE_DELETED
26 private static final String WORKFLOWSTATE_DELETED = "deleted";
27 // FIXME: Consider substituting existing constant WorkflowClient.WORKFLOWSTATE_LOCKED
28 private static final String WORKFLOWSTATE_LOCKED = "locked";
29 // FIXME: Consider substituting existing constant WorkflowClient.WORKFLOWTRANSITION_DELETE
30 private static final String WORKFLOWTRANSITION_DELETE = "delete";
32 // FIXME: We might experiment here with using log4j instead of Apache Commons Logging;
33 // am using the latter to follow Ray's pattern for now
34 final Log logger = LogFactory.getLog(RelationSubOrObjDeletionListener.class);
36 public void handleEvent(Event event) throws ClientException {
37 logger.info("In handleEvent in RelationSubOrObjDeletionListener ...");
39 EventContext eventContext = event.getContext();
41 if (isDocumentSoftDeletedEvent(eventContext)) {
43 DocumentEventContext docContext = (DocumentEventContext) eventContext;
44 DocumentModel docModel = docContext.getSourceDocument();
46 // Retrieve a list of relation records, where the soft deleted
47 // document provided in the context of the current event is
48 // either the subject or object of any relation
50 // Build a query string
51 String csid = docModel.getName();
52 StringBuilder queryString = new StringBuilder("");
53 queryString.append("SELECT * FROM Relation WHERE ");
54 // FIXME: Obtain and add tenant ID to the query here
55 // queryString.append("collectionspace_core:tenantId = 1 ");
56 // queryString.append(" AND ");
57 // queryString.append("ecm:currentLifeCycleState <> 'deleted' ");
58 queryString.append("ecm:isProxy = 0 ");
59 queryString.append(" AND ");
60 queryString.append("(");
61 queryString.append("relations_common:subjectCsid = ");
62 queryString.append("'");
63 queryString.append(csid);
64 queryString.append("'");
65 queryString.append(" OR ");
66 queryString.append("relations_common:objectCsid = ");
67 queryString.append("'");
68 queryString.append(csid);
69 queryString.append("'");
70 queryString.append(")");
72 // Create a filter to exclude from the list results any records
73 // that have already been soft deleted or are locked
74 List<String> workflowStatesToFilter = new ArrayList<String>();
75 workflowStatesToFilter.add(WORKFLOWSTATE_DELETED);
76 workflowStatesToFilter.add(WORKFLOWSTATE_LOCKED);
77 LifeCycleFilter workflowStateFilter = new LifeCycleFilter(null, workflowStatesToFilter);
79 // Perform the filtered query
80 CoreSession session = docModel.getCoreSession();
81 DocumentModelList matchingDocuments;
83 matchingDocuments = session.query(queryString.toString(), workflowStateFilter);
84 } catch (ClientException ce) {
85 logger.warn("Error attempting to retrieve relation records where "
86 + "record of type '" + docModel.getType() + "' with CSID " + csid
87 + " is the subject or object of any relation: " + ce.getMessage());
91 // Cycle through the list results, soft deleting each matching relation record
92 logger.trace("Attempting to soft delete " + matchingDocuments.size() + " relation records.");
93 for (DocumentModel doc : matchingDocuments) {
94 doc.followTransition(WORKFLOWTRANSITION_DELETE);
102 * Identifies whether a supplied event concerns a document that has
103 * been transitioned to the 'deleted' workflow state.
105 * @param eventContext an event context
107 * @return true if this event concerns a document that has
108 * been transitioned to the 'deleted' workflow state.
110 private boolean isDocumentSoftDeletedEvent(EventContext eventContext) {
111 boolean isSoftDeletedEvent = false;
112 if (eventContext instanceof DocumentEventContext) {
113 if (eventContext.getProperties().containsKey(WORKFLOWTRANSITION_TO)
114 && eventContext.getProperties().get(WORKFLOWTRANSITION_TO).equals(WORKFLOWSTATE_DELETED)) {
115 isSoftDeletedEvent = true;
118 return isSoftDeletedEvent;