1 package org.collectionspace.services.listener;
3 import java.util.Iterator;
6 import org.apache.commons.collections.ListUtils;
7 import org.apache.commons.lang3.StringUtils;
8 import org.nuxeo.ecm.core.api.DocumentModel;
9 import org.nuxeo.ecm.core.api.LifeCycleConstants;
10 import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
11 import org.nuxeo.ecm.core.event.Event;
12 import org.nuxeo.ecm.core.event.EventBundle;
13 import org.nuxeo.ecm.core.event.PostCommitEventListener;
14 import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
15 import org.nuxeo.elasticsearch.ElasticSearchComponent;
16 import org.nuxeo.elasticsearch.api.ElasticSearchService;
17 import org.nuxeo.runtime.api.Framework;
20 * Event listener that triggers reindexing of records in Elasticsearch when an associated record
21 * is created/updated/deleted. When a record is created or updated Nuxeo will automatically
22 * reindex it in ElasticSearch, but Nuxeo does not know about other records that may also need to
23 * be reindexed; for example, if a related record denormalizes data from the updated record at
26 public class Reindex implements PostCommitEventListener {
27 // FIXME: This listener runs asynchronously post-commit, so that reindexing records after a
28 // save does not hold up the save. In order to make it async, this class does not extend
29 // AbstractCSEventListenerImpl, because AbstractCSEventListenerImpl does not implement
30 // PostCommitEventListener (DRYD-477). Therefore this listener is not able to use the
31 // isRegistered method of AbstractCSEventListenerImpl to determine if it has been registered to
32 // run for the current tenant. Instead, it relies on the ReindexSupport listener, which does
33 // extend AbstractCSEventListenerImpl, to set a property in the event context that is used to
34 // determine if this listener should run. This means that this listener will be considered to
35 // be registered if and only if the ReindexSupport listener is registered.
37 public static final String IS_REGISTERED_KEY = "Reindex.IS_REGISTERED";
38 public static final String PREV_COVERAGE_KEY = "Reindex.PREV_COVERAGE";
39 public static final String PREV_PUBLISH_TO_KEY = "Reindex.PREV_PUBLISH_TO";
42 public void handleEvent(EventBundle events) {
43 // When a media record is created, reindex the material item that is referenced by its
46 // When a media record is updated and the coverage changed, reindex both the old and new
47 // referenced material items.
49 // When a media record is deleted, reindex the material item that was referenced by its
52 // TODO: Make this configurable. This is currently hardcoded to the needs of the material
53 // profile/Material Order application.
55 if (Framework.isBooleanPropertyTrue("elasticsearch.enabled") && events.size() > 0) {
56 Iterator<Event> iter = events.iterator();
58 while (iter.hasNext()) {
59 Event event = iter.next();
60 DocumentEventContext eventContext = (DocumentEventContext) event.getContext();
61 Boolean isRegistered = (Boolean) eventContext.getProperty(IS_REGISTERED_KEY);
63 if (isRegistered != null && isRegistered == true) {
64 DocumentModel doc = eventContext.getSourceDocument();
65 String docType = doc.getType();
66 String eventName = event.getName();
68 if (docType.startsWith("Media")) {
70 eventName.equals(DocumentEventTypes.DOCUMENT_CREATED) ||
71 eventName.equals(DocumentEventTypes.DOCUMENT_UPDATED)
73 String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
74 String coverage = (String) doc.getProperty("media_common", "coverage");
76 List<String> prevPublishTo = (List<String>) eventContext.getProperty(PREV_PUBLISH_TO_KEY);
77 List<String> publishTo = (List<String>) doc.getProperty("media_materials", "publishToList");
79 if (doc.getCurrentLifeCycleState().equals(LifeCycleConstants.DELETED_STATE)) {
80 reindex(doc.getRepositoryName(), coverage);
83 !ListUtils.isEqualList(prevPublishTo, publishTo) ||
84 !StringUtils.equals(prevCoverage, coverage)
86 if (!StringUtils.equals(prevCoverage, coverage)) {
87 reindex(doc.getRepositoryName(), prevCoverage);
90 reindex(doc.getRepositoryName(), coverage);
93 else if (eventName.equals(DocumentEventTypes.DOCUMENT_REMOVED)) {
94 String prevCoverage = (String) eventContext.getProperty(PREV_COVERAGE_KEY);
96 reindex(doc.getRepositoryName(), prevCoverage);
104 private void reindex(String repositoryName, String refName) {
105 if (StringUtils.isEmpty(refName)) {
109 String escapedRefName = refName.replace("'", "\\'");
110 String query = String.format("SELECT ecm:uuid FROM Materialitem WHERE collectionspace_core:refName = '%s'", escapedRefName);
112 ElasticSearchComponent es = (ElasticSearchComponent) Framework.getService(ElasticSearchService.class);
113 es.runReindexingWorker(repositoryName, query);