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;
024
025import org.apache.commons.lang.StringUtils;
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.api.DocumentNotFoundException;
031import org.nuxeo.ecm.core.api.IdRef;
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    public static void notifyEvent(CoreSession coreSession, DocumentModel document, NuxeoPrincipal principal,
056            Task task, String eventId, Map<String, Serializable> properties, String comment, String category)
057            {
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, task);
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), e);
119            }
120        } else {
121            log.error(String.format("Could not resolve document for notification: "
122                    + "document is on repository '%s' and given session is on " + "repository '%s'", docRepo,
123                    coreSession.getRepositoryName()));
124        }
125
126        final Map<String, Serializable> eventProperties = new HashMap<String, Serializable>();
127        ArrayList<String> notificationRecipients = new ArrayList<String>();
128        notificationRecipients.add(task.getInitiator());
129        notificationRecipients.addAll(task.getActors());
130        eventProperties.put(NotificationConstants.RECIPIENTS_KEY, notificationRecipients);
131        if (extraEventProperties != null) {
132            eventProperties.putAll(extraEventProperties);
133        }
134        boolean taskEndedByDelegatedActor = task.getDelegatedActors() != null
135                && task.getDelegatedActors().contains(principal.getName());
136        for (DocumentModel doc : documents) {
137            notifyEvent(coreSession, doc, principal, task, eventName, eventProperties,
138                    comment, null);
139            if (taskEndedByDelegatedActor) {
140                notifyEvent(
141                        coreSession,
142                        doc,
143                        principal,
144                        task,
145                        eventName,
146                        eventProperties,
147                        String.format("Task ended by an delegated actor '%s' ", principal.getName())
148                                + (!StringUtils.isEmpty(comment) ? " with the following comment: " + comment : ""),
149                        null);
150            }
151        }
152    }
153
154    public static EventProducer getEventProducer() {
155        return Framework.getLocalService(EventProducer.class);
156    }
157}