/*
* #!
* 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.basic.index;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import net.ontopia.topicmaps.core.AssociationIF;
import net.ontopia.topicmaps.core.AssociationRoleIF;
import net.ontopia.topicmaps.core.OccurrenceIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.core.TopicNameIF;
import net.ontopia.topicmaps.core.TypedIF;
import net.ontopia.topicmaps.core.index.ClassInstanceIndexIF;
import net.ontopia.topicmaps.impl.utils.BasicIndex;
import net.ontopia.topicmaps.impl.utils.EventManagerIF;
import net.ontopia.topicmaps.impl.utils.IndexManagerIF;
import net.ontopia.topicmaps.impl.utils.ObjectTreeManager;
import net.ontopia.topicmaps.utils.PSI;
import net.ontopia.utils.CollectionMap;
/**
* INTERNAL: The basic dynamic class instance index implementation.
*/
public class ClassInstanceIndex extends BasicIndex implements ClassInstanceIndexIF {
protected CollectionMap<TopicIF, TopicIF> topics;
protected CollectionMap<TopicIF, TopicNameIF> bnames;
protected CollectionMap<TopicIF, OccurrenceIF> occurs;
protected CollectionMap<TopicIF, AssociationIF> assocs;
protected CollectionMap<TopicIF, AssociationRoleIF> roles;
protected final TopicMapIF topicmap;
ClassInstanceIndex(IndexManagerIF imanager, EventManagerIF emanager, ObjectTreeManager otree) {
// Initialize index maps
topics = new CollectionMap<TopicIF, TopicIF>();
bnames = new CollectionMap<TopicIF, TopicNameIF>();
occurs = new CollectionMap<TopicIF, OccurrenceIF>();
assocs = new CollectionMap<TopicIF, AssociationIF>();
roles = new CollectionMap<TopicIF, AssociationRoleIF>();
this.topicmap = imanager.getTransaction().getTopicMap();
// Initialize object tree event handlers [objects added or removed]
otree.addListener(new TopicIF_added(topics, TopicIF.EVENT_ADD_TYPE), TopicIF.EVENT_ADDED);
otree.addListener(new TopicIF_removed(topics, TopicIF.EVENT_REMOVE_TYPE), TopicIF.EVENT_REMOVED);
otree.addListener(new TypedIF_added(assocs), AssociationIF.EVENT_ADDED);
otree.addListener(new TypedIF_removed(assocs), AssociationIF.EVENT_REMOVED);
otree.addListener(new TypedIF_added(bnames), TopicNameIF.EVENT_ADDED);
otree.addListener(new TypedIF_removed(bnames), TopicNameIF.EVENT_REMOVED);
otree.addListener(new TypedIF_added(occurs), OccurrenceIF.EVENT_ADDED);
otree.addListener(new TypedIF_removed(occurs), OccurrenceIF.EVENT_REMOVED);
otree.addListener(new TypedIF_added(roles), AssociationRoleIF.EVENT_ADDED);
otree.addListener(new TypedIF_removed(roles), AssociationRoleIF.EVENT_REMOVED);
// Initialize object property event handlers
handlers.put(TopicIF.EVENT_ADD_TYPE, new TopicIF_addType(topics));
handlers.put(TopicIF.EVENT_REMOVE_TYPE, new TopicIF_removeType(topics));
handlers.put(TopicNameIF.EVENT_SET_TYPE, new TypedIF_setType(bnames));
handlers.put(OccurrenceIF.EVENT_SET_TYPE, new TypedIF_setType(occurs));
handlers.put(AssociationRoleIF.EVENT_SET_TYPE, new TypedIF_setType(roles));
handlers.put(AssociationIF.EVENT_SET_TYPE, new TypedIF_setType(assocs));
// Register dynamic index as event listener
for (String handler : handlers.keySet()) {
emanager.addListener(this, handler);
}
}
// -----------------------------------------------------------------------------
// ClassInstanceIndexIF
// -----------------------------------------------------------------------------
public Collection<TopicIF> getTopics(TopicIF topic_type) {
return topics.containsKey(topic_type) ?
Collections.<TopicIF>unmodifiableCollection(
new ArrayList<TopicIF>(topics.get(topic_type))) :
Collections.<TopicIF>emptyList();
}
public Collection<TopicNameIF> getTopicNames(TopicIF basename_type) {
if (basename_type == null) {
basename_type = topicmap.getTopicBySubjectIdentifier(PSI.getSAMNameType());
}
return bnames.containsKey(basename_type) ?
Collections.<TopicNameIF>unmodifiableCollection(
new ArrayList<TopicNameIF>(bnames.get(basename_type))) :
Collections.<TopicNameIF>emptyList();
}
public Collection<OccurrenceIF> getOccurrences(TopicIF occurrence_type) {
return occurs.containsKey(occurrence_type) ?
Collections.<OccurrenceIF>unmodifiableCollection(
new ArrayList<OccurrenceIF>(occurs.get(occurrence_type))) :
Collections.<OccurrenceIF>emptyList();
}
public Collection<AssociationIF> getAssociations(TopicIF association_type) {
return assocs.containsKey(association_type) ?
Collections.<AssociationIF>unmodifiableCollection(
new ArrayList<AssociationIF>(assocs.get(association_type))) :
Collections.<AssociationIF>emptyList();
}
public Collection<AssociationRoleIF> getAssociationRoles(TopicIF association_role_type) {
return roles.containsKey(association_role_type) ?
Collections.<AssociationRoleIF>unmodifiableCollection(
new ArrayList<AssociationRoleIF>(roles.get(association_role_type))) :
Collections.<AssociationRoleIF>emptyList();
}
public Collection<TopicIF> getTopicTypes() {
// Create new collection
Collection<TopicIF> result = new ArrayList<TopicIF>(topics.keySet());
result.remove(null);
return Collections.unmodifiableCollection(result);
}
public Collection<TopicIF> getTopicNameTypes() {
// Create new collection
Collection<TopicIF> result = new ArrayList<TopicIF>(bnames.keySet());
result.remove(null);
return Collections.unmodifiableCollection(result);
}
public Collection<TopicIF> getOccurrenceTypes() {
// Create new collection
Collection<TopicIF> result = new ArrayList<TopicIF>(occurs.keySet());
result.remove(null);
return Collections.unmodifiableCollection(result);
}
public Collection<TopicIF> getAssociationTypes() {
// Create new collection
Collection<TopicIF> result = new ArrayList<TopicIF>(assocs.keySet());
result.remove(null);
return Collections.unmodifiableCollection(result);
}
public Collection<TopicIF> getAssociationRoleTypes() {
// Create new collection
Collection<TopicIF> result = new ArrayList<TopicIF>(roles.keySet());
result.remove(null);
return Collections.unmodifiableCollection(result);
}
public boolean usedAsTopicType(TopicIF topic) {
return topics.containsKey(topic);
}
public boolean usedAsTopicNameType(TopicIF topic) {
return bnames.containsKey(topic);
}
public boolean usedAsOccurrenceType(TopicIF topic) {
return occurs.containsKey(topic);
}
public boolean usedAsAssociationType(TopicIF topic) {
return assocs.containsKey(topic);
}
public boolean usedAsAssociationRoleType(TopicIF topic) {
return roles.containsKey(topic);
}
public boolean usedAsType(TopicIF topic) {
return (topics.containsKey(topic) ||
occurs.containsKey(topic) ||
assocs.containsKey(topic) ||
roles.containsKey(topic) ||
bnames.containsKey(topic));
}
// -----------------------------------------------------------------------------
// Event handlers
// -----------------------------------------------------------------------------
/**
* EventHandler: TypedIF.setType
*/
class TypedIF_setType extends EventHandler {
protected CollectionMap objects;
TypedIF_setType(CollectionMap objects) {
this.objects = objects;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
objects.move(object, old_value, new_value);
}
}
/**
* EventHandler: TopicIF.addType
*/
class TopicIF_addType extends EventHandler {
protected CollectionMap objects;
TopicIF_addType(CollectionMap objects) {
this.objects = objects;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF topic = (TopicIF)object;
// Register types
Collection types = topic.getTypes();
if (types.isEmpty())
// Unregister null type
objects.remove(null, topic);
// Register type
objects.add(new_value, topic);
}
}
/**
* EventHandler: TopicIF.removeType
*/
class TopicIF_removeType extends EventHandler {
protected CollectionMap objects;
TopicIF_removeType(CollectionMap objects) {
this.objects = objects;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF topic = (TopicIF)object;
// Register types
Collection types = topic.getTypes();
if (types.size() == 1 && types.contains(old_value))
// Unregister null type
objects.add(null, topic);
// Unregister type
objects.remove(old_value, topic);
}
}
/**
* EventHandler: TopicIF.added
*/
class TopicIF_added extends EventHandler {
protected CollectionMap objects;
protected String child_event;
TopicIF_added(CollectionMap objects, String child_event) {
this.objects = objects;
this.child_event = child_event;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF added = (TopicIF)new_value;
// Register types
Collection types = added.getTypes();
if (types.isEmpty())
// Register the null type
objects.add(null, added);
else {
Object[] _types = types.toArray();
for (int i=0; i < _types.length; i++)
addEvent(added, child_event, _types[i]);
}
}
}
/**
* EventHandler: TopicIF.removed
*/
class TopicIF_removed extends EventHandler {
protected CollectionMap objects;
protected String child_event;
TopicIF_removed(CollectionMap objects, String child_event) {
this.objects = objects;
this.child_event = child_event;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TopicIF removed = (TopicIF)old_value;
// Unregister types
Collection types = removed.getTypes();
if (!types.isEmpty()) {
Object[] _types = types.toArray();
for (int i=0; i < _types.length; i++)
removeEvent(removed, child_event, _types[i]);
}
// Unregister null type
objects.remove(null, removed);
}
}
/**
* EventHandler: TypedIF.added
*/
class TypedIF_added extends EventHandler {
protected CollectionMap objects;
TypedIF_added(CollectionMap objects) {
this.objects = objects;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TypedIF added = (TypedIF)new_value;
// Register type
objects.add(added.getType(), added);
}
}
/**
* EventHandler: TypedIF.removed
*/
class TypedIF_removed extends EventHandler {
protected CollectionMap objects;
TypedIF_removed(CollectionMap objects) {
this.objects = objects;
}
public void processEvent(Object object, String event, Object new_value, Object old_value) {
TypedIF removed = (TypedIF)old_value;
// Unregister type
objects.remove(removed.getType(), removed);
}
}
}