001    package de.deepamehta.core.impl;
002    
003    import de.deepamehta.core.service.Listener;
004    
005    import javax.ws.rs.WebApplicationException;
006    
007    import java.util.ArrayList;
008    import java.util.HashMap;
009    import java.util.List;
010    import java.util.Map;
011    
012    
013    
014    class EventManager {
015    
016        // ---------------------------------------------------------------------------------------------- Instance Variables
017    
018        /**
019         * The registered listeners, hashed by event name (name of CoreEvent enum constant, e.g. "POST_CREATE_TOPIC").
020         */
021        private Map<String, List<Listener>> listenerRegistry = new HashMap();
022    
023        // ----------------------------------------------------------------------------------------- Package Private Methods
024    
025        void addListener(CoreEvent event, Listener listener) {
026            List<Listener> listeners = getListeners(event);
027            if (listeners == null) {
028                listeners = new ArrayList();
029                putListeners(event, listeners);
030            }
031            listeners.add(listener);
032        }
033    
034        void removeListener(CoreEvent event, Listener listener) {
035            List<Listener> listeners = getListeners(event);
036            if (!listeners.remove(listener)) {
037                throw new RuntimeException("Removing " + listener + " from " +
038                    event + " listeners failed: not found in " + listeners);
039            }
040        }
041    
042        // ---
043    
044        void fireEvent(CoreEvent event, Object... params) {
045            List<Listener> listeners = getListeners(event);
046            if (listeners != null) {
047                // ### FIXME: ConcurrentModificationException might occur. Still true?
048                for (Listener listener : listeners) {
049                    deliverEvent(listener, event, params);
050                }
051            }
052        }
053    
054        void deliverEvent(Listener listener, CoreEvent event, Object... params) {
055            try {
056                event.deliver(listener, params);
057            } catch (WebApplicationException e) {
058                // Note: a WebApplicationException thrown by a event listener must reach Jersey. So we re-throw here.
059                // This allow plugins to produce specific HTTP responses by throwing a WebApplicationException.
060                // Consider the Caching plugin: it produces a possible 304 (Not Modified) response this way.
061                throw e;
062            } catch (Exception e) {
063                throw new RuntimeException("Processing event " + event + " by " + listener + " failed", e);
064            }
065        }
066    
067        // ------------------------------------------------------------------------------------------------- Private Methods
068    
069        private List<Listener> getListeners(CoreEvent event) {
070            return listenerRegistry.get(event.name());
071        }
072    
073        private void putListeners(CoreEvent event, List<Listener> listeners) {
074            listenerRegistry.put(event.name(), listeners);
075        }
076    }