001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.automation.core.events;
013
014import java.util.List;
015import java.util.Set;
016
017import org.apache.commons.logging.Log;
018import org.apache.commons.logging.LogFactory;
019import org.nuxeo.ecm.automation.AutomationService;
020import org.nuxeo.ecm.automation.OperationContext;
021import org.nuxeo.ecm.automation.OperationException;
022import org.nuxeo.ecm.core.api.NuxeoException;
023import org.nuxeo.ecm.core.event.Event;
024import org.nuxeo.ecm.core.event.EventContext;
025import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
026
027/**
028 * TODO: This service should be moved in another project, and renamed since it's a service, not a simple registry...
029 *
030 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
031 */
032public class EventHandlerRegistry {
033
034    private static final Log log = LogFactory.getLog(OperationEventListener.class);
035
036    protected final AutomationService svc;
037
038    protected EventRegistry handlers;
039
040    protected EventRegistry pchandlers;
041
042    public EventHandlerRegistry(AutomationService svc) {
043        this.svc = svc;
044        handlers = new EventRegistry();
045        pchandlers = new EventRegistry();
046    }
047
048    public List<EventHandler> getEventHandlers(String eventId) {
049        return handlers.lookup().get(eventId);
050    }
051
052    public List<EventHandler> getPostCommitEventHandlers(String eventId) {
053        return pchandlers.lookup().get(eventId);
054    }
055
056    public void putEventHandler(EventHandler handler) {
057        handlers.addContribution(handler);
058    }
059
060    public synchronized void putPostCommitEventHandler(EventHandler handler) {
061        pchandlers.addContribution(handler);
062    }
063
064    public synchronized void removePostCommitEventHandler(EventHandler handler) {
065        pchandlers.removeContribution(handler);
066    }
067
068    public synchronized void removeEventHandler(EventHandler handler) {
069        handlers.removeContribution(handler);
070    }
071
072    public synchronized void clear() {
073        handlers = new EventRegistry();
074        pchandlers = new EventRegistry();
075    }
076
077    public Set<String> getPostCommitEventNames() {
078        return pchandlers.lookup().keySet();
079    }
080
081    public boolean acceptEvent(Event event, List<EventHandler> handlers) {
082        if (handlers == null || handlers.isEmpty()) {
083            return false;
084        }
085        EventContext ectx = event.getContext();
086        OperationContext ctx;
087        if (ectx instanceof DocumentEventContext) {
088            ctx = new OperationContext(ectx.getCoreSession());
089            ctx.setInput(((DocumentEventContext) ectx).getSourceDocument());
090        } else {
091            ctx = new OperationContext();
092        }
093        ctx.put("Event", event);
094        for (EventHandler handler : handlers) {
095            if (handler.isEnabled(ctx, ectx, true)) {
096                return true;
097            }
098        }
099        return false;
100    }
101
102    // TODO: impl remove handlers method? or should refactor runtime to be able
103    // to redeploy only using clear() method
104
105    public void handleEvent(Event event, List<EventHandler> handlers, boolean saveSession) {
106        if (handlers == null || handlers.isEmpty()) {
107            return; // ignore
108        }
109
110        EventContext ectx = event.getContext();
111        OperationContext ctx = null;
112        for (EventHandler handler : handlers) {
113            if (ectx instanceof DocumentEventContext) {
114                ctx = new OperationContext(ectx.getCoreSession());
115                ctx.setInput(((DocumentEventContext) ectx).getSourceDocument());
116            } else { // not a document event .. the chain must begin with void
117                // operation - session is not available.
118                ctx = new OperationContext();
119            }
120            ctx.put("Event", event);
121            ctx.setCommit(saveSession); // avoid reentrant events
122            try {
123                if (handler.isEnabled(ctx, ectx, false)) {
124                    // TODO this will save the session at each iteration!
125                    svc.run(ctx, handler.getChainId());
126                }
127            } catch (NuxeoException | OperationException e) {
128                log.error("Failed to handle event " + event.getName() + " using chain: " + handler.getChainId(), e);
129            }
130        }
131    }
132
133}