1 package org.collectionspace.services.listener;
5 import org.apache.commons.collections.ListUtils;
6 import org.apache.commons.lang3.StringUtils;
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
10 import org.collectionspace.services.nuxeo.listener.AbstractCSEventPostCommitListenerImpl;
11 import org.nuxeo.ecm.core.api.DocumentModel;
12 import org.nuxeo.ecm.core.api.LifeCycleConstants;
13 import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
14 import org.nuxeo.ecm.core.event.Event;
15 import org.nuxeo.ecm.core.event.EventBundle;
16 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
17 import org.nuxeo.elasticsearch.ElasticSearchComponent;
18 import org.nuxeo.elasticsearch.api.ElasticSearchService;
19 import org.nuxeo.runtime.api.Framework;
22 * Event listener that triggers reindexing of records in Elasticsearch when an associated record
23 * is created/updated/deleted. When a record is created or updated Nuxeo will automatically
24 * reindex it in ElasticSearch, but Nuxeo does not know about other records that may also need to
25 * be reindexed; for example, if a related record denormalizes data from the updated record at
28 public class Reindex extends AbstractCSEventPostCommitListenerImpl {
29 private final static Log logger = LogFactory.getLog(Reindex.class);
31 // FIXME: This listener runs asynchronously post-commit, so that reindexing records after a
32 // save does not hold up the save.
34 public static final String PREV_COVERAGE_KEY = "Reindex.PREV_COVERAGE";
35 public static final String PREV_PUBLISH_TO_KEY = "Reindex.PREV_PUBLISH_TO";
36 public static final String ELASTICSEARCH_ENABLED_PROP = "elasticsearch.enabled";
39 public boolean shouldHandleEventBundle(EventBundle eventBundle) {
40 if (Framework.isBooleanPropertyTrue(ELASTICSEARCH_ENABLED_PROP) && eventBundle.size() > 0) {
48 public boolean shouldHandleEvent(Event event) {
49 DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
50 DocumentModel doc = eventContext.getSourceDocument();
51 String docType = doc.getType();
53 if (docType.startsWith("Media")) {
61 @SuppressWarnings("unchecked")
62 public void handleCSEvent(Event event) {
63 DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
64 DocumentModel doc = eventContext.getSourceDocument();
65 String eventName = event.getName();
67 // When a media record is created, reindex the material item that is referenced by its
70 // When a media record is updated and the coverage changed, reindex both the old and new
71 // referenced material items.
73 // When a media record is deleted, reindex the material item that was referenced by its
76 // TODO: Make this configurable. This is currently hardcoded to the needs of the material
77 // profile/Material Order application.
80 eventName.equals(DocumentEventTypes.DOCUMENT_CREATED) ||
81 eventName.equals(DocumentEventTypes.DOCUMENT_UPDATED)
83 String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
84 String coverage = (String) doc.getProperty("media_common", "coverage");
86 List<String> prevPublishTo = (List<String>) eventContext.getProperty(PREV_PUBLISH_TO_KEY);
87 List<String> publishTo = (List<String>) doc.getProperty("media_materials", "publishToList");
89 if (doc.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) {
90 reindex(doc.getRepositoryName(), coverage);
93 !ListUtils.isEqualList(prevPublishTo, publishTo) ||
94 !StringUtils.equals(prevCoverage, coverage)
96 if (!StringUtils.equals(prevCoverage, coverage)) {
97 reindex(doc.getRepositoryName(), prevCoverage);
100 reindex(doc.getRepositoryName(), coverage);
103 else if (eventName.equals(DocumentEventTypes.DOCUMENT_REMOVED)) {
104 String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
106 reindex(doc.getRepositoryName(), prevCoverage);
111 protected Log getLogger() {
115 private void reindex(String repositoryName, String refName) {
116 if (StringUtils.isEmpty(refName)) {
120 String escapedRefName = refName.replace("'", "\\'");
121 String query = String.format("SELECT ecm:uuid FROM Materialitem WHERE collectionspace_core:refName = '%s'", escapedRefName);
123 ElasticSearchComponent es = (ElasticSearchComponent) Framework.getService(ElasticSearchService.class);
124 es.runReindexingWorker(repositoryName, query);