/* * #! * 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.TopicNameIF; import net.ontopia.topicmaps.core.OccurrenceIF; import net.ontopia.topicmaps.core.TMObjectIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.core.VariantNameIF; import net.ontopia.utils.CollectionFactoryIF; /** * INTERNAL: Event manager that fires TopicIF.modified events.</p> */ public class TopicModificationManager implements EventManagerIF, java.io.Serializable { protected Map<String, EventHandler> handlers; protected Map<String, Set<EventListenerIF>> listeners; protected TopicModificationManager manager; protected CollectionFactoryIF cfactory; protected TopicHandler th; protected TopicNameHandler bh; protected VariantNameHandler vh; protected OccurrenceHandler oh; protected AssociationRoleHandler rh; protected AssociationHandler ah; protected TopicMapHandler mh; public TopicModificationManager(EventManagerIF emanager, CollectionFactoryIF cfactory) { // Setup this.cfactory = cfactory; // Initialize listeners this.listeners = cfactory.makeLargeMap(); // Initialize handlers map this.handlers = cfactory.makeLargeMap(); // Initialize parent-child relationship event handlers this.th = new TopicHandler(); handlers.put(TopicIF.EVENT_ADD_SUBJECTLOCATOR, th); handlers.put(TopicIF.EVENT_REMOVE_SUBJECTLOCATOR, th); handlers.put(TopicIF.EVENT_ADD_SUBJECTIDENTIFIER, th); handlers.put(TopicIF.EVENT_REMOVE_SUBJECTIDENTIFIER, th); handlers.put(TopicIF.EVENT_ADD_TOPICNAME, th); handlers.put(TopicIF.EVENT_REMOVE_TOPICNAME, th); handlers.put(TopicIF.EVENT_ADD_OCCURRENCE, th); handlers.put(TopicIF.EVENT_REMOVE_OCCURRENCE, th); handlers.put("TopicIF.addTheme", th); handlers.put("TopicIF.removeTheme", th); handlers.put(TopicIF.EVENT_ADD_TYPE, th); handlers.put(TopicIF.EVENT_REMOVE_TYPE, th); this.bh = new TopicNameHandler(); handlers.put(TopicNameIF.EVENT_SET_VALUE, bh); handlers.put(TopicNameIF.EVENT_ADD_VARIANT, bh); handlers.put(TopicNameIF.EVENT_REMOVE_VARIANT, bh); handlers.put(TopicNameIF.EVENT_ADD_THEME, bh); handlers.put(TopicNameIF.EVENT_REMOVE_THEME, bh); handlers.put(TopicNameIF.EVENT_SET_TYPE, bh); this.vh = new VariantNameHandler(); handlers.put(VariantNameIF.EVENT_SET_VALUE, vh); handlers.put(VariantNameIF.EVENT_ADD_THEME, vh); handlers.put(VariantNameIF.EVENT_REMOVE_THEME, vh); this.oh = new OccurrenceHandler(); handlers.put(OccurrenceIF.EVENT_SET_VALUE, oh); handlers.put(OccurrenceIF.EVENT_ADD_THEME, oh); handlers.put(OccurrenceIF.EVENT_REMOVE_THEME, oh); handlers.put(OccurrenceIF.EVENT_SET_TYPE, oh); this.ah = new AssociationHandler(); handlers.put(AssociationIF.EVENT_ADD_ROLE, ah); handlers.put(AssociationIF.EVENT_REMOVE_ROLE, ah); handlers.put(AssociationIF.EVENT_ADD_THEME, ah); handlers.put(AssociationIF.EVENT_REMOVE_THEME, ah); handlers.put(AssociationIF.EVENT_SET_TYPE, ah); this.rh = new AssociationRoleHandler(); handlers.put(AssociationRoleIF.EVENT_SET_PLAYER, rh); handlers.put(AssociationRoleIF.EVENT_SET_TYPE, rh); this.mh = new TopicMapHandler(); handlers.put(TopicMapIF.EVENT_REMOVE_ASSOCIATION, mh); TMObjectHandler xh = new TMObjectHandler(); handlers.put(TMObjectIF.EVENT_ADD_ITEMIDENTIFIER, xh); handlers.put(TMObjectIF.EVENT_REMOVE_ITEMIDENTIFIER, xh); // 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. manager = 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 = 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 topicModified(TopicIF topic) { String event = TopicIF.EVENT_MODIFIED; 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(topic, event, null, null); } } } } /** * EventHandler: Topic.* */ class TopicHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { TopicIF topic = (TopicIF)object; topicModified(topic); } } /** * EventHandler: TopicName.* */ class TopicNameHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { TopicNameIF bn = (TopicNameIF)object; TopicIF topic = bn.getTopic(); if (topic != null) topicModified(topic); } } /** * EventHandler: VariantName.* */ class VariantNameHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { VariantNameIF vn = (VariantNameIF)object; TopicNameIF bn = vn.getTopicName(); if (bn != null) { TopicIF topic = bn.getTopic(); if (topic != null) topicModified(topic); } } } /** * EventHandler: Occurrence.* */ class OccurrenceHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { OccurrenceIF occ = (OccurrenceIF)object; TopicIF topic = occ.getTopic(); if (topic != null) topicModified(topic); } } /** * EventHandler: AssociationRole.* */ class AssociationRoleHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { AssociationRoleIF role = (AssociationRoleIF)object; AssociationIF assoc = role.getAssociation(); if (event.equals(AssociationRoleIF.EVENT_SET_PLAYER)) { if (old_value != null) topicModified((TopicIF)old_value); if (new_value != null) topicModified((TopicIF)new_value); } else { TopicIF topic = role.getPlayer(); if (topic != null) topicModified(topic); } if (assoc != null) { Iterator<AssociationRoleIF> iter = assoc.getRoles().iterator(); while (iter.hasNext()) { AssociationRoleIF orole = iter.next(); if (!orole.equals(role)) { TopicIF otopic = orole.getPlayer(); if (otopic != null) topicModified(otopic); } } } } } /** * EventHandler: Association.* */ class AssociationHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { AssociationIF assoc = (AssociationIF)object; Iterator<AssociationRoleIF> iter = assoc.getRoles().iterator(); while (iter.hasNext()) { AssociationRoleIF role = iter.next(); TopicIF topic = role.getPlayer(); if (topic != null) topicModified(topic); } } } /** * EventHandler: TopicMap.* */ class TopicMapHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { if (event.equals(TopicMapIF.EVENT_REMOVE_ASSOCIATION)) { AssociationIF assoc = (AssociationIF)old_value; Iterator<AssociationRoleIF> iter = assoc.getRoles().iterator(); while (iter.hasNext()) { AssociationRoleIF role = iter.next(); TopicIF topic = role.getPlayer(); if (topic != null) topicModified(topic); } } } } /** * EventHandler: TMObjectIF.* */ class TMObjectHandler extends EventHandler { public void processEvent(Object object, String event, Object new_value, Object old_value) { if (object instanceof TopicNameIF) manager.bh.processEvent(object, event, new_value, old_value); else if (object instanceof VariantNameIF) manager.vh.processEvent(object, event, new_value, old_value); else if (object instanceof OccurrenceIF) manager.oh.processEvent(object, event, new_value, old_value); else if (object instanceof AssociationRoleIF) manager.rh.processEvent(object, event, new_value, old_value); else if (object instanceof AssociationIF) manager.ah.processEvent(object, event, new_value, old_value); else if (object instanceof TopicIF) manager.th.processEvent(object, event, new_value, old_value); else if (object instanceof TopicMapIF) manager.mh.processEvent(object, event, new_value, old_value); } } }