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