/*
* #!
* 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.tmapi2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import net.ontopia.topicmaps.core.ConstraintViolationException;
import net.ontopia.topicmaps.core.NotRemovableException;
import net.ontopia.topicmaps.core.OccurrenceIF;
import net.ontopia.topicmaps.core.ScopedIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicNameIF;
import net.ontopia.topicmaps.utils.MergeUtils;
import net.ontopia.topicmaps.xml.InvalidTopicMapException;
import org.tmapi.core.IdentityConstraintException;
import org.tmapi.core.Locator;
import org.tmapi.core.ModelConstraintException;
import org.tmapi.core.Name;
import org.tmapi.core.Occurrence;
import org.tmapi.core.Reifiable;
import org.tmapi.core.Role;
import org.tmapi.core.Topic;
import org.tmapi.core.TopicInUseException;
import org.tmapi.index.ScopedIndex;
import org.tmapi.index.TypeInstanceIndex;
/**
* INTERNAL: OKS->TMAPI 2 object wrapper.
*/
public class TopicImpl extends ConstructImpl implements Topic {
private TopicIF wrapped;
public TopicImpl(TopicMapImpl topicMap, TopicIF topic) {
super(topicMap);
wrapped = topic;
}
/*
* (non-Javadoc)
*
* @see net.ontopia.topicmaps.impl.tmapi2.Construct#getWrapped()
*/
TopicIF getWrapped() {
return wrapped;
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getSubjectIdentifiers()
*/
public Set<Locator> getSubjectIdentifiers() {
return topicMap.wrapSet(wrapped.getSubjectIdentifiers());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#addSubjectIdentifier(org.tmapi.core.Locator)
*/
public void addSubjectIdentifier(Locator sid) {
try {
wrapped.addSubjectIdentifier(topicMap.unwrapLocator(sid));
} catch (ConstraintViolationException ex) {
throw new IdentityConstraintException(this, topicMap
.getTopicBySubjectIdentifier(sid), sid,
"A topic with the subject identifier " + sid.getReference()
+ " exists");
} catch (NullPointerException ex) {
throw new ModelConstraintException(this,
"The subject identifier must not be null");
}
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#removeSubjectIdentifier(org.tmapi.core.Locator)
*/
public void removeSubjectIdentifier(Locator sid) {
if (sid == null) {
throw new ModelConstraintException(this,
"The subject identifier must not be null");
}
wrapped.removeSubjectIdentifier(topicMap.unwrapLocator(sid));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getSubjectLocators()
*/
public Set<Locator> getSubjectLocators() {
return topicMap.wrapSet(wrapped.getSubjectLocators());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#addSubjectLocator(org.tmapi.core.Locator)
*/
public void addSubjectLocator(Locator slo) {
try {
wrapped.addSubjectLocator(topicMap.unwrapLocator(slo));
} catch (ConstraintViolationException ex) {
throw new IdentityConstraintException(this, topicMap
.getTopicBySubjectLocator(slo), slo,
"A topic with the subject locator " + slo.getReference() + " exists");
} catch (NullPointerException ex) {
throw new ModelConstraintException(this,
"The subject locator must not be null");
}
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#removeSubjectLocator(org.tmapi.core.Locator)
*/
public void removeSubjectLocator(Locator slo) {
if (slo == null) {
throw new ModelConstraintException(this,
"The subject locator must not be null");
}
wrapped.removeSubjectLocator(topicMap.unwrapLocator(slo));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getTypes()
*/
public Set<Topic> getTypes() {
return topicMap.wrapSet(wrapped.getTypes());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#addType(org.tmapi.core.Topic)
*/
public void addType(Topic type) {
Check.typeNotNull(this, type);
Check.typeInTopicMap(getTopicMap(), type);
wrapped.addType(topicMap.unwrapTopic(type));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#removeType(org.tmapi.core.Topic)
*/
public void removeType(Topic type) {
Check.typeNotNull(this, type);
wrapped.removeType(topicMap.unwrapTopic(type));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createName(java.lang.String,
* org.tmapi.core.Topic[])
*/
public Name createName(String value, Topic... scope) {
return createName(topicMap.getDefaultNameType(), value, scope);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createName(java.lang.String,
* java.util.Collection)
*/
public Name createName(String value, Collection<Topic> scope) {
Check.scopeNotNull(this, scope);
return createName(value, scope.toArray(new Topic[scope.size()]));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createName(org.tmapi.core.Topic,
* java.lang.String, org.tmapi.core.Topic[])
*/
public Name createName(Topic type, String value, Topic... scope) {
Check.typeNotNull(this, type);
Check.valueNotNull(this, value);
Check.scopeNotNull(this, scope);
Check.scopeInTopicMap(getTopicMap(), scope);
Check.typeInTopicMap(getTopicMap(), type);
TopicNameIF name = topicMap.getWrapped().getBuilder().makeTopicName(
wrapped, topicMap.unwrapTopic(type), value);
applyScope(name, scope);
return topicMap.wrapName(name);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createName(org.tmapi.core.Topic,
* java.lang.String, java.util.Collection)
*/
public Name createName(Topic type, String value, Collection<Topic> scope) {
Check.scopeNotNull(this, scope);
return createName(type, value, scope.toArray(new Topic[scope.size()]));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* java.lang.String, org.tmapi.core.Topic[])
*/
public Occurrence createOccurrence(Topic type, String value, Topic... scope) {
Check.typeNotNull(this, type);
Check.valueNotNull(this, value);
Check.scopeNotNull(this, scope);
Check.scopeInTopicMap(getTopicMap(), scope);
Check.typeInTopicMap(getTopicMap(), type);
OccurrenceIF occ = topicMap.getWrapped().getBuilder().makeOccurrence(
wrapped, topicMap.unwrapTopic(type), value);
applyScope(occ, scope);
return topicMap.wrapOccurrence(occ);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* java.lang.String, java.util.Collection)
*/
public Occurrence createOccurrence(Topic type, String value,
Collection<Topic> scope) {
Check.scopeNotNull(this, scope);
return createOccurrence(type, value, scope.toArray(new Topic[scope.size()]));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* org.tmapi.core.Locator, org.tmapi.core.Topic[])
*/
public Occurrence createOccurrence(Topic type, Locator value, Topic... scope) {
Check.typeNotNull(this, type);
Check.valueNotNull(this, value);
Check.scopeNotNull(this, scope);
Check.scopeInTopicMap(getTopicMap(), scope);
Check.typeInTopicMap(getTopicMap(), type);
OccurrenceIF occ = topicMap.getWrapped().getBuilder().makeOccurrence(
wrapped, topicMap.unwrapTopic(type), topicMap.unwrapLocator(value));
applyScope(occ, scope);
return topicMap.wrapOccurrence(occ);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* org.tmapi.core.Locator, java.util.Collection)
*/
public Occurrence createOccurrence(Topic type, Locator value,
Collection<Topic> scope) {
Check.scopeNotNull(this, scope);
return createOccurrence(type, value, scope.toArray(new Topic[scope.size()]));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* java.lang.String, org.tmapi.core.Locator, org.tmapi.core.Topic[])
*/
public Occurrence createOccurrence(Topic type, String value,
Locator datatype, Topic... scope) {
Check.typeNotNull(this, type);
Check.valueNotNull(this, value, datatype);
Check.scopeNotNull(this, scope);
Check.typeInTopicMap(getTopicMap(), type);
OccurrenceIF occ = topicMap.getWrapped().getBuilder().makeOccurrence(
wrapped, topicMap.unwrapTopic(type), value,
topicMap.unwrapLocator(datatype));
applyScope(occ, scope);
return topicMap.wrapOccurrence(occ);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#createOccurrence(org.tmapi.core.Topic,
* java.lang.String, org.tmapi.core.Locator, java.util.Collection)
*/
public Occurrence createOccurrence(Topic type, String value,
Locator datatype, Collection<Topic> scope) {
Check.scopeNotNull(this, scope);
return createOccurrence(type, value, datatype, scope
.toArray(new Topic[scope.size()]));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getNames()
*/
public Set<Name> getNames() {
return topicMap.wrapSet(wrapped.getTopicNames());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getNames(org.tmapi.core.Topic)
*/
public Set<Name> getNames(Topic type) {
Check.typeNotNull(type);
TopicIF type_ = topicMap.unwrapTopic(type);
Collection<TopicNameIF> names = new ArrayList<TopicNameIF>();
for (Iterator<TopicNameIF> iter = wrapped.getTopicNames().iterator(); iter
.hasNext();) {
TopicNameIF name = iter.next();
if (type_.equals(name.getType())) {
names.add(name);
}
}
return topicMap.wrapSet(names);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getOccurrences()
*/
public Set<Occurrence> getOccurrences() {
return topicMap.wrapSet(wrapped.getOccurrences());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getOccurrences(org.tmapi.core.Topic)
*/
public Set<Occurrence> getOccurrences(Topic type) {
Check.typeNotNull(type);
TopicIF type_ = topicMap.unwrapTopic(type);
Collection<OccurrenceIF> occs = new ArrayList<OccurrenceIF>();
for (Iterator<OccurrenceIF> iter = wrapped.getOccurrences().iterator(); iter
.hasNext();) {
OccurrenceIF occ = iter.next();
if (type_.equals(occ.getType())) {
occs.add(occ);
}
}
return topicMap.wrapSet(occs);
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getParent()
*/
public TopicMapImpl getParent() {
return topicMap;
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getReified()
*/
public Reifiable getReified() {
return (Reifiable) topicMap.wrapTMObject(wrapped.getReified());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getRolesPlayed()
*/
public Set<Role> getRolesPlayed() {
return topicMap.wrapSet(wrapped.getRoles());
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getRolesPlayed(org.tmapi.core.Topic)
*/
public Set<Role> getRolesPlayed(Topic type) {
Check.typeNotNull(type);
return topicMap.wrapSet(wrapped.getRolesByType(topicMap.unwrapTopic(type)));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#getRolesPlayed(org.tmapi.core.Topic,
* org.tmapi.core.Topic)
*/
public Set<Role> getRolesPlayed(Topic type, Topic assocType) {
Check.typeNotNull(type);
if (assocType == null) {
throw new IllegalArgumentException(
"The association type must not be null");
}
return topicMap.wrapSet(wrapped.getRolesByType(topicMap.unwrapTopic(type),
topicMap.unwrapTopic(assocType)));
}
/*
* (non-Javadoc)
*
* @see org.tmapi.core.Topic#mergeIn(org.tmapi.core.Topic)
*/
public void mergeIn(Topic topic) {
if (topicMap.unwrapTopic(topic) == getWrapped())
return;
try {
MergeUtils.mergeInto(this.getWrapped(), topicMap.unwrapTopic(topic));
// getWrapped().merge(topicMap.unwrapTopic(topic));
} catch (InvalidTopicMapException e) {
throw new ModelConstraintException(this, e.getMessage());
} catch (ConstraintViolationException e) {
throw new ModelConstraintException(this, e.getMessage());
}
}
public void remove() {
isDeletable();
try {
super.remove();
} catch (NotRemovableException e) {
TopicInUseException ex = new TopicInUseException(this, e.getMessage());
ex.initCause(ex);
throw ex;
}
}
private void isDeletable() {
if (getReified() != null) {
throw new TopicInUseException(this, "The topic reifies a construct");
}
if (getRolesPlayed().size() > 0) {
throw new TopicInUseException(this, "The topic plays at least one role");
}
TypeInstanceIndex idx = getTopicMap().getIndex(TypeInstanceIndex.class);
if (idx.getOccurrenceTypes().contains(this)) {
throw new TopicInUseException(this,
"The topic is used as an occurrence type!");
}
if (idx.getRoleTypes().contains(this)) {
throw new TopicInUseException(this, "The topic is used as a role type!");
}
if (idx.getAssociationTypes().contains(this)) {
throw new TopicInUseException(this,
"The topic is used as an association type!");
}
if (idx.getTopicTypes().contains(this)) {
throw new TopicInUseException(this, "The topic is used as a topic type!");
}
if (idx.getNameTypes().contains(this)) {
throw new TopicInUseException(this, "The topic is used as a name type!");
}
ScopedIndex si = topicMap.getIndex(ScopedIndex.class);
if ((si.getAssociationThemes().contains(this))
|| (si.getNameThemes().contains(this))
|| (si.getOccurrenceThemes().contains(this))
|| (si.getVariantThemes().contains(this))) {
throw new TopicInUseException(this,
"The topic is used as a theme (scoping topic)!");
}
}
/**
* INTERNAL: Adds the specified scope to the scoped construct.
*
* @param scoped
* The scoped construct.
* @param scope
* The scope, must not be <tt>null</tt>.
*/
private void applyScope(ScopedIF scoped, Topic... scope) {
for (Topic theme : scope) {
scoped.addTheme(topicMap.unwrapTopic(theme));
}
}
}