/* AWE - Amanzi Wireless Explorer * http://awe.amanzi.org * (C) 2008-2009, AmanziTel AB * * This library is provided under the terms of the Eclipse Public License * as described at http://www.eclipse.org/legal/epl-v10.html. Any use, * reproduction or distribution of the library constitutes recipient's * acceptance of this agreement. * * This library is distributed WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package org.amanzi.awe.ui.manager; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.amanzi.awe.ui.events.EventStatus; import org.amanzi.awe.ui.events.IEvent; import org.amanzi.awe.ui.events.impl.AWEStartedEvent; import org.amanzi.awe.ui.events.impl.AWEStoppedEvent; import org.amanzi.awe.ui.events.impl.DataUpdatedEvent; import org.amanzi.awe.ui.events.impl.InitialiseEvent; import org.amanzi.awe.ui.events.impl.ProjectNameChangedEvent; import org.amanzi.awe.ui.events.impl.RefreshMapEvent; import org.amanzi.awe.ui.events.impl.ShowElementsOnMap; import org.amanzi.awe.ui.events.impl.ShowGISOnMap; import org.amanzi.awe.ui.events.impl.ShowInViewEvent; import org.amanzi.awe.ui.listener.IAWEEventListenter; import org.amanzi.awe.ui.listener.IAWEEventListenter.Priority; import org.amanzi.awe.ui.util.ActionUtil; import org.amanzi.neo.dto.IDataElement; import org.amanzi.neo.models.IModel; import org.amanzi.neo.models.render.IGISModel; import org.amanzi.neo.models.render.IRenderableModel; import org.apache.log4j.Logger; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.geotools.geometry.jts.ReferencedEnvelope; /** * TODO Purpose of * <p> * </p> * * @author Nikolay Lagutko (nikolay.lagutko@amanzitel.com) * @since 1.0.0 */ public final class AWEEventManager { private static final Logger LOGGER = Logger.getLogger(AWEEventManager.class); private static class AWEEventManagerInstanceHandler { private static volatile AWEEventManager instance = new AWEEventManager(); } private static final String AWE_LISTENER_EXTENSION_POINT_ID = "org.amanzi.awe.ui.listeners"; private static final String EVENT_STATUS_CHILD = "eventStatus"; private static final String CLASS_ATTRIBUTE = "class"; private static final String STATUS_ATTRIBUTE = "status"; private static final IEvent AWE_STARTED_EVENT = new AWEStartedEvent(null); private static final IEvent AWE_STOPPED_EVENT = new AWEStoppedEvent(null); public static final IEvent DATA_UPDATED_EVENT = new DataUpdatedEvent(null); private static final IEvent INITIALISE_EVENT = new InitialiseEvent(null); private final Map<Priority, Map<EventStatus, Set<IAWEEventListenter>>> listeners = new HashMap<Priority, Map<EventStatus, Set<IAWEEventListenter>>>(); private final IExtensionRegistry registry; protected AWEEventManager() { this(Platform.getExtensionRegistry()); } protected AWEEventManager(final IExtensionRegistry registry) { this.registry = registry; initializeExtensionPointListeners(); } public static AWEEventManager getManager() { return AWEEventManagerInstanceHandler.instance; } public synchronized void addListener(final IAWEEventListenter listener, final EventStatus... statuses) { assert listener != null; assert statuses != null; Map<EventStatus, Set<IAWEEventListenter>> prioritizedListeners = listeners.get(listener.getPriority()); if (prioritizedListeners == null) { prioritizedListeners = new HashMap<EventStatus, Set<IAWEEventListenter>>(); listeners.put(listener.getPriority(), prioritizedListeners); } for (final EventStatus eventStatus : statuses) { Set<IAWEEventListenter> eventListeners = prioritizedListeners.get(eventStatus); if (eventListeners == null) { eventListeners = new HashSet<IAWEEventListenter>(); prioritizedListeners.put(eventStatus, eventListeners); } eventListeners.add(listener); } } public synchronized void removeListener(final IAWEEventListenter listener) { final Map<EventStatus, Set<IAWEEventListenter>> prioritizedListeners = listeners.get(listener.getPriority()); if (prioritizedListeners != null) { for (final Entry<EventStatus, Set<IAWEEventListenter>> listenerEntry : prioritizedListeners.entrySet()) { listenerEntry.getValue().remove(listener); } } } private void fireEvent(final IEvent event, final boolean inDisplay) { for (final Priority priority : Priority.getSortedPriorities()) { final Map<EventStatus, Set<IAWEEventListenter>> prioritizedListeners = listeners.get(priority); if (prioritizedListeners != null) { final Set<IAWEEventListenter> eventListeners = prioritizedListeners.get(event.getStatus()); if (eventListeners != null) { for (final IAWEEventListenter singleListener : eventListeners) { run(event, singleListener, inDisplay); } } } } } /** * @param event * @param singleListener * @param inDisplay */ private void run(final IEvent event, final IAWEEventListenter singleListener, final boolean inDisplay) { if ((event.getSource() != null) && event.getSource().equals(singleListener)) { return; } if (inDisplay) { runEventListener(event, singleListener); } else { runEvent(event, singleListener); } } private void runEvent(final IEvent event, final IAWEEventListenter listener) { final long before = System.currentTimeMillis(); if (!event.isStopped()) { listener.onEvent(event); } final long after = System.currentTimeMillis(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Event <" + event + "> was handled by <" + listener.getClass().getSimpleName() + "> during " + (after - before) + " ms."); } } private void runEventListener(final IEvent event, final IAWEEventListenter singleListener) { ActionUtil.getInstance().runTask(new Runnable() { @Override public void run() { runEvent(event, singleListener); } }, event.isAsync()); } public synchronized void fireAWEStartedEvent() { fireEvent(AWE_STARTED_EVENT, true); } public synchronized void fireAWEStoppedEvent() { fireEvent(AWE_STOPPED_EVENT, true); } public synchronized void fireProjectNameChangedEvent(final String newProjectName, final Object source) { fireEvent(new ProjectNameChangedEvent(newProjectName, source), false); } public synchronized void fireDataUpdatedEvent(final Object source) { fireEvent(new DataUpdatedEvent(source), true); } public synchronized void fireShowOnMapEvent(final IGISModel model, final Object source) { fireEvent(new ShowGISOnMap(model, source), true); } public synchronized void fireShowInViewEvent(final IModel model, final Object element, final Object source) { fireEvent(new ShowInViewEvent(model, element, source), true); } public synchronized void fireShowOnMapEvent(final IRenderableModel model, final Iterable<IDataElement> elements, final Object source) { fireEvent(new ShowElementsOnMap(model, elements, source), true); } public synchronized void fireShowOnMapEvent(final IRenderableModel model, final Iterable<IDataElement> elements, final ReferencedEnvelope bounds, final Object source) { fireEvent(new ShowElementsOnMap(model, elements, bounds, source), true); } public synchronized void fireRefreshMapEvent() { fireEvent(new RefreshMapEvent(), false); } public synchronized void fireInitialiseEvent() { fireEvent(INITIALISE_EVENT, true); } public synchronized void fireEventChain(final EventChain eventChain) { ActionUtil.getInstance().runTask(new Runnable() { @Override public void run() { for (final IEvent event : eventChain.getEvents()) { fireEvent(event, false); } } }, eventChain.isAsync()); } private void initializeExtensionPointListeners() { for (final IConfigurationElement listenerElement : registry.getConfigurationElementsFor(AWE_LISTENER_EXTENSION_POINT_ID)) { try { initializeListenerFromElement(listenerElement); } catch (final CoreException e) { LOGGER.error("Error on initialization Listener <" + listenerElement.getAttribute(CLASS_ATTRIBUTE) + ">", e); } catch (final ClassCastException e) { LOGGER.error("Class <" + listenerElement.getAttribute(CLASS_ATTRIBUTE) + "> is not a Listener class", e); } } } private void initializeListenerFromElement(final IConfigurationElement element) throws CoreException { final IAWEEventListenter listener = (IAWEEventListenter)element.createExecutableExtension(CLASS_ATTRIBUTE); final IConfigurationElement[] eventStatusElement = element.getChildren(EVENT_STATUS_CHILD); for (final IConfigurationElement singleEventStatus : eventStatusElement) { final EventStatus status = getEventStatusFromElement(singleEventStatus); if (status != null) { addListener(listener, status); } } } private EventStatus getEventStatusFromElement(final IConfigurationElement element) { final String statusName = element.getAttribute(STATUS_ATTRIBUTE); return EventStatus.valueOf(statusName); } protected Map<EventStatus, Set<IAWEEventListenter>> getListeners(final Priority priority) { return listeners.get(priority); } }