001/*
002 * Copyright (c) 2006-2013 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 *     Nuxeo - initial API and implementation
011 *
012 * $Id$
013 */
014
015package org.nuxeo.ecm.core.event.impl;
016
017import java.util.ArrayList;
018import java.util.Collections;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.nuxeo.ecm.core.event.EventListener;
024import org.nuxeo.ecm.core.event.PostCommitEventListener;
025
026/**
027 * Utility class used to manage event listeners descriptors.
028 *
029 * @author Thierry Delprat
030 */
031public class EventListenerList {
032
033    protected final List<EventListenerDescriptor> inlineListenersDescriptors = new ArrayList<EventListenerDescriptor>();
034
035    protected final List<EventListenerDescriptor> syncPostCommitListenersDescriptors = new ArrayList<EventListenerDescriptor>();
036
037    protected final List<EventListenerDescriptor> asyncPostCommitListenersDescriptors = new ArrayList<EventListenerDescriptor>();
038
039    protected volatile List<EventListenerDescriptor> enabledInlineListenersDescriptors = null;
040
041    protected volatile List<EventListenerDescriptor> enabledSyncPostCommitListenersDescriptors = null;
042
043    protected volatile List<EventListenerDescriptor> enabledAsyncPostCommitListenersDescriptors = null;
044
045    protected final Map<String, EventListenerDescriptor> descriptors = new HashMap<String, EventListenerDescriptor>();
046
047    protected synchronized void flushCache() {
048        enabledAsyncPostCommitListenersDescriptors = null;
049        enabledInlineListenersDescriptors = null;
050        enabledSyncPostCommitListenersDescriptors = null;
051    }
052
053    public void add(EventListenerDescriptor descriptor) {
054
055        flushCache();
056        // merge if necessary
057        if (descriptors.containsKey(descriptor.getName())) {
058            descriptor = mergeDescriptor(descriptor);
059        }
060
061        // checkListener
062        descriptor.initListener();
063
064        if (descriptor.isPostCommit) {
065            if (descriptor.getIsAsync()) {
066                asyncPostCommitListenersDescriptors.add(descriptor);
067                Collections.sort(asyncPostCommitListenersDescriptors, new EventListenerDescriptorComparator());
068            } else {
069                syncPostCommitListenersDescriptors.add(descriptor);
070                Collections.sort(syncPostCommitListenersDescriptors, new EventListenerDescriptorComparator());
071            }
072
073        } else {
074            inlineListenersDescriptors.add(descriptor);
075            Collections.sort(inlineListenersDescriptors, new EventListenerDescriptorComparator());
076        }
077
078        descriptors.put(descriptor.getName(), descriptor);
079    }
080
081    protected EventListenerDescriptor mergeDescriptor(EventListenerDescriptor descriptor) {
082        EventListenerDescriptor existingDesc = getDescriptor(descriptor.getName());
083        removeDescriptor(existingDesc);
084        existingDesc.merge(descriptor);
085        return existingDesc;
086    }
087
088    public void removeDescriptor(EventListenerDescriptor descriptor) {
089        flushCache();
090        if (descriptors.containsKey(descriptor.getName())) {
091            if (descriptor.isPostCommit) {
092                if (descriptor.getIsAsync()) {
093                    asyncPostCommitListenersDescriptors.remove(descriptor);
094                } else {
095                    syncPostCommitListenersDescriptors.remove(descriptor);
096                }
097            } else {
098                inlineListenersDescriptors.remove(descriptor);
099            }
100            descriptors.remove(descriptor.getName());
101        }
102    }
103
104    public EventListenerDescriptor getDescriptor(String listenerName) {
105        return descriptors.get(listenerName);
106    }
107
108    public List<EventListener> getInLineListeners() {
109        List<EventListener> listeners = new ArrayList<EventListener>();
110        for (EventListenerDescriptor desc : getEnabledInlineListenersDescriptors()) {
111            listeners.add(desc.asEventListener());
112        }
113        return listeners;
114    }
115
116    public List<PostCommitEventListener> getSyncPostCommitListeners() {
117        List<PostCommitEventListener> listeners = new ArrayList<PostCommitEventListener>();
118        for (EventListenerDescriptor desc : getEnabledSyncPostCommitListenersDescriptors()) {
119            listeners.add(desc.asPostCommitListener());
120        }
121        return listeners;
122    }
123
124    public List<PostCommitEventListener> getAsyncPostCommitListeners() {
125        List<PostCommitEventListener> listeners = new ArrayList<PostCommitEventListener>();
126        for (EventListenerDescriptor desc : getEnabledAsyncPostCommitListenersDescriptors()) {
127            listeners.add(desc.asPostCommitListener());
128        }
129        return listeners;
130    }
131
132    public List<EventListenerDescriptor> getInlineListenersDescriptors() {
133        return inlineListenersDescriptors;
134    }
135
136    public List<EventListenerDescriptor> getSyncPostCommitListenersDescriptors() {
137        return syncPostCommitListenersDescriptors;
138    }
139
140    public List<EventListenerDescriptor> getAsyncPostCommitListenersDescriptors() {
141        return asyncPostCommitListenersDescriptors;
142    }
143
144    public synchronized void recomputeEnabledListeners() {
145        enabledAsyncPostCommitListenersDescriptors = new ArrayList<EventListenerDescriptor>();
146        for (EventListenerDescriptor desc : asyncPostCommitListenersDescriptors) {
147            if (desc.isEnabled) {
148                enabledAsyncPostCommitListenersDescriptors.add(desc);
149            }
150        }
151        enabledSyncPostCommitListenersDescriptors = new ArrayList<EventListenerDescriptor>();
152        for (EventListenerDescriptor desc : syncPostCommitListenersDescriptors) {
153            if (desc.isEnabled) {
154                enabledSyncPostCommitListenersDescriptors.add(desc);
155            }
156        }
157        enabledInlineListenersDescriptors = new ArrayList<EventListenerDescriptor>();
158        for (EventListenerDescriptor desc : inlineListenersDescriptors) {
159            if (desc.isEnabled) {
160                enabledInlineListenersDescriptors.add(desc);
161            }
162        }
163    }
164
165    public synchronized List<EventListenerDescriptor> getEnabledInlineListenersDescriptors() {
166        if (enabledInlineListenersDescriptors == null) {
167            recomputeEnabledListeners();
168        }
169        return new ArrayList<EventListenerDescriptor>(enabledInlineListenersDescriptors);
170    }
171
172    public synchronized List<EventListenerDescriptor> getEnabledSyncPostCommitListenersDescriptors() {
173        if (enabledSyncPostCommitListenersDescriptors == null) {
174            recomputeEnabledListeners();
175        }
176        return new ArrayList<EventListenerDescriptor>(enabledSyncPostCommitListenersDescriptors);
177    }
178
179    public synchronized List<EventListenerDescriptor> getEnabledAsyncPostCommitListenersDescriptors() {
180        if (enabledAsyncPostCommitListenersDescriptors == null) {
181            recomputeEnabledListeners();
182        }
183        return new ArrayList<EventListenerDescriptor>(enabledAsyncPostCommitListenersDescriptors);
184    }
185
186    public List<String> getListenerNames() {
187        return new ArrayList<String>(descriptors.keySet());
188    }
189
190    public boolean hasListener(String name) {
191        return descriptors.containsKey(name);
192    }
193
194}