/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.topicmaps.impl.utils;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.ontopia.topicmaps.core.AssociationIF;
import net.ontopia.topicmaps.core.AssociationRoleIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.core.TopicNameIF;
import net.ontopia.topicmaps.core.OccurrenceIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.VariantNameIF;
import net.ontopia.utils.CollectionFactoryIF;
/**
* INTERNAL: Event manager that fires object added and removed
* events for children of added or removed objects.</p>
*
* This class is itself an event listener that listens to the standard
* property change events fired by the object model. Objects that are
* added or removed are traversed and further events for the children
* of those objects are fired.</p>
*
* If your event listeners depends on knowing when objects are added
* or removed use this class instead of doing the traversal
* yourself.</p>
*/
public class ObjectTreeManager implements EventManagerIF, java.io.Serializable {
protected Map<String, EventHandler> handlers;
protected Map<String, Set<EventListenerIF>> listeners;
protected ObjectTreeManager otree;
protected CollectionFactoryIF cfactory;
public ObjectTreeManager(EventManagerIF emanager, CollectionFactoryIF cfactory) {
// Setup
this.cfactory = cfactory;
// Initialize listeners
listeners = cfactory.makeLargeMap();
// Initialize handlers map
handlers = cfactory.makeLargeMap();
// Initialize parent-child relationship event handlers
handlers.put(TopicMapIF.EVENT_ADD_TOPIC, new EH01());
handlers.put(TopicMapIF.EVENT_REMOVE_TOPIC, new EH02());
handlers.put(TopicMapIF.EVENT_ADD_ASSOCIATION, new EH03());
handlers.put(TopicMapIF.EVENT_REMOVE_ASSOCIATION, new EH04());
handlers.put(TopicIF.EVENT_ADD_TOPICNAME, new EH07());
handlers.put(TopicIF.EVENT_REMOVE_TOPICNAME, new EH08());
handlers.put(TopicNameIF.EVENT_ADD_VARIANT, new EH09());
handlers.put(TopicNameIF.EVENT_REMOVE_VARIANT, new EH10());
handlers.put(TopicIF.EVENT_ADD_OCCURRENCE, new EH13());
handlers.put(TopicIF.EVENT_REMOVE_OCCURRENCE, new EH14());
handlers.put(AssociationIF.EVENT_ADD_ROLE, new EH15());
handlers.put(AssociationIF.EVENT_REMOVE_ROLE, new EH16());
// Register as event listener
Iterator<String> iter = handlers.keySet().iterator();
while (iter.hasNext()) {
emanager.addListener(this, iter.next());
}
// Make this object available to nested classes.
otree = this;
}
// -----------------------------------------------------------------------------
// EventManagerIF implementation
// -----------------------------------------------------------------------------
public void addListener(EventListenerIF listener, String event) {
// Adding itself causes infinite loops.
if (listener == this) return;
// Initialize event entry
if (!listeners.containsKey(event)) {
Set<EventListenerIF> newset = cfactory.makeSmallSet();
listeners.put(event, newset);
}
// Add listener to event entry listeners collection
listeners.get(event).add(listener);
}
public void removeListener(EventListenerIF listener, String event) {
if (listeners.containsKey(event)) {
// Remove listener from event listeners collection
Set<EventListenerIF> event_listeners = listeners.get(event);
event_listeners.remove(listener);
// If there are no more listeners, remove event entry.
if (event_listeners.isEmpty()) listeners.remove(event);
}
}
// -----------------------------------------------------------------------------
// EventListenerIF
// -----------------------------------------------------------------------------
public void processEvent(Object object, String event, Object new_value, Object old_value) {
if (handlers.containsKey(event)) {
EventListenerIF handler = (EventListenerIF)handlers.get(event);
handler.processEvent(object, event, new_value, old_value);
}
}
// -----------------------------------------------------------------------------
// Event handlers
// -----------------------------------------------------------------------------
protected abstract class EventHandler implements EventListenerIF, java.io.Serializable {
public abstract void processEvent(Object object, String event, Object new_value, Object old_value);
/**
* Inform object tree event listeners about object tree add event.
*/
protected void treeAddEvent(Object parent, String event, Object added) {
if (listeners.containsKey(event)) {
// Loop over event listeners
Set<EventListenerIF> event_listeners = listeners.get(event);
Iterator<EventListenerIF> iter = event_listeners.iterator();
while (iter.hasNext()) {
// Notify listener
iter.next().processEvent(parent, event, added, null);
}
}
}
/**
* Inform object tree event listeners about object tree add event.
*/
protected void treeRemoveEvent(Object parent, String event, Object removed) {
if (listeners.containsKey(event)) {
// Loop over event listeners
Set<EventListenerIF> event_listeners = listeners.get(event);
Iterator<EventListenerIF> iter = event_listeners.iterator();
while (iter.hasNext()) {
// Notify listener
iter.next().processEvent(parent, event, null, removed);
}
}
}
}
/**
* EventHandler: TopicMapIF.addTopic
*/
class EH01 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF added = (TopicIF)new_value;
// Fire object added event
treeAddEvent(object, TopicIF.EVENT_ADDED, added);
// Add basenames
Object[] basenames = added.getTopicNames().toArray();
for (int i=0; i < basenames.length; i++)
otree.processEvent(added, TopicIF.EVENT_ADD_TOPICNAME, basenames[i], null);
// Add occurrences
Object[] occurs = added.getOccurrences().toArray();
for (int i=0; i < occurs.length; i++)
otree.processEvent(added, TopicIF.EVENT_ADD_OCCURRENCE, occurs[i], null);
}
}
/**
* EventHandler: TopicMapIF.removeTopic
*/
class EH02 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF removed = (TopicIF)old_value;
// Fire tree event
treeRemoveEvent(object, TopicIF.EVENT_REMOVED, removed);
// Remove basenames
Object[] basenames = removed.getTopicNames().toArray();
for (int i=0; i < basenames.length; i++)
otree.processEvent(removed, TopicIF.EVENT_REMOVE_TOPICNAME, null, basenames[i]);
// Remove occurrences
Object[] occurs = removed.getOccurrences().toArray();
for (int i=0; i < occurs.length; i++)
otree.processEvent(removed, TopicIF.EVENT_REMOVE_OCCURRENCE, null, occurs[i]);
}
}
/**
* EventHandler: TopicMapIF.addAssociation
*/
class EH03 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
AssociationIF added = (AssociationIF)new_value;
// Fire object added event
treeAddEvent(object, AssociationIF.EVENT_ADDED, added);
// Add association roles
Object[] roles = added.getRoles().toArray();
for (int i=0; i < roles.length; i++)
otree.processEvent(added, AssociationIF.EVENT_ADD_ROLE, roles[i], null);
}
}
/**
* EventHandler: TopicMapIF.removeAssociation
*/
class EH04 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
AssociationIF removed = (AssociationIF)old_value;
// Fire tree event
treeRemoveEvent(object, AssociationIF.EVENT_REMOVED, removed);
// Remove association roles
Object[] roles = removed.getRoles().toArray();
for (int i=0; i < roles.length; i++)
otree.processEvent(removed, AssociationIF.EVENT_REMOVE_ROLE, null, roles[i]);
}
}
/**
* EventHandler: TopicIF.addTopicName
*/
class EH07 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicNameIF added = (TopicNameIF)new_value;
// Fire object added event
treeAddEvent(object, TopicNameIF.EVENT_ADDED, added);
// Add variants
Object[] variants = added.getVariants().toArray();
for (int i=0; i < variants.length; i++)
otree.processEvent(added, TopicNameIF.EVENT_ADD_VARIANT, variants[i], null);
}
}
/**
* EventHandler: TopicIF.removeTopicName
*/
class EH08 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicNameIF removed = (TopicNameIF)old_value;
// Fire tree event
treeRemoveEvent(object, TopicNameIF.EVENT_REMOVED, removed);
// Remove variants
Object[] variants = removed.getVariants().toArray();
for (int i=0; i < variants.length; i++)
otree.processEvent(removed, TopicNameIF.EVENT_REMOVE_VARIANT, null, variants[i]);
}
}
/**
* EventHandler: TopicNameIF.addVariant
*/
class EH09 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
VariantNameIF added = (VariantNameIF)new_value;
// Fire object added event
treeAddEvent(object, VariantNameIF.EVENT_ADDED, added);
}
}
/**
* EventHandler: TopicNameIF.removeVariant
*/
class EH10 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
VariantNameIF removed = (VariantNameIF)old_value;
// Fire tree event
treeRemoveEvent(object, VariantNameIF.EVENT_REMOVED, removed);
}
}
/**
* EventHandler: TopicIF.addOccurrence
*/
class EH13 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
OccurrenceIF added = (OccurrenceIF)new_value;
// Fire object added event
treeAddEvent(object, OccurrenceIF.EVENT_ADDED, added);
}
}
/**
* EventHandler: TopicIF.removeOccurrence
*/
class EH14 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
OccurrenceIF removed = (OccurrenceIF)old_value;
// Fire tree event
treeRemoveEvent(object, OccurrenceIF.EVENT_REMOVED, removed);
}
}
/**
* EventHandler: AssociationIF.addRole
*/
class EH15 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
AssociationRoleIF added = (AssociationRoleIF)new_value;
// Fire object added event
treeAddEvent(object, AssociationRoleIF.EVENT_ADDED, added);
}
}
/**
* EventHandler: AssociationIF.removeRole
*/
class EH16 extends EventHandler {
public void processEvent(Object object, String event, Object new_value, Object old_value) {
AssociationRoleIF removed = (AssociationRoleIF)old_value;
// Fire tree event
treeRemoveEvent(object, AssociationRoleIF.EVENT_REMOVED, removed);
}
}
}