From: <lh...@us...> - 2008-11-13 13:22:58
|
Revision: 181 http://tinytim.svn.sourceforge.net/tinytim/?rev=181&view=rev Author: lheuer Date: 2008-11-13 13:22:47 +0000 (Thu, 13 Nov 2008) Log Message: ----------- - TinyTimMapInputHandler uses the new IConstructFactory instead of concrete classes - XTM 1.0 / XTM 2.0 writer do not swallow the IOException but raise it in the constructor Modified Paths: -------------- tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapWriter.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMTopicMapReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMWriter.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/CTMReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/LTMReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/SnelloReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/TMXMLReader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/TinyTimMapInputHandler.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XMLWriter.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Reader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Writer.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Reader.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Writer.java tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTMReader.java tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestTinyTimMapInputHandler.java Removed Paths: ------------- tinytim-mio/trunk/src/main/java/org/tinytim/core/ Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -48,34 +48,35 @@ /** * - * + * * @param topicMap * @param syntax * @param source * @throws IOException */ - protected AbstractTopicMapReader(final TopicMap topicMap, final Syntax syntax, - final File source) throws IOException { + protected AbstractTopicMapReader(final TopicMap topicMap, + final Syntax syntax, final File source) throws IOException { this(topicMap, syntax, source, source.toURL().toString()); } /** * - * + * * @param topicMap * @param syntax * @param source * @param docIRI * @throws IOException */ - protected AbstractTopicMapReader(final TopicMap topicMap, final Syntax syntax, - final File source, final String docIRI) throws IOException { + protected AbstractTopicMapReader(final TopicMap topicMap, + final Syntax syntax, final File source, final String docIRI) + throws IOException { this(topicMap, syntax, new Source(new FileInputStream(source), docIRI)); } /** * - * + * * @param topicMap * @param syntax * @param source @@ -86,17 +87,32 @@ this(topicMap, syntax, new Source(source, docIRI)); } - protected AbstractTopicMapReader(final TopicMap topicMap, final Syntax syntax, - final Source source) { + /** + * + * + * @param topicMap + * @param syntax + * @param source + */ + protected AbstractTopicMapReader(final TopicMap topicMap, + final Syntax syntax, final Source source) { this(new TinyTimMapInputHandler(topicMap), syntax, source); } - protected AbstractTopicMapReader(final IMapHandler handler, final Syntax syntax, - final Source source) { + /** + * + * + * @param handler + * @param syntax + * @param source + */ + protected AbstractTopicMapReader(final IMapHandler handler, + final Syntax syntax, final Source source) { this(handler, DeserializerRegistry.createDeserializer(syntax), source); } - protected AbstractTopicMapReader(final IMapHandler handler, final IDeserializer deserializer, final Source source) { + protected AbstractTopicMapReader(final IMapHandler handler, + final IDeserializer deserializer, final Source source) { if (_deserializer == null) { throw new IllegalArgumentException("Deserializer not found"); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapWriter.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapWriter.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractTopicMapWriter.java 2008-11-13 13:22:47 UTC (rev 181) @@ -19,8 +19,8 @@ import org.tmapi.core.Topic; /** + * Common, abstract superclass for {@link TopicMapWriter} implementations. * - * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> * @version $Rev$ - $Date$ */ @@ -32,9 +32,21 @@ _baseIRI = baseIRI; } - protected String _getId(Topic tmo) { + /** + * Returns an identifier for the topic. + * <p> + * The algorithm tries to avoid to use the internal identifier which may + * cause yet another item identifier. If the topic has an item identifier + * which starts with the specified IRI provided in the constructor, the + * algorithm tries to use the fragment identifier. + * </p> + * + * @param topic The topic to return an identifier for. + * @return An identifier, never <tt>null</tt>. + */ + protected String _getId(final Topic topic) { String id = null; - for (Locator loc: tmo.getItemIdentifiers()) { + for (Locator loc: topic.getItemIdentifiers()) { String reference = loc.getReference(); if (!reference.startsWith(_baseIRI)) { continue; @@ -51,6 +63,7 @@ break; } } - return id != null ? id : "id-" + tmo.getId(); + return id != null ? id : "id-" + topic.getId(); } + } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMTopicMapReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMTopicMapReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMTopicMapReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -31,7 +31,7 @@ * to configure the reader. * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> - * @version $Rev:$ - $Date:$ + * @version $Rev$ - $Date$ */ abstract class AbstractXTMTopicMapReader extends AbstractTopicMapReader { @@ -79,7 +79,8 @@ * @return <tt>true</tt> if mergeMap is ignored, otherwise <tt>false</tt>. */ public boolean isIgnoringMergeMap() { - return Boolean.TRUE.equals(_deserializer.getProperty(Property.IGNORE_MERGEMAP)); + return Boolean.TRUE.equals(_deserializer + .getProperty(Property.IGNORE_MERGEMAP)); } /** @@ -102,6 +103,8 @@ * @return <tt>true</tt> if this reader validates the source, otherwise <tt>false</tt>. */ public boolean isValidating() { - return Boolean.TRUE.equals(_deserializer.getProperty(Property.VALIDATE)); + return Boolean.TRUE + .equals(_deserializer.getProperty(Property.VALIDATE)); } + } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMWriter.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMWriter.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/AbstractXTMWriter.java 2008-11-13 13:22:47 UTC (rev 181) @@ -18,31 +18,55 @@ import java.io.IOException; import java.io.OutputStream; -import org.tmapi.core.TMAPIRuntimeException; -import org.xml.sax.Attributes; import org.xml.sax.helpers.AttributesImpl; /** + * Abstract superclass for XTM serializers. + * <p> + * Provides a XML writer and takes care about the encoding. + * </p> * - * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> * @version $Rev$ - $Date$ */ abstract class AbstractXTMWriter extends AbstractTopicMapWriter { - protected final Attributes _EMPTY_ATTRS = XMLWriter.EMPTY_ATTRS; - - protected AttributesImpl _attrs; - protected XMLWriter _out; + protected final AttributesImpl _attrs; - public AbstractXTMWriter(final OutputStream out, final String baseIRI) { + protected final XMLWriter _out; + + /** + * Creates a new instance using "utf-8" encoding. + * + * @param out The output stream to write onto. + * @param baseIRI The base IRI. + * @throws IOException If an error occurs. + */ + protected AbstractXTMWriter(final OutputStream out, final String baseIRI) + throws IOException { + this(out, baseIRI, "utf-8"); + } + + /** + * Creates a new instance. + * + * @param out + * The output stream to write onto. + * @param baseIRI + * The base IRI. + * @param encoding + * The encoding to use. + * @throws IOException + * If an error occurs. + */ + protected AbstractXTMWriter(final OutputStream out, final String baseIRI, + final String encoding) throws IOException { super(baseIRI); - try { - _out = new XMLWriter(out); + if (encoding == null) { + throw new IOException("The encoding must not be null"); } - catch (IOException ex) { - throw new TMAPIRuntimeException(ex); - } + _out = new XMLWriter(out, encoding); + _attrs = new AttributesImpl(); } } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/CTMReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/CTMReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/CTMReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -44,7 +44,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public CTMReader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public CTMReader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.CTM, source, docIRI); } @@ -59,7 +60,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public CTMReader(final TopicMap topicMap, final File source) throws IOException { + public CTMReader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.CTM, source); } @@ -70,7 +72,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public CTMReader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public CTMReader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.CTM, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/LTMReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/LTMReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/LTMReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -41,7 +41,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public LTMReader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public LTMReader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.LTM, source, docIRI); } @@ -56,7 +57,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public LTMReader(final TopicMap topicMap, final File source) throws IOException { + public LTMReader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.LTM, source); } @@ -67,7 +69,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public LTMReader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public LTMReader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.LTM, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/SnelloReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/SnelloReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/SnelloReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -41,7 +41,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public SnelloReader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public SnelloReader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.SNELLO, source, docIRI); } @@ -56,7 +57,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public SnelloReader(final TopicMap topicMap, final File source) throws IOException { + public SnelloReader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.SNELLO, source); } @@ -67,7 +69,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public SnelloReader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public SnelloReader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.SNELLO, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/TMXMLReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/TMXMLReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/TMXMLReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -42,7 +42,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public TMXMLReader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public TMXMLReader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.TMXML, source, docIRI); } @@ -57,7 +58,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public TMXMLReader(final TopicMap topicMap, final File source) throws IOException { + public TMXMLReader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.TMXML, source); } @@ -68,7 +70,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public TMXMLReader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public TMXMLReader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.TMXML, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/TinyTimMapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/TinyTimMapInputHandler.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/TinyTimMapInputHandler.java 2008-11-13 13:22:47 UTC (rev 181) @@ -15,24 +15,520 @@ */ package org.tinytim.mio; -import org.tinytim.core.AbstractMapInputHandler; +import java.util.List; + +import org.tinytim.core.Scope; +import org.tinytim.core.value.Literal; +import org.tinytim.internal.api.IConstruct; +import org.tinytim.internal.api.IConstructFactory; +import org.tinytim.internal.api.ILiteralAware; +import org.tinytim.internal.api.IName; +import org.tinytim.internal.api.IScope; +import org.tinytim.internal.api.IScoped; +import org.tinytim.internal.api.ITopic; +import org.tinytim.internal.api.ITopicMap; +import org.tinytim.internal.api.IVariant; +import org.tinytim.internal.utils.CollectionFactory; +import org.tinytim.utils.TypeInstanceConverter; +import org.tinytim.voc.TMDM; + +import org.tmapi.core.Association; +import org.tmapi.core.Construct; +import org.tmapi.core.Locator; +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. + * Abstract {@link com.semagia.mio.IMapHandler} implementation. + * <p> + * This class utilises the <tt>.core</tt> package since some <tt>...Impl</tt> + * classes have only package visibility. + * </p> * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> * @version $Rev$ - $Date$ */ -public final class TinyTimMapInputHandler extends AbstractMapInputHandler { +public final class TinyTimMapInputHandler implements IMapHandler { + private static final int + INITIAL = 1, + TOPIC = 2, + ASSOCIATION = 3, + ROLE = 4, + OCCURRENCE = 5, + NAME = 6, + VARIANT = 7, + SCOPE = 8, + THEME = 9, + REIFIER = 10, + PLAYER = 11, + ISA = 12, + TYPE = 13; + + private static final int _CONSTRUCT_SIZE = 6; + private static final int _STATE_SIZE = 10; + private static final int _SCOPE_SIZE = 6; + + private final IConstructFactory _factory; + private final ITopicMap _tm; + private final List<Topic> _scope; + private int[] _stateStack; + private int _stateSize; + private IConstruct[] _constructStack; + private int _constructSize; + + protected TinyTimMapInputHandler(TopicMap topicMap) { + if (topicMap == null) { + throw new IllegalArgumentException("The topic map must not be null"); + } + _tm = (ITopicMap) topicMap; + _factory = _tm.getConstructFactory(); + _scope = CollectionFactory.createList(_SCOPE_SIZE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startTopicMap() + */ + public void startTopicMap() throws MIOException { + _constructStack = new IConstruct[_CONSTRUCT_SIZE]; + _stateStack = new int[_STATE_SIZE]; + _constructSize = 0; + _stateSize = 0; + _enterState(INITIAL, _tm); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endTopicMap() + */ + public void endTopicMap() throws MIOException { + TypeInstanceConverter.convertAssociationsToTypes(_tm); + _constructStack = null; + _stateStack = null; + _scope.clear(); + } + + /* (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 void endTopic() throws MIOException { + _handleTopic((Topic) _leaveStatePopConstruct(TOPIC)); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startAssociation() + */ + public void startAssociation() throws MIOException { + _enterState(ASSOCIATION, _factory.createAssociation()); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endAssociation() + */ + public void endAssociation() throws MIOException { + _leaveStatePopConstruct(ASSOCIATION); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startRole() + */ + public void startRole() throws MIOException { + assert _state() == ASSOCIATION; + _enterState(ROLE, _factory.createRole((Association) _peekConstruct())); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endRole() + */ + public void endRole() throws MIOException { + _leaveStatePopConstruct(ROLE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startPlayer() + */ + public void startPlayer() throws MIOException { + assert _state() == ROLE; + _enterState(PLAYER); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endPlayer() + */ + public void endPlayer() throws MIOException { + _leaveState(PLAYER); + assert _state() == ROLE; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startOccurrence() + */ + public void startOccurrence() throws MIOException { + _enterState(OCCURRENCE, _factory.createOccurrence(_peekTopic())); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endOccurrence() + */ + public void endOccurrence() throws MIOException { + _leaveStatePopConstruct(OCCURRENCE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startName() + */ + public void startName() throws MIOException { + _enterState(NAME, _factory.createName(_peekTopic())); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endName() + */ + public void endName() throws MIOException { + IName name = (IName) _leaveStatePopConstruct(NAME); + if (name.getType() == null) { + name.setType(_tm.createTopicBySubjectIdentifier(TMDM.TOPIC_NAME)); + } + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startVariant() + */ + public void startVariant() throws MIOException { + assert _state() == NAME; + _enterState(VARIANT, _factory.createVariant((IName) _peekConstruct())); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endVariant() + */ + public void endVariant() throws MIOException { + IVariant variant = (IVariant) _leaveStatePopConstruct(VARIANT); + IName name = (IName) _peekConstruct(); + IScope scope = variant.getScopeObject(); + if (scope.isUnconstrained() || name.getScopeObject() == scope) { + _reportError("The variant has no scope"); + } + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startType() + */ + public void startType() throws MIOException { + assert _peekConstruct() instanceof Typed; + _enterState(TYPE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endType() + */ + public void endType() throws MIOException { + _leaveState(TYPE); + assert _peekConstruct() instanceof Typed; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startScope() + */ + public void startScope() throws MIOException { + assert _peekConstruct() instanceof Scoped; + _enterState(SCOPE); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endScope() + */ + public void endScope() throws MIOException { + _leaveState(SCOPE); + ((IScoped) _peekConstruct()).setScopeObject(Scope.create(_scope)); + _scope.clear(); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startTheme() + */ + public void startTheme() throws MIOException { + assert _state() == SCOPE; + _enterState(THEME); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endTheme() + */ + public void endTheme() throws MIOException { + _leaveState(THEME); + assert _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); + ITopic 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 void subjectLocator(String subjectLocator) throws MIOException { + Locator slo = _tm.createLocator(subjectLocator); + ITopic 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); + IConstruct tmo = _peekConstruct(); + if (_state() == TOPIC) { + IConstruct existing = (IConstruct) _tm.getConstructByItemIdentifier(iid); + if (existing != null && existing.isTopic() && !existing.equals(tmo)) { + _merge((Topic) existing, (ITopic) tmo); + } + else { + Topic topic = _tm.getTopicBySubjectIdentifier(iid); + if (topic != null && !topic.equals(tmo)) { + _merge(topic, (ITopic) tmo); + } + } + } + tmo.addItemIdentifier(iid); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startIsa() + */ + public void startIsa() throws MIOException { + assert _state() == TOPIC; + _enterState(ISA); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endIsa() + */ + public void endIsa() throws MIOException { + _leaveState(ISA); + assert _state() == TOPIC; + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#startReifier() + */ + public void startReifier() throws MIOException { + assert _peekConstruct() instanceof Reifiable; + _enterState(REIFIER); + } + + /* (non-Javadoc) + * @see com.semagia.mio.IMapHandler#endReifier() + */ + public void endReifier() throws MIOException { + _leaveState(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() == NAME; + ((IName) _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)); + } + /** - * Intitializes a new instance with the specified <tt>topicMap</tt>. + * Enters a state. * - * @param topicMap The {@link TopicMap} instance. + * @param state The state to push ontop of the state stack. */ - public TinyTimMapInputHandler(TopicMap topicMap) { - super(topicMap); + private void _enterState(int state) { + if (_stateSize >= _stateStack.length) { + int[] states = new int[_stateStack.length*2]; + System.arraycopy(_stateStack, 0, states, 0, _stateStack.length); + _stateStack = states; + } + _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, Construct tmo) { + _enterState(state); + if (_constructSize >= _constructStack.length) { + IConstruct[] constructs = new IConstruct[_constructStack.length*2]; + System.arraycopy(_constructStack, 0, constructs, 0, _constructStack.length); + _constructStack = constructs; + } + _constructStack[_constructSize++] = (IConstruct) 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 { + if (state != _state()) { + _reportError("Unexpected state: " + _state() + ", 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-1]; + } + + /** + * Returns the topic on top of the stack. + * + * @return The topic. + */ + private ITopic _peekTopic() { + return (ITopic) _peekConstruct(); + } + + /** + * Returns the current state. + * + * @return The current state. + */ + private int _state() { + return _stateStack[_stateSize-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, ITopic 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 ITopic _createTopic(IRef ref) throws MIOException { + Locator loc = _tm.createLocator(ref.getIRI()); + switch (ref.getType()) { + case IRef.ITEM_IDENTIFIER: return (ITopic) _tm.createTopicByItemIdentifier(loc); + case IRef.SUBJECT_IDENTIFIER: return (ITopic) _tm.createTopicBySubjectIdentifier(loc); + case IRef.SUBJECT_LOCATOR: return (ITopic) _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); + } + } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XMLWriter.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XMLWriter.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XMLWriter.java 2008-11-13 13:22:47 UTC (rev 181) @@ -27,7 +27,7 @@ * Simple SAX-alike XML writer. * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> - * @version $Rev:$ - $Date:$ + * @version $Rev$ - $Date$ */ final class XMLWriter { @@ -38,17 +38,17 @@ private OutputStreamWriter _out; private final String _encoding; - - XMLWriter(OutputStream out) throws IOException { + + public XMLWriter(OutputStream out) throws IOException { this(out, "utf-8"); } - XMLWriter(OutputStream out, String encoding) throws IOException { + public XMLWriter(OutputStream out, String encoding) throws IOException { _out = new OutputStreamWriter(out, encoding); _encoding = encoding; } - /* (non-Javadoc) + /** * @see org.xml.sax.DocumentHandler#startDocument() */ public void startDocument() throws IOException { @@ -62,7 +62,7 @@ newline(); } - /* (non-Javadoc) + /** * @see org.xml.sax.DocumentHandler#endDocument() */ public void endDocument() throws IOException { @@ -79,7 +79,7 @@ startElement(name, EMPTY_ATTRS); } - /* (non-Javadoc) + /** * @see org.xml.sax.DocumentHandler#startElement(java.lang.String, org.xml.sax.AttributeList) */ public void startElement(String name, Attributes attrs) throws IOException { @@ -89,7 +89,7 @@ _out.write('>'); } - /* (non-Javadoc) + /** * @see org.xml.sax.DocumentHandler#endElement(java.lang.String) */ public void endElement(String name) throws IOException { @@ -138,8 +138,6 @@ /** * Writes the specified characters to the output. - * - * The data is written according to the rules of canonicalized XML. * * @param data The data to write. * @throws IOException If an error occurs. @@ -149,7 +147,7 @@ characters(chars, 0, chars.length); } - /* (non-Javadoc) + /** * @see org.xml.sax.DocumentHandler#characters(char[], int, int) */ public void characters(char[] chars, int start, int length) throws IOException { Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Reader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Reader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Reader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -45,7 +45,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public XTM10Reader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public XTM10Reader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.XTM_10, source, docIRI); } @@ -60,7 +61,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public XTM10Reader(final TopicMap topicMap, final File source) throws IOException { + public XTM10Reader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.XTM_10, source); } @@ -71,7 +73,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public XTM10Reader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public XTM10Reader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.XTM_10, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Writer.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Writer.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM10Writer.java 2008-11-13 13:22:47 UTC (rev 181) @@ -19,6 +19,8 @@ import java.io.OutputStream; import java.util.Set; +import org.tinytim.internal.api.IScope; +import org.tinytim.internal.api.IScoped; import org.tinytim.voc.Namespace; import org.tinytim.voc.XSD; @@ -52,14 +54,30 @@ // warn if datatype not in (xsd:string, xsd:anyURI) /** - * + * Creates a XTM 1.0 writer using "utf-8" encoding. * - * @param baseIRI + * @param out The stream the XTM is written onto. + * @param baseIRI The base IRI which is used to resolve IRIs against. + * @throws IOException If an error occurs. */ - public XTM10Writer(final OutputStream out, final String baseIRI) { + public XTM10Writer(final OutputStream out, final String baseIRI) + throws IOException { super(out, baseIRI); } + /** + * Creates a XTM 1.0 writer. + * + * @param out The stream the XTM is written onto. + * @param baseIRI The base IRI which is used to resolve IRIs against. + * @param encoding The encoding to use. + * @throws IOException If an error occurs. + */ + public XTM10Writer(final OutputStream out, final String baseIRI, + final String encoding) throws IOException { + super(out, baseIRI, encoding); + } + private String _getId(Reifiable reifiable) { assert reifiable.getReifier() != null; return "reifier-id-" + reifiable.getReifier().getId(); @@ -99,7 +117,6 @@ protected void _writeTopic(final Topic topic) throws IOException { _attrs.clear(); _attrs.addAttribute("", "id", "", "CDATA", _getId(topic)); - _out.newline(); _out.startElement("topic", _attrs); _writeIdentities(topic); for (Topic type: topic.getTypes()) { @@ -126,7 +143,6 @@ protected void _writeAssociation(final Association assoc) throws IOException { _attrs.clear(); _addId(_attrs, assoc); - _out.newline(); _out.startElement("association", _attrs); _writeType(assoc); _writeScope(assoc); @@ -217,8 +233,8 @@ } private void _writeScope(final Scoped scoped) throws IOException { - final Set<Topic> scope = scoped.getScope(); - if (scope.isEmpty()) { + final IScope scope = ((IScoped) scoped).getScopeObject(); + if (scope.isUnconstrained()) { return; } _out.newline(); @@ -242,6 +258,7 @@ _out.startElement("subjectIdentity"); _out.newline(); if (!slos.isEmpty()) { + // Choose one subject locator Locator slo = slos.iterator().next(); _attrs.clear(); _addLocator(_attrs, slo); Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Reader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Reader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Reader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -45,7 +45,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public XTM20Reader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public XTM20Reader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.XTM_20, source, docIRI); } @@ -60,7 +61,8 @@ * @param source The source to read the topic map from. * @throws IOException If an error occurs. */ - public XTM20Reader(final TopicMap topicMap, final File source) throws IOException { + public XTM20Reader(final TopicMap topicMap, final File source) + throws IOException { super(topicMap, Syntax.XTM_20, source); } @@ -71,7 +73,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public XTM20Reader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public XTM20Reader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.XTM_20, source, docIRI); } Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Writer.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Writer.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTM20Writer.java 2008-11-13 13:22:47 UTC (rev 181) @@ -19,7 +19,9 @@ import java.io.OutputStream; import java.util.Set; -import org.tinytim.core.IConstruct; +import org.tinytim.internal.api.IConstruct; +import org.tinytim.internal.api.IScope; +import org.tinytim.internal.api.IScoped; import org.tinytim.voc.Namespace; import org.tinytim.voc.TMDM; import org.tinytim.voc.XSD; @@ -52,14 +54,30 @@ public class XTM20Writer extends AbstractXTMWriter { /** - * + * Creates a XTM 2.0 writer using "utf-8" encoding. * - * @param baseIRI + * @param out The stream the XTM is written onto. + * @param baseIRI The base IRI which is used to resolve IRIs against. + * @throws IOException If an error occurs. */ - public XTM20Writer(final OutputStream out, final String baseIRI) { + public XTM20Writer(final OutputStream out, final String baseIRI) + throws IOException { super(out, baseIRI); } + /** + * Creates a XTM 2.0 writer. + * + * @param out The stream the XTM is written onto. + * @param baseIRI The base IRI which is used to resolve IRIs against. + * @param encoding The encoding to use. + * @throws IOException If an error occurs. + */ + public XTM20Writer(final OutputStream out, final String baseIRI, + final String encoding) throws IOException { + super(out, baseIRI, encoding); + } + /* (non-Javadoc) * @see org.tinytim.mio.ITopicMapWriter#write(org.tmapi.core.TopicMap) */ @@ -73,12 +91,10 @@ _out.startElement("topicMap", _attrs); _writeItemIdentifiers(topicMap); for (Topic topic: topicMap.getTopics()) { - _out.newline(); _writeTopic(topic); _out.newline(); } for (Association assoc: topicMap.getAssociations()) { - _out.newline(); _writeAssociation(assoc); _out.newline(); } @@ -99,12 +115,10 @@ _out.endElement("instanceOf"); } for (Name name: topic.getNames()) { - _out.newline(); _writeName(name); _out.newline(); } for (Occurrence occ: topic.getOccurrences()) { - _out.newline(); _writeOccurrence(occ); _out.newline(); } @@ -117,7 +131,6 @@ _writeType(assoc); _writeScope(assoc); for (Role role: assoc.getRoles()) { - _out.newline(); _writeRole(role); _out.newline(); } @@ -129,6 +142,7 @@ _writeItemIdentifiers(role); _writeType(role); _writeTopicRef(role.getPlayer()); + _out.newline(); _out.endElement("role"); } @@ -139,7 +153,6 @@ _writeScope(name); _out.dataElement("value", name.getValue()); for (Variant variant: name.getVariants()) { - _out.newline(); _writeVariant(variant); _out.newline(); } @@ -194,7 +207,7 @@ _addReifier(_attrs, reifier); return _attrs; } - return _EMPTY_ATTRS; + return XMLWriter.EMPTY_ATTRS; } private void _addReifier(final AttributesImpl attrs, final Topic reifier) { @@ -221,8 +234,8 @@ } private void _writeScope(final Scoped scoped) throws IOException { - final Set<Topic> scope = scoped.getScope(); - if (scope.isEmpty()) { + final IScope scope = ((IScoped) scoped).getScopeObject(); + if (scope.isUnconstrained()) { return; } _out.newline(); Modified: tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTMReader.java =================================================================== --- tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTMReader.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/main/java/org/tinytim/mio/XTMReader.java 2008-11-13 13:22:47 UTC (rev 181) @@ -45,7 +45,8 @@ * @param docIRI The document IRI which is used to resolve IRIs against. * @throws IOException If an error occurs. */ - public XTMReader(final TopicMap topicMap, final File source, final String docIRI) throws IOException { + public XTMReader(final TopicMap topicMap, final File source, + final String docIRI) throws IOException { super(topicMap, Syntax.XTM, source, docIRI); } @@ -71,7 +72,8 @@ * @param source The source to read the topic map from. * @param docIRI The document IRI which is used to resolve IRIs against. */ - public XTMReader(final TopicMap topicMap, final InputStream source, final String docIRI) { + public XTMReader(final TopicMap topicMap, final InputStream source, + final String docIRI) { super(topicMap, Syntax.XTM, source, docIRI); } Modified: tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestTinyTimMapInputHandler.java =================================================================== --- tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestTinyTimMapInputHandler.java 2008-11-13 13:19:39 UTC (rev 180) +++ tinytim-mio/trunk/src/test/java/org/tinytim/mio/TestTinyTimMapInputHandler.java 2008-11-13 13:22:47 UTC (rev 181) @@ -27,7 +27,7 @@ import com.semagia.mio.helpers.Ref; /** - * Tests against the {@link org.tinytim.core.AbstractMapInputHandler}. + * Tests against the {@link org.tinytim.mio.TinyTimMapInputHandler}. * * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a> * @version $Rev$ - $Date$ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |