/* * #! * 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.io.Reader; import java.io.StringReader; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.Set; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.core.ConstraintViolationException; import net.ontopia.topicmaps.core.CrossTopicMapException; import net.ontopia.topicmaps.core.DataTypes; import net.ontopia.topicmaps.core.DuplicateReificationException; import net.ontopia.topicmaps.core.OccurrenceIF; import net.ontopia.topicmaps.core.ReifiableIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.impl.utils.DeletionUtils; import net.ontopia.topicmaps.impl.utils.ObjectStrings; import net.ontopia.topicmaps.impl.utils.LocatorInterningTable; import net.ontopia.utils.UniqueSet; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.StreamUtils; /** * INTERNAL: The basic occurrence implementation. */ public class Occurrence extends TMObject implements OccurrenceIF { static final long serialVersionUID = -7364980697913079915L; protected TopicIF reifier; protected TopicIF type; protected UniqueSet<TopicIF> scope; protected String value; protected LocatorIF datatype; Occurrence(TopicMap tm) { super(tm); } // ----------------------------------------------------------------------------- // OccurrenceIF implementation // ----------------------------------------------------------------------------- public void remove() { if (parent != null) { DeletionUtils.removeDependencies(this); ((Topic)parent).removeOccurrence(this); } } public TopicIF getTopic() { return (TopicIF)parent; } /** * INTERNAL: Set the topic that the occurrence 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 topic this.parent = parent; } public LocatorIF getDataType() { return datatype; } protected void setDataType(LocatorIF datatype) { // Notify listeners fireEvent(OccurrenceIF.EVENT_SET_DATATYPE, value, getDataType()); this.datatype = LocatorInterningTable.intern(datatype); } public String getValue() { return value; } public void setValue(String value) { setValue(value, DataTypes.TYPE_STRING); } public void setValue(String value, LocatorIF datatype) { if (value == null) throw new NullPointerException("Occurrence value must not be null."); if (datatype == null) throw new NullPointerException("Occurrence value datatype must not be null."); if (!"URI".equals(datatype.getNotation())) throw new ConstraintViolationException("Only datatypes with notation 'URI' are supported: " + datatype); setDataType(datatype); // Notify listeners fireEvent(OccurrenceIF.EVENT_SET_VALUE, value, getValue()); this.value = value; } public Reader getReader() { return (value == null ? null : new StringReader(value)); } //! Public InputStream getInputStream() { //! try { //! return (value == null ? null : new ReaderInputStream(new StringReader(value), "utf-8")); //! } catch (Exception e) { //! throw new OntopiaRuntimeException(e); //! } //! } public void setReader(Reader value, long length, LocatorIF datatype) { if (value == null) throw new NullPointerException("Occurrence value must not be null."); if (datatype == null) throw new NullPointerException("Occurrence value datatype must not be null."); if (!"URI".equals(datatype.getNotation())) throw new ConstraintViolationException("Only datatypes with notation 'URI' are supported: " + datatype); try { setValue(StreamUtils.readString(value, length), datatype); } catch (IOException e) { throw new OntopiaRuntimeException(e); } } //! Public void setInputStream(InputStream value, long length, LocatorIF datatype) { //! throw new UnsupportedOperationException(); //! } //! //! public boolean isBinary() { //! return ObjectUtils.equals(getDataType(), DataTypes.TYPE_BINARY); //! } public LocatorIF getLocator() { if (!DataTypes.TYPE_URI.equals(getDataType())) return null; String value = getValue(); return (value == null ? null : URILocator.create(value)); } public void setLocator(LocatorIF locator) { if (locator == null) throw new NullPointerException("Occurrence locator must not be null."); if (!"URI".equals(locator.getNotation())) throw new ConstraintViolationException("Only locators with notation 'URI' are supported: " + locator); setValue(locator.getAddress(), DataTypes.TYPE_URI); } public long getLength() { return (value == null ? 0 : value.length()); } // ----------------------------------------------------------------------------- // ScopedIF implementation // ----------------------------------------------------------------------------- public Collection<TopicIF> getScope() { // Return scope defined on this object return (scope == null ? Collections.<TopicIF>emptySet() : 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(OccurrenceIF.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); } public void removeTheme(TopicIF theme) { if (theme == null) throw new NullPointerException("null is not a valid argument."); CrossTopicMapException.check(theme, this); // Notify listeners fireEvent(OccurrenceIF.EVENT_REMOVE_THEME, null, theme); // 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) throw new NullPointerException("Occurrence type must not be null."); CrossTopicMapException.check(type, this); // Notify listeners fireEvent(OccurrenceIF.EVENT_SET_TYPE, type, getType()); this.type = type; } // ----------------------------------------------------------------------------- // 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.Occurrence", (OccurrenceIF)this); } }