From: <lh...@us...> - 2008-08-15 12:10:35
|
Revision: 127 http://tinytim.svn.sourceforge.net/tinytim/?rev=127&view=rev Author: lheuer Date: 2008-08-15 12:10:43 +0000 (Fri, 15 Aug 2008) Log Message: ----------- - Code reorg: Added abstract handler implementation into .core and created concrete class in .mio Modified Paths: -------------- tinytim-mio/trunk/src/main/java/org/tinytim/mio/TopicMapImporter.java Added Paths: ----------- tinytim-mio/trunk/src/main/java/org/tinytim/core/AbstractMapInputHandler.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/MapInputHandler.java tinytim-mio/trunk/src/test/java/org/tinytim/mio/ tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestMapInputHandler.java Removed Paths: ------------- tinytim-mio/trunk/src/main/java/org/tinytim/core/TinyTimMapInputHandler.java tinytim-mio/trunk/src/test/java/org/tinytim/core/ Added: tinytim-mio/trunk/src/main/java/org/tinytim/core/AbstractMapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/core/AbstractMapInputHandler.java (rev 0) +++ tinytim-mio/trunk/src/main/java/org/tinytim/core/AbstractMapInputHandler.java 2008-08-15 12:10:43 UTC (rev 127) @@ -0,0 +1,537 @@ +/* + * This is tinyTiM, a tiny Topic Maps engine. + * + * Copyright (C) 2008 Lars Heuer (heuer[at]semagia.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +package org.tinytim.core; + +import java.util.List; + +import org.tinytim.internal.utils.CollectionFactory; +import org.tinytim.utils.TypeInstanceConverter; +import org.tinytim.voc.TMDM; +import org.tmapi.core.Locator; +import org.tmapi.core.Name; +import org.tmapi.core.Occurrence; +import org.tmapi.core.Reifiable; +import org.tmapi.core.Role; +import org.tmapi.core.Scoped; +import org.tmapi.core.Topic; +import org.tmapi.core.TopicMap; +import org.tmapi.core.Typed; + +import com.semagia.mio.IMapHandler; +import com.semagia.mio.IRef; +import com.semagia.mio.MIOException; + +/** + * Abstract {@link com.semagia.mio.IMapHandler} implementation. + * + * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> + * @version $Rev$ - $Date$ + */ +public abstract class AbstractMapInputHandler implements IMapHandler { + + private final int + INITIAL = 0, + TOPIC = 1, + ASSOCIATION = 2, + ROLE = 3, + OCCURRENCE = 4, + NAME = 5, + VARIANT = 6, + SCOPE = 7, + THEME = 8, + REIFIER = 9, + PLAYER = 10, + ISA = 11, + TYPE = 12; + + private final int _CONSTRUCTS = 6; + private final int _STATES = 8; + private final int _SCOPE = 4; + + private TopicMapImpl _tm; + private int[] _stateStack; + private int _stateSize = -1; + private IConstruct[] _constructStack; + private int _constructSize = -1; + private List<Topic> _scope; + + protected AbstractMapInputHandler(TopicMap topicMap) { + setTopicMap(topicMap); + } + + /** + * Sets the topic map instance to operate on. + * + * @param topicMap The topic map. + */ + private final void setTopicMap(TopicMap topicMap) { + if (topicMap == null) { + throw new IllegalArgumentException("The topic map must not be null"); + } + _tm = (TopicMapImpl) topicMap; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startTopicMap() + */ + public final void startTopicMap() throws MIOException { + _constructStack = new IConstruct[_CONSTRUCTS]; + _stateStack = new int[_STATES]; + _scope = CollectionFactory.createList(_SCOPE); + _enterState(INITIAL, _tm); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endTopicMap() + */ + public final void endTopicMap() throws MIOException { + TypeInstanceConverter.convertAssociationsToTypes(_tm); + _constructStack = null; + _stateStack = null; + _scope = null; + _tm = null; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startTopic(com.semagia.mio.IRef) + */ + public void startTopic(IRef identity) throws MIOException { + _enterState(TOPIC, _createTopic(identity)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endTopic() + */ + public final void endTopic() throws MIOException { + _handleTopic((Topic) _leaveStatePopConstruct(TOPIC)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startAssociation() + */ + public final void startAssociation() throws MIOException { + _enterState(ASSOCIATION, new AssociationImpl(_tm)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endAssociation() + */ + public final void endAssociation() throws MIOException { + AssociationImpl assoc = (AssociationImpl) _leaveStatePopConstruct(ASSOCIATION); + _tm.addAssociation(assoc); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startRole() + */ + public final void startRole() throws MIOException { + assert _state() == ASSOCIATION; + _enterState(ROLE, new RoleImpl(_tm)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endRole() + */ + public final void endRole() throws MIOException { + Role role = (Role) _leaveStatePopConstruct(ROLE); + ((AssociationImpl) _peekConstruct()).addRole(role); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startPlayer() + */ + public final void startPlayer() throws MIOException { + assert _state() == ROLE; + _enterState(PLAYER); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endPlayer() + */ + public final void endPlayer() throws MIOException { + _leaveState(PLAYER); + assert _state() == ROLE; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startOccurrence() + */ + public final void startOccurrence() throws MIOException { + _enterState(OCCURRENCE, new OccurrenceImpl(_tm)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endOccurrence() + */ + public final void endOccurrence() throws MIOException { + Occurrence occ = (Occurrence) _leaveStatePopConstruct(OCCURRENCE); + _peekTopic().addOccurrence(occ); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startName() + */ + public final void startName() throws MIOException { + _enterState(NAME, new NameImpl(_tm)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endName() + */ + public final void endName() throws MIOException { + Name name = (Name) _leaveStatePopConstruct(NAME); + if (name.getType() == null) { + name.setType(_tm.createTopicBySubjectIdentifier(TMDM.TOPIC_NAME)); + } + _peekTopic().addName(name); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startVariant() + */ + public final void startVariant() throws MIOException { + assert _state() == NAME; + _enterState(VARIANT, new VariantImpl(_tm)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endVariant() + */ + public final void endVariant() throws MIOException { + VariantImpl variant = (VariantImpl) _leaveStatePopConstruct(VARIANT); + NameImpl name = (NameImpl) _peekConstruct(); + IScope scope = variant.getScopeObject(); + if (scope.isUnconstrained() || name.getScopeObject() == scope) { + throw new MIOException("The variant has no scope"); + } + name.addVariant(variant); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startType() + */ + public final void startType() throws MIOException { + assert _peekConstruct() instanceof Typed; + _enterState(TYPE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endType() + */ + public final void endType() throws MIOException { + _leaveState(TYPE); + assert _peekConstruct() instanceof Typed; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startScope() + */ + public final void startScope() throws MIOException { + assert _peekConstruct() instanceof Scoped; + _enterState(SCOPE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endScope() + */ + public final void endScope() throws MIOException { + _leaveState(SCOPE); + ((IScoped) _peekConstruct()).setScopeObject(Scope.create(_scope)); + _scope.clear(); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startTheme() + */ + public final void startTheme() throws MIOException { + assert _state() == SCOPE; + _enterState(THEME); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endTheme() + */ + public final void endTheme() throws MIOException { + _leaveState(THEME); + assert _state() == SCOPE; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#subjectIdentifier(java.lang.String) + */ + public final void subjectIdentifier(String subjectIdentifier) throws MIOException { + Locator sid = _tm.createLocator(subjectIdentifier); + TopicImpl topic = _peekTopic(); + Topic existing = _tm.getTopicBySubjectIdentifier(sid); + if (existing != null && !(existing == topic)) { + _merge(existing, topic); + } + else { + IConstruct tmo = (IConstruct) _tm.getConstructByItemIdentifier(sid); + if (tmo != null && tmo.isTopic() && !tmo.equals(topic)) { + _merge((Topic) tmo, topic); + } + } + topic.addSubjectIdentifier(sid); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#subjectLocator(java.lang.String) + */ + public final void subjectLocator(String subjectLocator) throws MIOException { + Locator slo = _tm.createLocator(subjectLocator); + TopicImpl topic = _peekTopic(); + Topic existing = _tm.getTopicBySubjectLocator(slo); + if (existing != null && !(existing == topic)) { + _merge(existing, topic); + } + topic.addSubjectLocator(slo); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#itemIdentifier(java.lang.String) + */ + public final void itemIdentifier(String itemIdentifier) throws MIOException { + Locator iid = _tm.createLocator(itemIdentifier); + IConstruct tmo = _peekConstruct(); + if (_state() == TOPIC) { + IConstruct existing = (IConstruct) _tm.getConstructByItemIdentifier(iid); + if (existing != null && existing.isTopic() && !existing.equals(tmo)) { + _merge((Topic) existing, (TopicImpl) tmo); + } + else { + Topic topic = _tm.getTopicBySubjectIdentifier(iid); + if (topic != null && !topic.equals(tmo)) { + _merge(topic, (TopicImpl) tmo); + } + } + } + tmo.addItemIdentifier(iid); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startIsa() + */ + public final void startIsa() throws MIOException { + assert _state() == TOPIC; + _enterState(ISA); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endIsa() + */ + public final void endIsa() throws MIOException { + _leaveState(ISA); + assert _state() == TOPIC; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startReifier() + */ + public final void startReifier() throws MIOException { + assert _peekConstruct() instanceof Reifiable; + _enterState(REIFIER); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endReifier() + */ + public final void endReifier() throws MIOException { + _leaveState(REIFIER); + assert _peekConstruct() instanceof Reifiable; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#topicRef(com.semagia.mio.IRef) + */ + public final void topicRef(IRef identity) throws MIOException { + _handleTopic(_createTopic(identity)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#value(java.lang.String) + */ + public final void value(String value) throws MIOException { + assert _state() == NAME; + ((Name) _peekConstruct()).setValue(value); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#value(java.lang.String, java.lang.String) + */ + public final void value(String value, String datatype) throws MIOException { + ((ILiteralAware) _peekConstruct()).setLiteral(Literal.create(value, datatype)); + } + + /** + * Enters a state. + * + * @param state The state to push ontop of the state stack. + */ + private void _enterState(int state) { + if (_stateSize + 1 > _stateStack.length) { + int[] states = new int[_stateSize*2]; + System.arraycopy(_stateStack, 0, states, 0, _stateSize); + _stateStack = states; + } + _stateSize++; + _stateStack[_stateSize] = state; + } + + /** + * Enters a state and pushes the Topic Maps construct ontop of the construct + * stack. + * + * @param state The state to enter. + * @param tmo The Topic Maps construct which should be pushed to the stack. + */ + private void _enterState(int state, IConstruct tmo) { + _enterState(state); + if (_constructSize + 1 > _constructStack.length) { + IConstruct[] constructs = new IConstruct[_constructSize*2]; + System.arraycopy(_constructStack, 0, constructs, 0, _constructSize); + _constructStack = constructs; + } + _constructSize++; + _constructStack[_constructSize] = tmo; + } + + /** + * Leaves a state. + * + * @param state The state to leave. + * @throws MIOException If the state is not equals to the current state. + */ + private void _leaveState(int state) throws MIOException { + final int current = _stateStack[_stateSize]; + if (state != current) { + _reportError("Unexpected state: " + current + ", expected: " + state); + } + _stateSize--; + } + + /** + * Leaves a state and removed the Topic Maps construct from the top of the + * construct stack. + * + * @param state The state to leave. + * @throws MIOException If the state is not equals to the current state. + */ + private IConstruct _leaveStatePopConstruct(int state) throws MIOException { + _leaveState(state); + final IConstruct construct = _peekConstruct(); + _constructStack[_constructSize] = null; + _constructSize--; + return construct; + } + + /** + * Returns the Topic Maps construct on top of the stack. + * + * @return The Topic Maps construct. + */ + private IConstruct _peekConstruct() { + return _constructStack[_constructSize]; + } + + /** + * Returns the topic on top of the stack. + * + * @return The topic. + */ + private TopicImpl _peekTopic() { + return (TopicImpl) _peekConstruct(); + } + + /** + * Returns the current state. + * + * @return The current state. + */ + private int _state() { + return _stateStack[_stateSize]; + } + + /** + * Handles the topic dependent on the current state. + * + * @param topic The topic to handle. + */ + private void _handleTopic(Topic topic) { + switch (_state()) { + case ISA: _peekTopic().addType(topic); break; + case TYPE: ((Typed) _peekConstruct()).setType(topic); break; + case PLAYER: ((Role) _peekConstruct()).setPlayer(topic); break; + case THEME: _scope.add(topic); break; + case REIFIER: ((Reifiable) _peekConstruct()).setReifier(topic); break; + } + } + + /** + * Merges the <tt>source</tt> topic with the <tt>target</tt>. + * + * Further, this method ensures that the construct stack stays valid: If + * the <tt>source</tt> is part of the stack, it is replaced with + * <tt>target</tt>. + * + * @param source The source topic (will be removed). + * @param target The target topic. + */ + private void _merge(Topic source, TopicImpl target) { + for (int i=0; i<_constructSize; i++) { + if (_constructStack[i] == source) { + _constructStack[i] = target; + } + } + target.mergeIn(source); + } + + /** + * Returns either an existing topic with the specified identity or creates + * a topic with the given identity. + * + * @param ref The identity of the topic. + * @return A topic instance. + * @throws MIOException + */ + private TopicImpl _createTopic(IRef ref) throws MIOException { + Locator loc = _tm.createLocator(ref.getIRI()); + switch (ref.getType()) { + case IRef.ITEM_IDENTIFIER: return (TopicImpl) _tm.createTopicByItemIdentifier(loc); + case IRef.SUBJECT_IDENTIFIER: return (TopicImpl) _tm.createTopicBySubjectIdentifier(loc); + case IRef.SUBJECT_LOCATOR: return (TopicImpl) _tm.createTopicBySubjectLocator(loc); + default: _reportError("Unknown reference type " + ref.getType()); + } + // Never returned, an exception was thrown + return null; + } + + /** + * Reports an error. + * + * @param msg The error message. + * @throws MIOException Thrown in any case. + */ + private static void _reportError(String msg) throws MIOException { + throw new MIOException(msg); + } + +} Property changes on: tinytim-mio/trunk/src/main/java/org/tinytim/core/AbstractMapInputHandler.java ___________________________________________________________________ Added: svn:keywords + Rev Date Id Added: svn:eol-style + native Deleted: tinytim-mio/trunk/src/main/java/org/tinytim/core/TinyTimMapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/core/TinyTimMapInputHandler.java 2008-08-14 12:11:54 UTC (rev 126) +++ tinytim-mio/trunk/src/main/java/org/tinytim/core/TinyTimMapInputHandler.java 2008-08-15 12:10:43 UTC (rev 127) @@ -1,512 +0,0 @@ -/* - * This is tinyTiM, a tiny Topic Maps engine. - * - * Copyright (C) 2008 Lars Heuer (heuer[at]semagia.com) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -package org.tinytim.core; - -import java.util.ArrayList; -import java.util.List; - -import org.tinytim.utils.TypeInstanceConverter; -import org.tinytim.voc.TMDM; -import org.tmapi.core.Construct; -import org.tmapi.core.Locator; -import org.tmapi.core.Name; -import org.tmapi.core.Occurrence; -import org.tmapi.core.Reifiable; -import org.tmapi.core.Role; -import org.tmapi.core.Scoped; -import org.tmapi.core.Topic; -import org.tmapi.core.TopicMap; -import org.tmapi.core.Typed; - -import com.semagia.mio.IMapHandler; -import com.semagia.mio.IRef; -import com.semagia.mio.MIOException; - -/** - * {@link com.semagia.mio.IMapHandler} implementation. - * - * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> - * @version $Rev$ - $Date$ - */ -public class TinyTimMapInputHandler implements IMapHandler { - - private enum State { - INITIAL, TOPIC, ASSOCIATION, ROLE, OCCURRENCE, NAME, VARIANT, - SCOPE, THEME, REIFIER, PLAYER, ISA, TYPE; - } - - private TopicMapImpl _tm; - private List<State> _stateStack; - private List<Construct> _constructStack; - private List<Topic> _scope; - - public TinyTimMapInputHandler() { - // noop. - } - - public TinyTimMapInputHandler(TopicMap topicMap) { - this(); - setTopicMap(topicMap); - } - - /** - * Sets the topic map instance to operate on. - * - * @param topicMap The topic map. - */ - public void setTopicMap(TopicMap topicMap) { - if (topicMap == null) { - throw new IllegalArgumentException("The topic map must not be null"); - } - _tm = (TopicMapImpl) topicMap; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startTopicMap() - */ - public void startTopicMap() throws MIOException { - _constructStack = new ArrayList<Construct>(); - _stateStack = new ArrayList<State>(); - _scope = new ArrayList<Topic>(); - _enterState(State.INITIAL, _tm); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endTopicMap() - */ - public void endTopicMap() throws MIOException { - TypeInstanceConverter.convertAssociationsToTypes(_tm); - _constructStack = null; - _stateStack = null; - _scope = null; - _tm = null; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startTopic(com.semagia.mio.IRef) - */ - public void startTopic(IRef identity) throws MIOException { - _enterState(State.TOPIC, _createTopic(identity)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endTopic() - */ - public void endTopic() throws MIOException { - Topic topic = (Topic) _leaveStatePopConstruct(State.TOPIC); - _handleTopic(topic); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startAssociation() - */ - public void startAssociation() throws MIOException { - _enterState(State.ASSOCIATION, new AssociationImpl(_tm)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endAssociation() - */ - public void endAssociation() throws MIOException { - AssociationImpl assoc = (AssociationImpl) _leaveStatePopConstruct(State.ASSOCIATION); - _tm.addAssociation(assoc); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startRole() - */ - public void startRole() throws MIOException { - assert _state() == State.ASSOCIATION; - _enterState(State.ROLE, new RoleImpl(_tm)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endRole() - */ - public void endRole() throws MIOException { - Role role = (Role) _leaveStatePopConstruct(State.ROLE); - ((AssociationImpl) _peekConstruct()).addRole(role); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startPlayer() - */ - public void startPlayer() throws MIOException { - assert _state() == State.ROLE; - _enterState(State.PLAYER); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endPlayer() - */ - public void endPlayer() throws MIOException { - _leaveState(State.PLAYER); - assert _state() == State.ROLE; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startOccurrence() - */ - public void startOccurrence() throws MIOException { - _enterState(State.OCCURRENCE, new OccurrenceImpl(_tm)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endOccurrence() - */ - public void endOccurrence() throws MIOException { - Occurrence occ = (Occurrence) _leaveStatePopConstruct(State.OCCURRENCE); - _peekTopic().addOccurrence(occ); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startName() - */ - public void startName() throws MIOException { - _enterState(State.NAME, new NameImpl(_tm)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endName() - */ - public void endName() throws MIOException { - Name name = (Name) _leaveStatePopConstruct(State.NAME); - if (name.getType() == null) { - name.setType(_tm.createTopicBySubjectIdentifier(TMDM.TOPIC_NAME)); - } - _peekTopic().addName(name); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startVariant() - */ - public void startVariant() throws MIOException { - assert _state() == State.NAME; - _enterState(State.VARIANT, new VariantImpl(_tm)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endVariant() - */ - public void endVariant() throws MIOException { - VariantImpl variant = (VariantImpl) _leaveStatePopConstruct(State.VARIANT); - NameImpl name = (NameImpl) _peekConstruct(); - IScope scope = variant.getScopeObject(); - if (scope.isUnconstrained() || name.getScopeObject() == scope) { - throw new MIOException("The variant has no scope"); - } - name.addVariant(variant); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startType() - */ - public void startType() throws MIOException { - assert _peekConstruct() instanceof Typed; - _enterState(State.TYPE); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endType() - */ - public void endType() throws MIOException { - _leaveState(State.TYPE); - assert _peekConstruct() instanceof Typed; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startScope() - */ - public void startScope() throws MIOException { - assert _peekConstruct() instanceof Scoped; - _enterState(State.SCOPE); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endScope() - */ - public void endScope() throws MIOException { - _leaveState(State.SCOPE); - ((IScoped) _peekConstruct()).setScopeObject(Scope.create(_scope)); - _scope.clear(); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startTheme() - */ - public void startTheme() throws MIOException { - assert _state() == State.SCOPE; - _enterState(State.THEME); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endTheme() - */ - public void endTheme() throws MIOException { - _leaveState(State.THEME); - assert _state() == State.SCOPE; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#subjectIdentifier(java.lang.String) - */ - public void subjectIdentifier(String subjectIdentifier) throws MIOException { - Locator sid = _tm.createLocator(subjectIdentifier); - Topic topic = _peekTopic(); - Topic existing = _tm.getTopicBySubjectIdentifier(sid); - if (existing != null && !(existing == topic)) { - _merge(existing, topic); - } - else { - Construct tmo = _tm.getConstructByItemIdentifier(sid); - if (tmo != null && tmo instanceof Topic && !tmo.equals(topic)) { - _merge((Topic) tmo, topic); - } - } - topic.addSubjectIdentifier(sid); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#subjectLocator(java.lang.String) - */ - public void subjectLocator(String subjectLocator) throws MIOException { - Locator slo = _tm.createLocator(subjectLocator); - Topic topic = _peekTopic(); - Topic existing = _tm.getTopicBySubjectLocator(slo); - if (existing != null && !(existing == topic)) { - _merge(existing, topic); - } - topic.addSubjectLocator(slo); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#itemIdentifier(java.lang.String) - */ - public void itemIdentifier(String itemIdentifier) throws MIOException { - Locator iid = _tm.createLocator(itemIdentifier); - Construct tmo = _peekConstruct(); - if (_state() == State.TOPIC) { - Construct existing = _tm.getConstructByItemIdentifier(iid); - if (existing != null && existing instanceof Topic && !existing.equals(tmo)) { - _merge((Topic) existing, (Topic) tmo); - } - else { - Topic topic = _tm.getTopicBySubjectIdentifier(iid); - if (topic != null && !topic.equals(tmo)) { - _merge(topic, (Topic) tmo); - } - } - } - tmo.addItemIdentifier(iid); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startIsa() - */ - public void startIsa() throws MIOException { - assert _state() == State.TOPIC; - _enterState(State.ISA); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endIsa() - */ - public void endIsa() throws MIOException { - _leaveState(State.ISA); - assert _state() == State.TOPIC; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#startReifier() - */ - public void startReifier() throws MIOException { - assert _peekConstruct() instanceof Reifiable; - _enterState(State.REIFIER); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#endReifier() - */ - public void endReifier() throws MIOException { - _leaveState(State.REIFIER); - assert _peekConstruct() instanceof Reifiable; - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#topicRef(com.semagia.mio.IRef) - */ - public void topicRef(IRef identity) throws MIOException { - _handleTopic(_createTopic(identity)); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#value(java.lang.String) - */ - public void value(String value) throws MIOException { - assert _state() == State.NAME; - ((Name) _peekConstruct()).setValue(value); - } - - /* (non-Javadoc) - * @see com.semagia.mio.IMapHandler#value(java.lang.String, java.lang.String) - */ - public void value(String value, String datatype) throws MIOException { - ((ILiteralAware) _peekConstruct()).setLiteral(Literal.create(value, datatype)); - } - - /** - * Enters a state. - * - * @param state The state to push ontop of the state stack. - */ - private void _enterState(State state) { - _stateStack.add(state); - } - - /** - * Enters a state and pushes the Topic Maps construct ontop of the construct - * stack. - * - * @param state The state to enter. - * @param tmo The Topic Maps construct which should be pushed to the stack. - */ - private void _enterState(State state, Construct tmo) { - _enterState(state); - _constructStack.add(tmo); - } - - /** - * Leaves a state. - * - * @param state The state to leave. - * @throws MIOException If the state is not equals to the current state. - */ - private void _leaveState(State state) throws MIOException { - State current = _stateStack.remove(_stateStack.size()-1); - if (state != current) { - _reportError("Unexpected state: " + current + ", expected: " + state); - } - } - - /** - * Leaves a state and removed the Topic Maps construct from the top of the - * construct stack. - * - * @param state The state to leave. - * @throws MIOException If the state is not equals to the current state. - */ - private Construct _leaveStatePopConstruct(State state) throws MIOException { - _leaveState(state); - return _constructStack.remove(_constructStack.size()-1); - } - - /** - * Returns the Topic Maps construct on top of the stack. - * - * @return The Topic Maps construct. - */ - private Construct _peekConstruct() { - return _constructStack.get(_constructStack.size()-1); - } - - /** - * Returns the topic on top of the stack. - * - * @return The topic. - */ - private TopicImpl _peekTopic() { - return (TopicImpl) _peekConstruct(); - } - - /** - * Returns the current state. - * - * @return The current state. - */ - private State _state() { - return _stateStack.get(_stateStack.size()-1); - } - - /** - * Handles the topic dependent on the current state. - * - * @param topic The topic to handle. - */ - private void _handleTopic(Topic topic) { - switch (_state()) { - case ISA: _peekTopic().addType(topic); break; - case TYPE: ((Typed) _peekConstruct()).setType(topic); break; - case PLAYER: ((Role) _peekConstruct()).setPlayer(topic); break; - case THEME: _scope.add(topic); break; - case REIFIER: ((Reifiable) _peekConstruct()).setReifier(topic); break; - } - } - - /** - * Merges the <tt>source</tt> topic with the <tt>target</tt>. - * - * Further, this method ensures that the construct stack stays valid: If - * the <tt>source</tt> is part of the stack, it is replaced with - * <tt>target</tt>. - * - * @param source The source topic (will be removed). - * @param target The target topic. - */ - private void _merge(Topic source, Topic target) { - int i = _constructStack.indexOf(source); - while (i > -1) { - _constructStack.set(i, target); - i = _constructStack.indexOf(source); - } - target.mergeIn(source); - } - - /** - * Returns either an existing topic with the specified identity or creates - * a topic with the given identity. - * - * @param ref The identity of the topic. - * @return A topic instance. - * @throws MIOException - */ - private Topic _createTopic(IRef ref) throws MIOException { - Locator loc = _tm.createLocator(ref.getIRI()); - switch (ref.getType()) { - case IRef.ITEM_IDENTIFIER: return _tm.createTopicByItemIdentifier(loc); - case IRef.SUBJECT_IDENTIFIER: return _tm.createTopicBySubjectIdentifier(loc); - case IRef.SUBJECT_LOCATOR: return _tm.createTopicBySubjectLocator(loc); - default: _reportError("Unknown reference type " + ref.getType()); - } - // Never returned, an exception was thrown - return null; - } - - /** - * Reports an error. - * - * @param msg The error message. - * @throws MIOException Thrown in any case. - */ - private static void _reportError(String msg) throws MIOException { - throw new MIOException(msg); - } - -} Added: tinytim-mio/trunk/src/main/java/org/tinytim/mio/MapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/MapInputHandler.java (rev 0) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/MapInputHandler.java 2008-08-15 12:10:43 UTC (rev 127) @@ -0,0 +1,44 @@ +/* + * This is tinyTiM, a tiny Topic Maps engine. + * + * Copyright (C) 2008 Lars Heuer (heuer[at]semagia.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +package org.tinytim.mio; + +import org.tinytim.core.AbstractMapInputHandler; +import org.tmapi.core.TopicMap; + +/** + * {@link com.semagia.mio.IMapHandler} implementation. + * + * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> + * @version $Rev$ - $Date$ + */ +public final class MapInputHandler extends AbstractMapInputHandler { + + /** + * Intitializes a new <tt>MapInputHandler</tt> instance with the specified + * <tt>topicMap</tt>. + * + * @param topicMap The {@link TopicMap} instance. + */ + public MapInputHandler(final TopicMap topicMap) { + super(topicMap); + } + +} Property changes on: tinytim-mio/trunk/src/main/java/org/tinytim/mio/MapInputHandler.java ___________________________________________________________________ Added: svn:keywords + Rev Date Id Added: svn:eol-style + native Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/TopicMapImporter.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/TopicMapImporter.java 2008-08-14 12:11:54 UTC (rev 126) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/TopicMapImporter.java 2008-08-15 12:10:43 UTC (rev 127) @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.InputStream; -import org.tinytim.core.TinyTimMapInputHandler; import org.tmapi.core.TMAPIRuntimeException; import org.tmapi.core.TopicMap; @@ -207,7 +206,7 @@ if (deser == null) { throw new IOException("No deserializer found for the syntax '" + syntax.getName() + "'"); } - deser.setMapHandler(new TinyTimMapInputHandler(topicMap)); + deser.setMapHandler(new MapInputHandler(topicMap)); try { deser.parse(input, docIRI); } Added: tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestMapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestMapInputHandler.java (rev 0) +++ tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestMapInputHandler.java 2008-08-15 12:10:43 UTC (rev 127) @@ -0,0 +1,324 @@ +/* + * This is tinyTiM, a tiny Topic Maps engine. + * + * Copyright (C) 2008 Lars Heuer (heuer[at]semagia.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +package org.tinytim.mio; + +import org.tinytim.core.TinyTimTestCase; +import org.tinytim.voc.TMDM; +import org.tinytim.voc.XSD; +import org.tmapi.core.Locator; +import org.tmapi.core.Name; +import org.tmapi.core.Occurrence; +import org.tmapi.core.Topic; + +import com.semagia.mio.MIOException; +import com.semagia.mio.helpers.Ref; + +/** + * Tests against the {@link org.tinytim.core.AbstractMapInputHandler}. + * + * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> + * @version $Rev$ - $Date$ + */ +public class TestMapInputHandler extends TinyTimTestCase { + + private static final String _XSD_STRING = XSD.STRING.getReference(); + private static final String _XSD_ANY_URI = XSD.ANY_URI.getReference(); + + private MapInputHandler _handler; + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + _handler = new MapInputHandler(_tm); + } + + /** + * Simple startTopicMap, followed by an endTopicMap event. + */ + public void testEmpty() throws Exception { + assertEquals(0, _tm.getTopics().size()); + assertEquals(0, _tm.getAssociations().size()); + _handler.startTopicMap(); + _handler.endTopicMap(); + assertEquals(0, _tm.getTopics().size()); + assertEquals(0, _tm.getAssociations().size()); + } + + /** + * Tests reifying a topic map. + */ + public void testTMReifier() throws Exception { + String itemIdent = "http://sf.net/projects/tinytim/test#1"; + assertEquals(0, _tm.getTopics().size()); + assertEquals(0, _tm.getAssociations().size()); + _handler.startTopicMap(); + _handler.startReifier(); + _handler.startTopic(Ref.createItemIdentifier(itemIdent)); + _handler.endTopic(); + _handler.endReifier(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + assertEquals(0, _tm.getAssociations().size()); + Topic topic = (Topic) _tm.getConstructByItemIdentifier(_tm.createLocator(itemIdent)); + assertNotNull(topic); + assertNotNull(_tm.getReifier()); + assertEquals(topic, _tm.getReifier()); + } + + /** + * Tests topic creation with an item identifier. + */ + public void testTopicIdentityItemIdentifier() throws Exception { + String itemIdent = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createItemIdentifier(itemIdent)); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Topic topic = (Topic) _tm.getConstructByItemIdentifier(_tm.createLocator(itemIdent)); + assertNotNull(topic); + } + + /** + * Tests topic creation with a subject identifier. + */ + public void testTopicIdentitySubjectIdentifier() throws Exception { + String subjIdent = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(subjIdent)); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(subjIdent)); + assertNotNull(topic); + } + + /** + * Tests topic creation with a subject locator. + */ + public void testTopicIdentitySubjectLocator() throws Exception { + String subjLoc = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectLocator(subjLoc)); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Topic topic = _tm.getTopicBySubjectLocator(_tm.createLocator(subjLoc)); + assertNotNull(topic); + } + + /** + * Tests transparent merging. + */ + public void testTopicMerging() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String itemIdent = "http://example.org/1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + // Topic in topic event + _handler.startTopic(Ref.createItemIdentifier(itemIdent)); + _handler.itemIdentifier(ref); + _handler.endTopic(); + _handler.startOccurrence(); + _handler.value("tinyTiM", _XSD_STRING); + _handler.endOccurrence(); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(ref)); + assertNotNull(topic); + assertEquals(topic, _tm.getConstructByItemIdentifier(_tm.createLocator(ref))); + assertEquals(topic, _tm.getConstructByItemIdentifier(_tm.createLocator(itemIdent))); + assertEquals(1, topic.getOccurrences().size()); + Occurrence occ = (Occurrence) topic.getOccurrences().iterator().next(); + assertEquals("tinyTiM", occ.getValue()); + } + + /** + * Tests assigning identities to a topic. + */ + public void testTopicIdentities1() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.itemIdentifier(ref); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Locator loc = _tm.createLocator(ref); + Topic topic = _tm.getTopicBySubjectIdentifier(loc); + assertNotNull(topic); + assertEquals(topic, _tm.getConstructByItemIdentifier(loc)); + } + + /** + * Tests assigning identities to a topic. + */ + public void testTopicIdentities2() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createItemIdentifier(ref)); + _handler.subjectIdentifier(ref); + _handler.endTopic(); + _handler.endTopicMap(); + assertEquals(1, _tm.getTopics().size()); + Locator loc = _tm.createLocator(ref); + Topic topic = _tm.getTopicBySubjectIdentifier(loc); + assertNotNull(topic); + assertEquals(topic, _tm.getConstructByItemIdentifier(loc)); + } + + /** + * Tests reifying the topic map. + */ + public void testTopicMapReifier() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + _handler.startTopicMap(); + _handler.startReifier(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.endTopic(); + _handler.endReifier(); + _handler.endTopicMap(); + assertNotNull(_tm.getReifier()); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(ref)); + assertNotNull(topic); + assertEquals(topic, _tm.getReifier()); + } + + /** + * Tests occurrence creation with a value of datatype xsd:string. + */ + public void testOccurrenceValueString() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String val = "tinyTiM"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.startOccurrence(); + _handler.value(val, _XSD_STRING); + _handler.endOccurrence(); + _handler.endTopic(); + _handler.endTopicMap(); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(ref)); + assertNotNull(topic); + Occurrence occ = (Occurrence) topic.getOccurrences().iterator().next(); + assertEquals(val, occ.getValue()); + assertEquals(XSD.STRING, occ.getDatatype()); + } + + /** + * Tests occurrence creation with a value of datatype xsd:anyURI. + */ + public void testOccurrenceValueURI() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String val = "http://sf.net/projects/tinytim"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.startOccurrence(); + _handler.value(val, _XSD_ANY_URI); + _handler.endOccurrence(); + _handler.endTopic(); + _handler.endTopicMap(); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(ref)); + assertNotNull(topic); + Occurrence occ = (Occurrence) topic.getOccurrences().iterator().next(); + assertEquals(val, occ.getValue()); + assertEquals(XSD.ANY_URI, occ.getDatatype()); + } + + /** + * Tests if the name type is automatically set. + */ + public void testDefaultNameType() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String val = "tinyTiM"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.startName(); + _handler.value(val); + _handler.endName(); + _handler.endTopic(); + _handler.endTopicMap(); + Topic topic = _tm.getTopicBySubjectIdentifier(_tm.createLocator(ref)); + assertNotNull(topic); + Name name = topic.getNames().iterator().next(); + assertEquals(val, name.getValue()); + assertNotNull(name.getType()); + assertTrue(name.getType().getSubjectIdentifiers().contains(TMDM.TOPIC_NAME)); + } + + /** + * Tests if a variant with no scope is reported as error. + */ + public void testVariantNoScopeError() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String val = "tinyTiM"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.startName(); + _handler.value(val); + _handler.startVariant(); + _handler.value(val, _XSD_STRING); + try { + _handler.endVariant(); + fail("A variant with no scope shouldn't be allowed"); + } + catch (MIOException ex) { + // noop. + } + } + + /** + * Tests if a variant with a scope equals to the parent's scope is rejected. + */ + public void testVariantNoScopeError2() throws Exception { + String ref = "http://sf.net/projects/tinytim/test#1"; + String theme = "http://sf.net/projects/tinytim/test#theme"; + String val = "tinyTiM"; + _handler.startTopicMap(); + _handler.startTopic(Ref.createSubjectIdentifier(ref)); + _handler.startName(); + _handler.startScope(); + _handler.startTheme(); + _handler.topicRef(Ref.createItemIdentifier(theme)); + _handler.endTheme(); + _handler.endScope(); + _handler.value(val); + + _handler.startVariant(); + _handler.value(val, _XSD_STRING); + _handler.startScope(); + _handler.startTheme(); + _handler.topicRef(Ref.createItemIdentifier(theme)); + _handler.endTheme(); + _handler.endScope(); + try { + _handler.endVariant(); + fail("A variant with a scope equals to the parent's scope shouldn't be allowed"); + } + catch (MIOException ex) { + // noop. + } + } + +} Property changes on: tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestMapInputHandler.java ___________________________________________________________________ Added: svn:keywords + Rev Date Id Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |