001/*
002 * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
020 */
021
022package org.nuxeo.ecm.platform.dublincore.listener;
023
024import static org.nuxeo.ecm.core.api.LifeCycleConstants.TRANSITION_EVENT;
025import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.BEFORE_DOC_UPDATE;
026import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.DOCUMENT_CREATED;
027import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.DOCUMENT_CREATED_BY_COPY;
028import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.DOCUMENT_PUBLISHED;
029import static org.nuxeo.ecm.core.schema.FacetNames.SYSTEM_DOCUMENT;
030
031import java.io.Serializable;
032import java.util.Calendar;
033import java.util.Date;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.nuxeo.ecm.core.api.CoreSession;
038import org.nuxeo.ecm.core.api.DocumentModel;
039import org.nuxeo.ecm.core.api.DocumentRef;
040import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
041import org.nuxeo.ecm.core.api.event.CoreEventConstants;
042import org.nuxeo.ecm.core.event.Event;
043import org.nuxeo.ecm.core.event.EventListener;
044import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
045import org.nuxeo.ecm.platform.dublincore.NXDublinCore;
046import org.nuxeo.ecm.platform.dublincore.service.DublinCoreStorageService;
047import org.nuxeo.runtime.api.Framework;
048import org.nuxeo.runtime.services.config.ConfigurationService;
049
050/**
051 * Core Event Listener for updating DublinCore.
052 *
053 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a>
054 * @author <a href="mailto:rspivak@nuxeo.com">Ruslan Spivak</a>
055 */
056public class DublinCoreListener implements EventListener {
057
058    private static final Log log = LogFactory.getLog(DublinCoreListener.class);
059
060    public static final String DISABLE_DUBLINCORE_LISTENER = "disableDublinCoreListener";
061
062    private static final String RESET_CREATOR_PROPERTY = "nuxeo.dclistener.reset-creator-on-copy";
063
064    /**
065     * Core event notification.
066     * <p>
067     * Gets core events and updates DublinCore if needed.
068     *
069     * @param event event fired at core layer
070     */
071    @Override
072    public void handleEvent(Event event) {
073
074        DocumentEventContext docCtx;
075        if (event.getContext() instanceof DocumentEventContext) {
076            docCtx = (DocumentEventContext) event.getContext();
077        } else {
078            return;
079        }
080        String eventId = event.getName();
081
082        if (!eventId.equals(DOCUMENT_CREATED) && !eventId.equals(BEFORE_DOC_UPDATE)
083                && !eventId.equals(TRANSITION_EVENT) && !eventId.equals(DOCUMENT_PUBLISHED)
084                && !eventId.equals(DOCUMENT_CREATED_BY_COPY)) {
085            return;
086        }
087
088        DublinCoreStorageService service = NXDublinCore.getDublinCoreStorageService();
089        if (service == null) {
090            log.error("DublinCoreStorage service not found ... !");
091            return;
092        }
093
094        Boolean block = (Boolean) event.getContext().getProperty(DISABLE_DUBLINCORE_LISTENER);
095        if (Boolean.TRUE.equals(block)) {
096            // ignore the event - we are blocked by the caller
097            return;
098        }
099
100        DocumentModel doc = docCtx.getSourceDocument();
101
102        if (doc.isVersion()) {
103            log.debug("No DublinCore update on versions except for the issued date");
104            return;
105        }
106
107        if (doc.hasFacet(SYSTEM_DOCUMENT)) {
108            // ignore the event for System documents
109            return;
110        }
111
112        Date eventDate = new Date(event.getTime());
113        Calendar cEventDate = Calendar.getInstance();
114        cEventDate.setTime(eventDate);
115
116        if (doc.isProxy()) {
117            if (eventId.equals(DOCUMENT_PUBLISHED)) {
118                CoreSession session = event.getContext().getCoreSession();
119                UnrestrictedPropertySetter setter = new UnrestrictedPropertySetter(session, doc.getRef(), "dc:issued",
120                        cEventDate);
121                setter.runUnrestricted();
122            }
123            if (doc.isImmutable()) {
124                // proxies with attached schemas can be changed
125                // (and therefore saved), but they're still mostly
126                // immutable, so don't attempt to set modification dates
127                // on them
128                return;
129            }
130            // live proxies may be updated normally, except at creation time (don't update the live doc)
131            if (eventId.equals(DOCUMENT_CREATED)) {
132                return;
133            }
134        }
135
136        Boolean resetCreator = (Boolean) event.getContext().getProperty(CoreEventConstants.RESET_CREATOR);
137        boolean resetCreatorProperty = Framework.getService(ConfigurationService.class).isBooleanPropertyTrue(
138                RESET_CREATOR_PROPERTY);
139        Boolean dirty = (Boolean) event.getContext().getProperty(CoreEventConstants.DOCUMENT_DIRTY);
140        if ((eventId.equals(BEFORE_DOC_UPDATE) && Boolean.TRUE.equals(dirty))
141                || (eventId.equals(TRANSITION_EVENT) && !doc.isImmutable())) {
142            service.setModificationDate(doc, cEventDate, event);
143            service.addContributor(doc, event);
144        } else if (eventId.equals(DOCUMENT_CREATED)) {
145            service.setCreationDate(doc, cEventDate, event);
146            service.setModificationDate(doc, cEventDate, event);
147            service.addContributor(doc, event);
148        } else if (eventId.equals(DOCUMENT_CREATED_BY_COPY)
149                && (resetCreatorProperty || Boolean.TRUE.equals(resetCreator))) {
150            doc.setProperty("dublincore", "creator", null);
151            doc.setProperty("dublincore", "contributors", null);
152            service.setCreationDate(doc, cEventDate, event);
153            service.setModificationDate(doc, cEventDate, event);
154            service.addContributor(doc, event);
155        }
156    }
157
158    protected class UnrestrictedPropertySetter extends UnrestrictedSessionRunner {
159
160        DocumentRef docRef;
161
162        String xpath;
163
164        Serializable value;
165
166        protected UnrestrictedPropertySetter(CoreSession session, DocumentRef docRef, String xpath, Serializable value) {
167            super(session);
168            this.docRef = docRef;
169            this.xpath = xpath;
170            this.value = value;
171        }
172
173        @Override
174        public void run() {
175            DocumentModel doc = session.getSourceDocument(docRef);
176            if (doc != null) {
177                doc.setPropertyValue(xpath, value);
178                session.saveDocument(doc);
179            }
180
181        }
182
183    }
184
185}