/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.core.internal.event;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventRegistration;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.event.ICoreEventSupport;
public class CoreEventSupport implements ICoreEventSupport {
private static class CoreEventManager {
private Map<String, CoreEventRegistrationList> regs;
public void add(CoreEventRegistration reg) {
regs = addListener(reg.getEventType(), reg, regs);
}
private Map<String, CoreEventRegistrationList> addListener(String type,
CoreEventRegistration reg,
Map<String, CoreEventRegistrationList> map) {
if (map == null)
map = new HashMap<String, CoreEventRegistrationList>();
CoreEventRegistrationList list = map.get(type);
if (list == null) {
list = new CoreEventRegistrationList();
map.put(type, list);
}
list.add(reg);
return map;
}
public void remove(CoreEventRegistration reg) {
regs = removeListener(reg.getEventType(), reg, regs);
}
private Map<String, CoreEventRegistrationList> removeListener(
String type, CoreEventRegistration reg,
Map<String, CoreEventRegistrationList> map) {
if (map != null) {
CoreEventRegistrationList list = map.get(type);
if (list != null) {
list.remove(reg);
if (list.isEmpty()) {
map.remove(type);
}
}
if (map.isEmpty()) {
map = null;
}
}
return map;
}
public boolean isEmpty() {
return regs == null || regs.isEmpty();
}
public void dispatchCoreEvent(String type, CoreEvent event) {
if (regs != null) {
CoreEventRegistrationList list = regs.get(type);
if (list != null) {
if (list.hasOnceRegistration()) {
list.fireCoreEvent(event,
CoreEventRegistrationList.ONLY_ONCE);
} else {
list
.fireCoreEvent(event,
CoreEventRegistrationList.ALL);
}
}
}
}
public void dispatchCoreEvent(String type, CoreEvent event,
int eventGroup) {
dispatchCoreEvent(type, event, eventGroup, regs);
}
private Map<String, CoreEventRegistrationList> dispatchCoreEvent(
String type, CoreEvent event, int eventGroup,
Map<String, CoreEventRegistrationList> map) {
if (map != null) {
CoreEventRegistrationList list = map.get(type);
if (list != null) {
list.fireCoreEvent(event, eventGroup);
}
}
return map;
}
public boolean hasListeners(String type) {
return regs != null && regs.containsKey(type);
}
public boolean hasOnceListeners(String type) {
if (regs == null)
return false;
CoreEventRegistrationList list = regs.get(type);
return list != null && list.hasOnceRegistration();
}
}
private ICoreEventSupport parent;
private Map<ICoreEventSource, CoreEventManager> managers;
private CoreEventManager globalManager;
public ICoreEventSupport getParent() {
return parent;
}
public void setParent(ICoreEventSupport parent) {
this.parent = parent;
}
public ICoreEventRegistration registerCoreEventListener(
ICoreEventSource source, String eventType,
ICoreEventListener listener) {
return registerListener(source, eventType, listener, false);
}
private ICoreEventRegistration registerListener(ICoreEventSource source,
String eventType, ICoreEventListener listener, boolean once) {
CoreEventRegistration reg = new CoreEventRegistration(this, source,
eventType, listener, once);
if (managers == null)
managers = new HashMap<ICoreEventSource, CoreEventManager>();
CoreEventManager manager = managers.get(source);
if (manager == null) {
manager = new CoreEventManager();
managers.put(source, manager);
}
manager.add(reg);
return reg;
}
public ICoreEventRegistration registerGlobalListener(String eventType,
ICoreEventListener listener) {
return registerGlobalListener(eventType, listener, false);
}
private ICoreEventRegistration registerGlobalListener(String eventType,
ICoreEventListener listener, boolean once) {
CoreEventRegistration reg = new CoreEventRegistration(this, null,
eventType, listener, once);
if (globalManager == null)
globalManager = new CoreEventManager();
globalManager.add(reg);
return reg;
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.core.event.ICoreEventSupport#registerOnceCoreEventListener(
* org.xmind.core.event.ICoreEventSource, java.lang.String,
* org.xmind.core.event.ICoreEventListener)
*/
public ICoreEventRegistration registerOnceCoreEventListener(
ICoreEventSource source, String eventType,
ICoreEventListener listener) {
ICoreEventRegistration reg = registerListener(source, eventType,
listener, true);
dispatch(source, eventType, new CoreEvent(source, eventType, null,
listener), false);
return reg;
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.core.event.ICoreEventSupport#registerOnceGlobalListener(java
* .lang.String, org.xmind.core.event.ICoreEventListener)
*/
public ICoreEventRegistration registerOnceGlobalListener(String eventType,
ICoreEventListener listener) {
ICoreEventRegistration reg = registerGlobalListener(eventType,
listener, true);
if (managers != null) {
for (Entry<ICoreEventSource, CoreEventManager> entry : managers
.entrySet()) {
if (entry.getValue().hasListeners(eventType)) {
ICoreEventSource source = entry.getKey();
dispatch(source, eventType, new CoreEvent(source,
eventType, listener), false);
}
}
}
return reg;
}
protected void unregister(CoreEventRegistration reg) {
ICoreEventSource source = reg.getSource();
if (source == null) {
unregisterGlobalRegistration(reg);
return;
}
if (managers == null || managers.isEmpty())
return;
CoreEventManager manager = managers.get(source);
if (manager == null)
return;
manager.remove(reg);
if (manager.isEmpty()) {
managers.remove(source);
}
if (managers.isEmpty()) {
managers = null;
}
if (reg.isOnce()) {
String eventType = reg.getEventType();
ICoreEventListener listener = reg.getListener();
dispatch(source, eventType, new CoreEvent(source, eventType,
listener, null), false);
}
}
private void unregisterGlobalRegistration(CoreEventRegistration reg) {
if (globalManager != null) {
globalManager.remove(reg);
}
if (globalManager.isEmpty()) {
globalManager = null;
}
}
public void dispatchValueChange(ICoreEventSource source, String eventType,
Object oldValue, Object newValue) {
if (oldValue == newValue
|| (oldValue != null && oldValue.equals(newValue)))
return;
dispatch(source, eventType, new CoreEvent(source, eventType, oldValue,
newValue), true);
}
public void dispatchIndexedValueChange(ICoreEventSource source,
String eventType, Object oldValue, Object newValue, int index) {
if (oldValue == newValue
|| (oldValue != null && oldValue.equals(newValue)))
return;
dispatch(source, eventType, new CoreEvent(source, eventType, oldValue,
newValue, index), true);
}
public void dispatchIndexedTargetChange(ICoreEventSource source,
String eventType, Object target, int index) {
dispatch(source, eventType, new CoreEvent(source, eventType, target,
index), true);
}
public void dispatchTargetChange(ICoreEventSource source, String eventType,
Object target) {
dispatch(source, eventType, new CoreEvent(source, eventType, target),
true);
}
public void dispatchTargetValueChange(ICoreEventSource source,
String eventType, Object target, Object oldValue, Object newValue) {
dispatch(source, eventType, new CoreEvent(source, eventType, target,
oldValue, newValue), true);
}
public void dispatch(ICoreEventSource source, CoreEvent event) {
String eventType = event.getType();
dispatch(source, eventType, event, true);
}
private void dispatch(ICoreEventSource source, String eventType,
CoreEvent event, boolean notifyOnceListeners) {
dispatchBySource(source, eventType, event, notifyOnceListeners);
dispatchGlobal(eventType, event, notifyOnceListeners);
}
private void dispatchBySource(ICoreEventSource source, String eventType,
CoreEvent event, boolean notifyOnceListeners) {
if (managers == null || managers.isEmpty())
return;
CoreEventManager manager = managers.get(source);
if (manager == null || manager.isEmpty())
return;
if (notifyOnceListeners) {
manager.dispatchCoreEvent(eventType, event);
} else {
manager.dispatchCoreEvent(eventType, event,
CoreEventRegistrationList.ONLY_NORMAL);
}
}
private void dispatchGlobal(String eventType, CoreEvent event,
boolean notifyOnceListeners) {
if (globalManager != null) {
if (notifyOnceListeners) {
globalManager.dispatchCoreEvent(eventType, event);
} else {
globalManager.dispatchCoreEvent(eventType, event,
CoreEventRegistrationList.ONLY_NORMAL);
}
}
if (getParent() != null && getParent() instanceof CoreEventSupport) {
((CoreEventSupport) getParent()).dispatchGlobal(eventType, event,
notifyOnceListeners);
}
}
public void dispose() {
if (managers != null) {
managers.clear();
managers = null;
}
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.core.event.ICoreEventSupport#hasListeners(java.lang.String)
*/
public boolean hasListeners(ICoreEventSource source, String eventType) {
if (managers == null)
return false;
CoreEventManager manager = managers.get(source);
return manager != null && manager.hasListeners(eventType);
}
public boolean hasOnceListeners(ICoreEventSource source, String eventType) {
if (managers == null)
return false;
CoreEventManager manager = managers.get(source);
return manager != null && manager.hasOnceListeners(eventType);
}
}