/* * #! * Ontopia TMRAP * #- * 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.remote; import java.util.Collection; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.topicmaps.core.ConstraintViolationException; 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.impl.basic.Topic; import net.ontopia.topicmaps.impl.basic.TopicMap; import net.ontopia.topicmaps.impl.utils.ObjectStrings; import net.ontopia.topicmaps.utils.tmrap.RemoteTopicIndex; import net.ontopia.utils.OntopiaRuntimeException; /** * INTERNAL: The remote topic implementation. Checks that it is loaded * and then delegates calls to the super class. */ public class RemoteTopic extends Topic { /** Indicates if this topic has been fully loaded from the remote topic map to which it belongs. */ private boolean isLoaded; /** References a topic when this topic is removed through merging.*/ private RemoteTopic realTopic; RemoteTopic(TopicMap tm) { super(tm); } // Special to remote topic ----------------------------------------------------- public boolean isLoaded() { return isLoaded; } public void setLoaded(boolean isLoaded) { this.isLoaded = isLoaded; } protected void setRealTopic(RemoteTopic topic) { realTopic = topic; } public TopicIF getRealTopic() { return realTopic; } public synchronized void checkLoad() { if (!isLoaded() && isConnected()) load(); } /** Attempts to load topic from remote topic map.*/ private synchronized void load() { RemoteTopicMapStore store = (RemoteTopicMapStore) getTopicMap().getStore(); RemoteTopicIndex tindex = store.getTopicIndex(); if (getSubjectIdentifiers().isEmpty() && getItemIdentifiers().isEmpty() && getSubjectLocators().isEmpty()) throw new OntopiaRuntimeException("Can't load topic without identity"); // isLoaded gets set from elsewhere, strangely tindex.getTopics(getSubjectIdentifiers(), getItemIdentifiers(), getSubjectLocators()); } // ---------------------------------------------------------------------------- // TopicIF implementation // ---------------------------------------------------------------------------- public Collection<LocatorIF> getSubjectLocators() { if (realTopic!=null) return realTopic.getSubjectLocators(); else return super.getSubjectLocators(); } public void addSubjectLocator(LocatorIF subject_locator) throws ConstraintViolationException { if (realTopic != null) realTopic.addSubjectLocator(subject_locator); else super.addSubjectLocator(subject_locator); } public void removeSubjectLocator(LocatorIF subject_locator) { checkLoad(); if (realTopic != null) realTopic.removeSubjectLocator(subject_locator); else super.removeSubjectLocator(subject_locator); } public Collection<LocatorIF> getSubjectIdentifiers() { if (realTopic!=null) return realTopic.getSubjectIdentifiers(); else return super.getSubjectIdentifiers(); } public void addSubjectIdentifier(LocatorIF subject_indicator) throws ConstraintViolationException { if (realTopic != null) realTopic.addSubjectIdentifier(subject_indicator); else super.addSubjectIdentifier(subject_indicator); } public void removeSubjectIdentifier(LocatorIF subject_indicator) { checkLoad(); if (realTopic != null) realTopic.removeSubjectIdentifier(subject_indicator); else super.removeSubjectIdentifier(subject_indicator); } public Collection<TopicNameIF> getTopicNames() { checkLoad(); if (realTopic != null) return realTopic.getTopicNames(); else return super.getTopicNames(); } protected void addTopicName(TopicNameIF _basename) { checkLoad(); if (realTopic!=null) realTopic.addTopicName(_basename); else super.addTopicName(_basename); } protected void removeTopicName(TopicNameIF _basename) { checkLoad(); if (realTopic!=null) realTopic.removeTopicName(_basename); else super.removeTopicName(_basename); } public Collection<OccurrenceIF> getOccurrences() { checkLoad(); if (realTopic!=null) return realTopic.getOccurrences(); else return super.getOccurrences(); } protected void addOccurrence(OccurrenceIF _occurrence) { checkLoad(); if (realTopic!=null) realTopic.addOccurrence(_occurrence); else super.addOccurrence(_occurrence); } protected void removeOccurrence(OccurrenceIF _occurrence) { checkLoad(); if (realTopic!=null) realTopic.removeOccurrence(_occurrence); else super.removeOccurrence(_occurrence); } public Collection<AssociationRoleIF> getRoles() { checkLoad(); if (realTopic!=null) return realTopic.getRoles(); else return super.getRoles(); } public void remove() { throw new UnsupportedOperationException(); } public Collection<TopicIF> getTypes() { checkLoad(); if (realTopic != null) return realTopic.getTypes(); else return super.getTypes(); } public void addType(TopicIF type) { // this gets called before we know the identity of the topic if (realTopic != null) realTopic.addType(type); else super.addType(type); } public void removeType(TopicIF type) { checkLoad(); if (realTopic!=null) realTopic.removeType(type); else super.removeType(type); } // ----------------------------------------------------------------------------- // Misc. methods // ----------------------------------------------------------------------------- public String toString() { if (realTopic!=null) { return "{" + realTopic.toString() + "}"; } else { return ObjectStrings.toString("remote.Topic", (TopicIF)this) + ":" + isLoaded(); } } // tm object implementation public String getObjectId() { if (realTopic != null) return realTopic.getObjectId(); else return super.getObjectId(); } public boolean isReadOnly() { if (realTopic!=null) { return realTopic.isReadOnly(); } else { return super.isReadOnly(); } } public TopicMapIF getTopicMap() { if (realTopic!=null) { return realTopic.getTopicMap(); } else { return super.getTopicMap(); } } public Collection<LocatorIF> getItemIdentifiers() { if (realTopic!=null) { return realTopic.getItemIdentifiers(); } else { return super.getItemIdentifiers(); } } public void addItemIdentifier(LocatorIF source_locator) throws ConstraintViolationException { if (realTopic != null) realTopic.addItemIdentifier(source_locator); else super.addItemIdentifier(source_locator); } public void removeItemIdentifier(LocatorIF source_locator) { if (realTopic != null) realTopic.removeItemIdentifier(source_locator); else super.removeItemIdentifier(source_locator); } public synchronized void merge(TopicIF topic) { if (realTopic != null) throw new OntopiaRuntimeException("THIS SHOULD NEVER HAPPEN."); RemoteTopic rtopic = (RemoteTopic) topic; if (rtopic.isLoaded || this.isLoaded) { rtopic.setLoaded(true); setLoaded(true); } super.merge(topic); rtopic.setRealTopic(this); } public void debug() { System.out.println("-----RemoteTopic " + getObjectId() + " " + System.identityHashCode(this)); if (realTopic != null) { System.out.println("Deferring to real topic"); realTopic.debug(); } System.out.println("isLoaded: " + isLoaded() + ", isConnected: " + isConnected()); System.out.println("base names: " + super.getTopicNames().size()); } public boolean equals(Object obj) { if (obj instanceof RemoteTopic) { if( realTopic == null ) return ((RemoteTopic) obj).equals(this); return obj.equals(realTopic); } if (realTopic == null) return super.equals(obj); return realTopic.equals(obj); } public boolean equals(RemoteTopic obj) { if (realTopic == null) return super.equals(obj); return realTopic.equals(obj); } public int hashCode() { if (realTopic == null) return super.hashCode(); return realTopic.hashCode(); } }