package org.ovirt.engine.ui.uicompat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; /** * <p> * The main Event class in uicommon's eventing infrastructure. Note that this is * completely separate from GWT's eventing infrastructure, GwtEvent, etc. * </p> * <p> * Encapsulates an event that occurs to an object -- usually a Model object. The * event can be anything, but is typically a property value change. * </p> * <p> * Event uses a simple publish-subscribe model. Create an Event, and set it as a * Model field. Subscribe to the Event by calling addListener() (usually do this * from a Presenter or View). Event keeps the subscribers in a simple List. * Fire the event (probably in a Model setter) when your event condition occurs * (for example, a Model property is changed) by calling Event.raise(). raise() * publishes the event to all those who subscribed via addListener(); * </p> */ public class Event<T extends EventArgs> { private List<IEventListener<? super T>> listeners; private Map<IEventListener<? super T>, Object> contexts; private Class<?> privateOwnerType; public Class<?> getOwnerType() { return privateOwnerType; } private void setOwnerType(Class<?> value) { privateOwnerType = value; } private String privateName; public String getName() { return privateName; } private void setName(String value) { privateName = value; } /** * Gets an object representing current event context. Specified when add listener. */ private Object privateContext; public Object getContext() { return privateContext; } private void setContext(Object value) { privateContext = value; } public Event(String name, Class<?> ownerType) { setName(name); setOwnerType(ownerType); listeners = new ArrayList<>(); contexts = new HashMap<>(); } public Event() { } public Event(EventDefinition definition) { this(definition.getName(), definition.getOwnerType()); } /** * Add listener with no context specified. */ public void addListener(IEventListener<? super T> listener) { listeners.add(listener); } /** * Subscribe to this Event. Subscriber will have eventRaised() called back when the event is published. */ public void addListener(IEventListener<? super T> listener, Object context) { listeners.add(listener); contexts.put(listener, context); } public void removeListener(IEventListener<? super T> listener) { listeners.remove(listener); if (contexts.containsKey(listener)) { contexts.remove(listener); } } /** * Raise (publish) the event. This simply calls eventRaised() on all those who subscribed via addListener(); */ public void raise(Object sender, T e) { // Iterate on a new instance of listeners list, // to enable listener unsubscribe from event // as a result on event firing. ArrayList<IEventListener<? super T>> list = new ArrayList<>(); for (IEventListener<? super T> listener : listeners) { list.add(listener); } for (IEventListener<? super T> listener : list) { //Update current context. setContext(contexts.containsKey(listener) ? contexts.get(listener) : null); listener.eventRaised(this, sender, e); } } @Override public int hashCode() { return Objects.hash( privateName, privateOwnerType ); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof Event)) { return false; } Event<?> other = (Event<?>) obj; return Objects.equals(privateName, other.privateName) && Objects.equals(privateOwnerType, other.privateOwnerType); } public boolean matchesDefinition(EventDefinition other) { if(other == null){ return false; } return getName().equals(other.getName()) && getOwnerType() == other.getOwnerType(); } public List<IEventListener<? super T>> getListeners() { return listeners; } public void clearListeners() { listeners.clear(); contexts.clear(); } public void setListeners(List<IEventListener<? super T>> listeners) { this.listeners = listeners; } }