001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Antoine Taillefer
016 */
017package org.nuxeo.ecm.platform.task.core.service;
018
019import java.io.Serializable;
020import java.util.ArrayList;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024import org.apache.commons.lang.StringUtils;
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.nuxeo.ecm.core.api.CoreSession;
028import org.nuxeo.ecm.core.api.DocumentModel;
029import org.nuxeo.ecm.core.api.DocumentNotFoundException;
030import org.nuxeo.ecm.core.api.IdRef;
031import org.nuxeo.ecm.core.api.InstanceRef;
032import org.nuxeo.ecm.core.api.NuxeoPrincipal;
033import org.nuxeo.ecm.core.api.event.CoreEventConstants;
034import org.nuxeo.ecm.core.api.event.DocumentEventCategories;
035import org.nuxeo.ecm.core.event.Event;
036import org.nuxeo.ecm.core.event.EventContext;
037import org.nuxeo.ecm.core.event.EventProducer;
038import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
039import org.nuxeo.ecm.core.event.impl.EventContextImpl;
040import org.nuxeo.ecm.platform.ec.notification.NotificationConstants;
041import org.nuxeo.ecm.platform.task.Task;
042import org.nuxeo.ecm.platform.task.TaskEventNames;
043import org.nuxeo.ecm.platform.task.TaskService;
044import org.nuxeo.runtime.api.Framework;
045
046/**
047 * Helper for notifying task related events.
048 *
049 * @since 5.6
050 */
051public final class TaskEventNotificationHelper {
052
053    private final static Log log = LogFactory.getLog(TaskEventNotificationHelper.class);
054
055
056    public static void notifyEvent(CoreSession coreSession, DocumentModel document, NuxeoPrincipal principal, Task task,
057            String eventId, Map<String, Serializable> properties, String comment, String category) {
058        // Default category
059        if (category == null) {
060            category = DocumentEventCategories.EVENT_DOCUMENT_CATEGORY;
061        }
062        if (properties == null) {
063            properties = new HashMap<String, Serializable>();
064        }
065
066        EventContext eventContext = null;
067        if (document != null) {
068            properties.put(CoreEventConstants.REPOSITORY_NAME, document.getRepositoryName());
069            properties.put(CoreEventConstants.SESSION_ID, coreSession.getSessionId());
070            properties.put(CoreEventConstants.DOC_LIFE_CYCLE, document.getCurrentLifeCycleState());
071            eventContext = new DocumentEventContext(coreSession, principal, document);
072        } else {
073            eventContext = new EventContextImpl(coreSession, principal);
074        }
075        properties.put(DocumentEventContext.COMMENT_PROPERTY_KEY, comment);
076        properties.put(DocumentEventContext.CATEGORY_PROPERTY_KEY, category);
077        properties.put(TaskService.TASK_INSTANCE_EVENT_PROPERTIES_KEY, new InstanceRef(task.getDocument(), coreSession.getPrincipal()));
078        String disableNotif = task.getVariable(TaskEventNames.DISABLE_NOTIFICATION_SERVICE);
079        if (disableNotif != null && Boolean.TRUE.equals(Boolean.valueOf(disableNotif))) {
080            properties.put(TaskEventNames.DISABLE_NOTIFICATION_SERVICE, Boolean.TRUE);
081        }
082        eventContext.setProperties(properties);
083
084        Event event = eventContext.newEvent(eventId);
085        getEventProducer().fireEvent(event);
086    }
087
088    /**
089     * @since 7.2
090     */
091    public static void notifyTaskEnded(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment,
092            String eventName, Map<String, Serializable> extraEventProperties) {
093
094        // try to resolve document when notifying
095        DocumentModel document = null;
096
097        List<String> docIds = new ArrayList<String>();
098        docIds.addAll(task.getTargetDocumentsIds());
099        // handle compatibility with tasks created before 5.8
100        String docId = task.getTargetDocumentId();
101        if (!docIds.contains(docId)) {
102            docIds.add(docId);
103        }
104        // also handle compatibility with deprecated jbpm tasks
105        String docIdVar = task.getVariable(TaskService.VariableName.documentId.name());
106        if (!docIds.contains(docIdVar)) {
107            docIds.add(docIdVar);
108        }
109        String docRepo = task.getVariable(TaskService.VariableName.documentRepositoryName.name());
110        List<DocumentModel> documents = new ArrayList<DocumentModel>();
111        if (coreSession.getRepositoryName().equals(docRepo)) {
112            try {
113                for (String id : docIds) {
114                    document = coreSession.getDocument(new IdRef(id));
115                    documents.add(document);
116                }
117            } catch (DocumentNotFoundException e) {
118                log.error(String.format("Could not fetch document with id '%s:%s' for notification", docRepo, docId),
119                        e);
120            }
121        } else {
122            log.error(String.format(
123                    "Could not resolve document for notification: "
124                            + "document is on repository '%s' and given session is on " + "repository '%s'",
125                    docRepo, coreSession.getRepositoryName()));
126        }
127
128        final Map<String, Serializable> eventProperties = new HashMap<String, Serializable>();
129        ArrayList<String> notificationRecipients = new ArrayList<String>();
130        notificationRecipients.add(task.getInitiator());
131        notificationRecipients.addAll(task.getActors());
132        eventProperties.put(NotificationConstants.RECIPIENTS_KEY, notificationRecipients);
133        if (extraEventProperties != null) {
134            eventProperties.putAll(extraEventProperties);
135        }
136        boolean taskEndedByDelegatedActor = task.getDelegatedActors() != null
137                && task.getDelegatedActors().contains(principal.getName());
138        for (DocumentModel doc : documents) {
139            notifyEvent(coreSession, doc, principal, task, eventName, eventProperties, comment, null);
140            if (taskEndedByDelegatedActor) {
141                notifyEvent(coreSession, doc, principal, task, eventName, eventProperties,
142                        String.format("Task ended by an delegated actor '%s' ", principal.getName())
143                                + (!StringUtils.isEmpty(comment) ? " with the following comment: " + comment : ""),
144                        null);
145            }
146        }
147    }
148
149    public static EventProducer getEventProducer() {
150        return Framework.getLocalService(EventProducer.class);
151    }
152}