/* * #! * 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; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Set; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.core.TopicNameIF; import net.ontopia.topicmaps.core.ConstraintViolationException; import net.ontopia.topicmaps.core.CrossTopicMapException; import net.ontopia.topicmaps.core.DuplicateReificationException; import net.ontopia.topicmaps.core.ReifiableIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.VariantNameIF; import net.ontopia.topicmaps.impl.utils.DeletionUtils; import net.ontopia.topicmaps.impl.utils.ObjectStrings; import net.ontopia.topicmaps.utils.PSI; import net.ontopia.utils.UniqueSet; /** * INTERNAL: The basic topic name implementation. */ public class TopicName extends TMObject implements TopicNameIF { static final long serialVersionUID = -7350019735868904034L; protected TopicIF reifier; protected String value; protected TopicIF type; protected UniqueSet<TopicIF> scope; protected Set<VariantNameIF> variants; TopicName(TopicMap tm) { super(tm); } // --------------------------------------------------------------------------- // NameIF implementation // --------------------------------------------------------------------------- public TopicIF getTopic() { return (TopicIF) parent; } /** * INTERNAL: Set the topic that the topic name belongs to. [parent] */ void setTopic(Topic parent) { // Validate topic map if (parent != null && parent.topicmap != this.topicmap) throw new ConstraintViolationException( "Cannot move objects across topic maps: " + this.topicmap + " and " + parent.topicmap); // (De)reference pooled sets if (scope != null) { if (parent == null) topicmap.setpool.dereference(scope); else scope = topicmap.setpool.get(scope); } // Set parent this.parent = parent; } public String getValue() { return value; } public void setValue(String value) { if (value == null) throw new NullPointerException("Topic name value must not be null."); // Notify listeners fireEvent(TopicNameIF.EVENT_SET_VALUE, value, getValue()); this.value = value; } public Collection<VariantNameIF> getVariants() { if (variants == null) return Collections.emptyList(); else return Collections.unmodifiableSet(variants); } void addVariant(VariantNameIF _variant) { VariantName variant = (VariantName) _variant; if (variant == null) throw new NullPointerException("null is not a valid argument."); // Check to see if variant is already a member of this topic name if (variant.parent == this) return; // Check if used elsewhere. if (variant.parent != null) throw new ConstraintViolationException("Moving objects is not allowed."); // Notify listeners fireEvent(TopicNameIF.EVENT_ADD_VARIANT, variant, null); // Set topic name property if (variants == null) variants = topicmap.cfactory.makeSmallSet(); variant.setTopicName(this); // Add variant to list of variants variants.add(variant); // Add inherited themes to variant name if (scope != null && !scope.isEmpty()) for (TopicIF theme : scope) variant._addTheme(theme, false); } void removeVariant(VariantNameIF _variant) { VariantName variant = (VariantName) _variant; if (variant == null) throw new NullPointerException("null is not a valid argument."); // Check to see if variant is not a member of this topic name if (variant.parent != this) return; // Notify listeners fireEvent(TopicNameIF.EVENT_REMOVE_VARIANT, null, variant); // Remove inherited themes from variant name if (scope != null && !scope.isEmpty()) for (TopicIF theme : scope) variant._removeTheme(theme, false); // Unset topic name property variant.setTopicName(null); // Remove variant from list of variants if (variants == null) return; variants.remove(variant); } public void remove() { if (parent != null) { DeletionUtils.removeDependencies(this); ((Topic) parent).removeTopicName(this); } } // --------------------------------------------------------------------------- // ScopedIF implementation // --------------------------------------------------------------------------- public Collection<TopicIF> getScope() { // Return scope defined on this object return (scope == null ? Collections.<TopicIF>emptyList() : scope); } public void addTheme(TopicIF theme) { if (theme == null) throw new NullPointerException("null is not a valid argument."); CrossTopicMapException.check(theme, this); // Notify listeners fireEvent(TopicNameIF.EVENT_ADD_THEME, theme, null); // Add theme to scope if (scope == null) { scope = topicmap.setpool.get(Collections.<TopicIF>emptySet()); } scope = topicmap.setpool.add(scope, theme, true); // add theme to variants if (variants != null && !variants.isEmpty()) { Iterator<VariantNameIF> iter = variants.iterator(); while (iter.hasNext()) { VariantName v = (VariantName) iter.next(); v._addTheme(theme, false); } } } public void removeTheme(TopicIF theme) { if (theme == null) throw new NullPointerException("null is not a valid argument."); CrossTopicMapException.check(theme, this); // Notify listeners fireEvent(TopicNameIF.EVENT_REMOVE_THEME, null, theme); // remove theme from variants if (variants != null && !variants.isEmpty()) { Iterator<VariantNameIF> iter = variants.iterator(); while (iter.hasNext()) { VariantName v = (VariantName) iter.next(); v._removeTheme(theme, false); } } // Remove theme from scope if (scope == null) return; scope = topicmap.setpool.remove(scope, theme, true); } // --------------------------------------------------------------------------- // TypedIF implementation // --------------------------------------------------------------------------- public TopicIF getType() { return type; } public void setType(TopicIF type) { if (type == null) { type = getDefaultNameType(); } else { CrossTopicMapException.check(type, this); } // Notify listeners fireEvent(TopicNameIF.EVENT_SET_TYPE, type, getType()); this.type = type; } private TopicIF getDefaultNameType() { TopicMapIF tm = getTopicMap(); TopicIF nameType = tm.getTopicBySubjectIdentifier(PSI.getSAMNameType()); if (nameType == null) { nameType = tm.getBuilder().makeTopic(); nameType.addSubjectIdentifier(PSI.getSAMNameType()); } return nameType; } // --------------------------------------------------------------------------- // ReifiableIF implementation // --------------------------------------------------------------------------- public TopicIF getReifier() { return reifier; } public void setReifier(TopicIF _reifier) { if (_reifier != null) CrossTopicMapException.check(_reifier, this); if (DuplicateReificationException.check(this, _reifier)) { return; } // Notify listeners Topic reifier = (Topic) _reifier; Topic oldReifier = (Topic) getReifier(); fireEvent(ReifiableIF.EVENT_SET_REIFIER, reifier, oldReifier); this.reifier = reifier; if (oldReifier != null) oldReifier.setReified(null); if (reifier != null) reifier.setReified(this); } // --------------------------------------------------------------------------- // Misc. methods // --------------------------------------------------------------------------- protected void fireEvent(String event, Object new_value, Object old_value) { if (parent == null || parent.parent == null) return; else topicmap.processEvent(this, event, new_value, old_value); } protected boolean isConnected() { if (parent != null && parent.parent != null) return true; else return false; } public String toString() { return ObjectStrings.toString("basic.TopicName", (TopicNameIF) this); } }