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