|
From: <lh...@us...> - 2008-08-16 17:12:25
|
Revision: 129
http://tinytim.svn.sourceforge.net/tinytim/?rev=129&view=rev
Author: lheuer
Date: 2008-08-16 17:12:35 +0000 (Sat, 16 Aug 2008)
Log Message:
-----------
- Notice that .cxtm is outdated for version > 1.5
Added Paths:
-----------
tinytim-cxtm/THIS_PACKAGE_IS_NOT_USED_FOR_VERSIONS_LATER_THAN_1_5.txt
Removed Paths:
-------------
tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/CXTMWriter.java
tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/Canonicalizer.java
Added: tinytim-cxtm/THIS_PACKAGE_IS_NOT_USED_FOR_VERSIONS_LATER_THAN_1_5.txt
===================================================================
--- tinytim-cxtm/THIS_PACKAGE_IS_NOT_USED_FOR_VERSIONS_LATER_THAN_1_5.txt (rev 0)
+++ tinytim-cxtm/THIS_PACKAGE_IS_NOT_USED_FOR_VERSIONS_LATER_THAN_1_5.txt 2008-08-16 17:12:35 UTC (rev 129)
@@ -0,0 +1,2 @@
+2008-08-16: The .cxtm package has been moved into the .mio package.
+The Canonicalizer is the .mio.CXTMWriter and implements .mio.ITopicMapWriter
Deleted: tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/CXTMWriter.java
===================================================================
--- tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/CXTMWriter.java 2008-08-16 17:00:53 UTC (rev 128)
+++ tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/CXTMWriter.java 2008-08-16 17:12:35 UTC (rev 129)
@@ -1,207 +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.cxtm;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.Arrays;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * Simple SAX-alike XML writer that respects canonical XML to some extend.
- *
- * This class is not meant to be a generic XML-C14N writer, but it should be
- * good enough to support CXTM.
- *
- * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
- * @version $Rev$ - $Date$
- */
-final class CXTMWriter {
-
- public static final Attributes EMPTY_ATTRS = new AttributesImpl();
-
- private static final char _NL = '\n';
-
- private OutputStreamWriter _out;
-
- public CXTMWriter(OutputStream out) throws IOException {
- _out = new OutputStreamWriter(out, "UTF-8");
- }
-
- /**
- * Indicates the start of the serialization process.
- *
- * @throws IOException If an error occurs.
- */
- public void startDocument() throws IOException {
- // noop
- }
-
- /**
- * Indicates the end of the serialization process.
- *
- * @throws IOException If an error occurs.
- */
- public void endDocument() throws IOException {
- _out.flush();
- }
-
- /**
- * Indicates the start of an element with the specified local name.
- *
- * @see #startElement(String, Attributes).
- *
- * @param localName The element's name.
- * @throws IOException If an error occurs.
- */
- public void startElement(String localName) throws IOException {
- startElement(localName, EMPTY_ATTRS);
- }
-
- /**
- * Indicates the start of an element with the provided local name.
- *
- * The attributes written in canonical XML.
- *
- * @param localName The name of the element.
- * @param attrs The element's attributes.
- * @throws IOException If an error occurs.
- */
- public void startElement(String localName, Attributes attrs) throws IOException {
- String[] names = new String[attrs.getLength()];
- for (int i=0; i < names.length; i++) {
- names[i] = attrs.getLocalName(i);
- }
- Arrays.sort(names);
- _out.write('<');
- _out.write(localName);
- for (int i=0; i < names.length; i++) {
- _out.write(' ');
- _out.write(names[i]);
- _out.write("=\"");
- _out.write(_escapeAttributeValue(attrs.getValue("", names[i])));
- _out.write('"');
- }
- _out.write('>');
- }
-
- /**
- * Indicates the end of an elemnt.
- *
- * @param localName The element's name.
- * @throws IOException If an error occurs.
- */
- public void endElement(String localName) throws IOException {
- _out.write("</");
- _out.write(localName);
- _out.write('>');
- }
-
- /**
- * Writes a <tt>#x0A</tt> to the output.
- *
- * @throws IOException If an error occurs.
- */
- public void newline() throws IOException {
- _out.write(_NL);
- }
-
- /**
- * 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.
- */
- public void characters(String data) throws IOException {
- _out.write(_escapeTextContent(data));
- }
-
- /**
- * Escapes the data according to the canonical XML rules.
- *
- * @param value The value.
- * @return The escaped value.
- */
- private String _escapeTextContent(String value) {
- char[] data = value.toCharArray();
- StringBuilder sb = new StringBuilder(data.length);
- for (int i=0; i < data.length; i++) {
- char c = data[i];
- if (c == '\r') {
- sb.append("
");
- }
- else if (c == '&') {
- sb.append("&");
- }
- else if (c == '<') {
- sb.append("<");
- }
- else if (c == '>') {
- sb.append(">");
- }
- else {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- /**
- * Escapes the attribute's value according to canonical XML.
- *
- * @param value The value to escape.
- * @return The escaped value.
- */
- private String _escapeAttributeValue(String value) {
- char[] data = value.toCharArray();
- StringBuilder sb = new StringBuilder(data.length);
- for (int i=0; i<data.length; i++) {
- char c = data[i];
- if (c == '\t') {
- sb.append("	");
- }
- else if (c == '\n') {
- sb.append("
");
- }
- else if (c == '\r') {
- sb.append("
");
- }
- else if (c == '\"') {
- sb.append(""");
- }
- else if (c == '&') {
- sb.append("&");
- }
- else if (c == '<') {
- sb.append("<");
- }
- else {
- sb.append(c);
- }
- }
- return sb.toString();
- }
-}
Deleted: tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/Canonicalizer.java
===================================================================
--- tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/Canonicalizer.java 2008-08-16 17:00:53 UTC (rev 128)
+++ tinytim-cxtm/trunk/src/main/java/org/tinytim/cxtm/Canonicalizer.java 2008-08-16 17:12:35 UTC (rev 129)
@@ -1,1237 +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.cxtm;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.AbstractSet;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.logging.Logger;
-
-import org.tinytim.core.TopicMapImpl;
-import org.tinytim.internal.utils.CollectionFactory;
-import org.tinytim.utils.DuplicateRemovalUtils;
-import org.tinytim.voc.TMDM;
-import org.tinytim.voc.XSD;
-import org.tmapi.core.Association;
-import org.tmapi.core.Construct;
-import org.tmapi.core.DatatypeAware;
-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.TopicInUseException;
-import org.tmapi.core.TopicMap;
-import org.tmapi.core.Typed;
-import org.tmapi.core.Variant;
-import org.tmapi.index.TypeInstanceIndex;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.helpers.AttributesImpl;
-
-/**
- * Provides serialization of topic maps into Canonical XTM (CXTM).
- * <p>
- * CXTM is a format that guarantees that two equivalent Topic Maps Data Model
- * instances [ISO/IEC 13250-2] will always produce byte-by-byte identical
- * serializations, and that non-equivalent instances will always produce
- * different serializations.
- * </p>
- * <p>
- * See <a href="http://www.isotopicmaps.org/cxtm/">http://www.isotopicmaps.org/cxtm/</a>
- * for details.
- * </p>
- * <p>
- * <em>CAUTION</em>: This class implements the
- * <a href="http://www.isotopicmaps.org/cxtm/">CXTM draft dtd. 2008-05-15</a>,
- * the output may change in the future.
- * </p>
- * <p>
- * The canonicalizer IS NOT a generic TMAPI-compatible implementation. It
- * requires tinyTiM.
- * </p>
- * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
- * @version $Rev$ - $Date$
- */
-public final class Canonicalizer {
-
- private static final Logger LOG = Logger.getLogger(Canonicalizer.class.getName());
-
- private static final Role[] _EMPTY_ROLES = new Role[0];
-
- private Topic _type;
- private Topic _instance;
- private Topic _typeInstance;
-
- private CXTMWriter _out;
- private final String _normBase;
- private Map<Construct, Integer> _construct2Id;
- private Map<Topic, List<Role>> _topic2Roles;
- private Map<Locator, String> _locator2Norm;
-
- private Comparator<Topic> _topicComparator;
- private Comparator<Association> _assocComparator;
- private Comparator<Role> _roleComparator;
- private Comparator<Occurrence> _occComparator;
- private Comparator<Name> _nameComparator;
- private Comparator<Variant> _variantComparator;
- private Comparator<Set<Locator>> _locSetComparator;
- private Comparator<Locator> _locComparator;
- private Comparator<Set<Topic>> _scopeComparator;
-
- private Map<Association, Role[]> _assoc2Roles;
-
- /**
- * Creates a canonicalizer.
- *
- * @param out The stream the CXTM is written onto.
- * @param baseLocator The base locator which is used to resolve IRIs against.
- * @throws IOException If an error occurs.
- */
- public Canonicalizer(OutputStream out, String baseLocator) throws IOException {
- if (baseLocator == null) {
- throw new IllegalArgumentException("The base locator must not be null");
- }
- _out = new CXTMWriter(out);
- _normBase = _normalizeBaseLocator(baseLocator);
- _topicComparator = new TopicComparator();
- _assocComparator = new AssociationComparator();
- _roleComparator = new RoleComparator();
- _occComparator = new OccurrenceComparator();
- _nameComparator = new NameComparator();
- _variantComparator = new VariantComparator();
- _locSetComparator = new LocatorSetComparator();
- _locComparator = new LocatorComparator();
- _scopeComparator = new ScopeComparator();
- }
-
- /**
- * Serializes the specified <tt>topicMap</tt> into the CXTM format.
- * <p>
- * <em>CAUTION</em>: This method MAY modify the topic map since duplicate
- * Topic Maps constructs (if any) are removed in advance.
- * </p>
- *
- * @param topicMap The topic map to serialize.
- * @throws IOException If an error occurs.
- */
- public void write(TopicMap topicMap) throws IOException {
- DuplicateRemovalUtils.removeDuplicates(topicMap);
- _construct2Id = CollectionFactory.createIdentityMap();
- _locator2Norm = CollectionFactory.createIdentityMap();
- _assoc2Roles = CollectionFactory.createIdentityMap();
- _topic2Roles = CollectionFactory.createIdentityMap();
- TypeInstanceIndex typeInstanceIndex = ((TopicMapImpl) topicMap).getIndexManager().getTypeInstanceIndex();
- if (!typeInstanceIndex.isAutoUpdated()) {
- typeInstanceIndex.reindex();
- }
- Topic[] topics = _fetchTopics(topicMap, typeInstanceIndex);
- Association[] assocs = _fetchAssociations(topicMap, typeInstanceIndex);
- typeInstanceIndex.close();
- _createIndex(topics, assocs);
- _out.startDocument();
- AttributesImpl attrs = new AttributesImpl();
- _addReifier(attrs, topicMap);
- _out.startElement("topicMap", attrs);
- _out.newline();
- _writeItemIdentifiers(topicMap);
- for (Topic topic: topics) {
- _writeTopic(topic);
- }
- for (Association assoc: assocs) {
- _writeAssociation(assoc);
- }
- _out.endElement("topicMap");
- _out.newline();
- _out.endDocument();
- _out = null;
- _construct2Id = null;
- _locator2Norm = null;
- _assoc2Roles = null;
- _topic2Roles = null;
- }
-
- /**
- * Returns an unsorted array of topics which should be included into
- * the output.
- *
- * This method may return more topics than {@link TopicMap#getTopics()}
- * since this method creates virtual topics to model type-instance
- * relationships properly.
- *
- * @param topicMap The topic map from which the topic should be serialized.
- * @param idx A (upto date) type instance index.
- * @return All topics which must be included into the output.
- */
- private Topic[] _fetchTopics(final TopicMap topicMap, final TypeInstanceIndex idx) {
- Collection<Topic> types = idx.getTopicTypes();
- if (types.isEmpty()) {
- Set<Topic> topics = topicMap.getTopics();
- return topics.toArray(new Topic[topics.size()]);
- }
- else {
- List<Topic> topics = CollectionFactory.createList(topicMap.getTopics());
- TopicMapImpl tm = (TopicMapImpl) topicMap;
- _typeInstance = _getTopicBySubjectIdentifier(tm, topics, TMDM.TYPE_INSTANCE);
- _type = _getTopicBySubjectIdentifier(tm, topics, TMDM.TYPE);
- _instance = _getTopicBySubjectIdentifier(tm, topics, TMDM.INSTANCE);
- return topics.toArray(new Topic[topics.size()]);
- }
- }
-
- /**
- * Returns a topic by its subject identifier. If the topic is null, a
- * {@link TypeInstanceTopic} is created, added to the <tt>topics</tt>
- * and returned.
- *
- * @param tm The topic map to fetch the topic from.
- * @param topics A modifiable collection of topics.
- * @param sid The subject identifier.
- * @return A topic with the specified subject identifier.
- */
- private Topic _getTopicBySubjectIdentifier(TopicMap tm, Collection<Topic> topics, Locator sid) {
- Topic topic = tm.getTopicBySubjectIdentifier(sid);
- if (topic == null) {
- topic = new TypeInstanceTopic(sid);
- topics.add(topic);
- }
- return topic;
- }
-
- /**
- * Returns an unsorted array of associations which should be serialized.
- *
- * This method may return more association than {@link TopicMap#getAssociations()}
- * since this method may create virtual associations which are used to
- * model type-instance relationships properly.
- *
- * @param tm The topic map from which the associations should be serialized.
- * @param idx A (upto date) type instance index.
- * @return An unsorted array of associations which must be included into the output.
- */
- private Association[] _fetchAssociations(final TopicMap tm, final TypeInstanceIndex idx) {
- Collection<Topic> types = idx.getTopicTypes();
- if (types.isEmpty()) {
- Set<Association> assocs = tm.getAssociations();
- return assocs.toArray(new Association[assocs.size()]);
- }
- else {
- List<Association> assocs = CollectionFactory.createList(tm.getAssociations());
- for (Topic type: types) {
- for (Topic instance: idx.getTopics(type)) {
- assocs.add(new TypeInstanceAssociation(type, instance));
- }
- }
- return assocs.toArray(new Association[assocs.size()]);
- }
- }
-
- /**
- * Creates the index on which the canonicalizer operates.
- *
- * As sideeffect, the provided topic and association arrays get sorted.
- *
- * @param topics An array of topics.
- * @param assocs An array of associations.
- */
- private void _createIndex(Topic[] topics, Association[] assocs) {
- Arrays.sort(topics, _topicComparator);
- Topic topic = null;
- for (int i=0; i < topics.length; i++) {
- topic = topics[i];
- _construct2Id.put(topic, Integer.valueOf(i+1));
- }
- Arrays.sort(assocs, _assocComparator);
- Association assoc = null;
- for (int i=0; i < assocs.length; i++) {
- assoc = assocs[i];
- _construct2Id.put(assoc, Integer.valueOf(i+1));
- Set<Role> roles_ = assoc.getRoles();
- Role[] roles = roles_.toArray(new Role[roles_.size()]);
- Arrays.sort(roles, _roleComparator);
- _assoc2Roles.put(assoc, roles);
- for (int j=0; j < roles.length; j++) {
- _construct2Id.put(roles[j], Integer.valueOf(j+1));
- }
- }
- }
-
- /**
- * Returns a sorted array of roles of the provided association.
- *
- * @param assoc The association to retrieve the roles from.
- * @return A (maybe empty) sorted array of roles.
- */
- private Role[] _getRoles(final Association assoc) {
- Role[] roles = _assoc2Roles.get(assoc);
- return roles != null ? roles : _EMPTY_ROLES;
- }
-
- /**
- * Returns a sorted array of names of the provided topic.
- *
- * @param topic The topic to retrieve the names from.
- * @return A (maybe empty) sorted array of names.
- */
- private Name[] _getNames(final Topic topic) {
- Set<Name> names_ = topic.getNames();
- Name[] names = names_.toArray(new Name[names_.size()]);
- Arrays.sort(names, _nameComparator);
- return names;
- }
-
- /**
- * Returs a sorted array of variants of the provided name.
- *
- * @param name The name to retrieve the variants from.
- * @return A (maybe empty) sorted array of variants.
- */
- private Variant[] _getVariants(final Name name) {
- Set<Variant> variants_ = name.getVariants();
- Variant[] variants = variants_.toArray(new Variant[variants_.size()]);
- Arrays.sort(variants, _variantComparator);
- return variants;
- }
-
- /**
- * Returns a sorted array of occurrences of the provided topic.
- *
- * @param topic The topic to retrieve the occurrences from.
- * @return A (maybe emtpy) sorted array of occurrences.
- */
- private Occurrence[] _getOccurrences(final Topic topic) {
- Set<Occurrence> occs_ = topic.getOccurrences();
- Occurrence[] occs = occs_.toArray(new Occurrence[occs_.size()]);
- Arrays.sort(occs, _occComparator);
- return occs;
- }
-
- /**
- * Returns the index of the provided Topic Maps construct.
- *
- * The "index" is <cite>"[...] the string encoding of the position of this
- * information item in the canonically ordered list of the values from
- * that set".</cite> (CXTM 3.20 Constructing the number attribute).
- *
- * @param tmo The Topic Maps construct to return the index of.
- * @return The index of the Topic Maps construct.
- */
- private int _indexOf(final Construct tmo) {
- return _construct2Id.get(tmo).intValue();
- }
-
- /**
- * Serializes the <tt>topic</tt>.
- *
- * @param topic The topic to serialize.
- * @throws IOException If an error occurs.
- */
- private void _writeTopic(final Topic topic) throws IOException {
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "number", null, null, "" +_indexOf(topic));
- _out.startElement("topic", attrs);
- _out.newline();
- _writeLocatorSet("subjectIdentifiers", topic.getSubjectIdentifiers());
- _writeLocatorSet("subjectLocators", topic.getSubjectLocators());
- _writeItemIdentifiers(topic);
- Name[] names = _getNames(topic);
- for (int i=0; i < names.length; i++) {
- _writeName(names[i], i+1);
- }
- Occurrence[] occs = _getOccurrences(topic);
- for (int i=0; i < occs.length; i++) {
- _writeOccurrence(occs[i], i+1);
- }
- List<Role> roles_ = CollectionFactory.createList(topic.getRolesPlayed());
- List<Role> alienRoles = _topic2Roles.get(topic);
- if (alienRoles != null) {
- roles_.addAll(alienRoles);
- }
- Role[] roles = roles_.toArray(new Role[roles_.size()]);
- Arrays.sort(roles, _roleComparator);
- AttributesImpl roleAttrs = new AttributesImpl();
- StringBuilder sb = new StringBuilder(20);
- for (int i=0; i < roles.length; i++) {
- sb.append("association.")
- .append(_indexOf(roles[i].getParent()))
- .append(".role.")
- .append(_indexOf(roles[i]));
- roleAttrs.addAttribute("", "ref", null, null, sb.toString());
- _out.startElement("rolePlayed", roleAttrs);
- _out.endElement("rolePlayed");
- _out.newline();
- sb.setLength(0);
- roleAttrs.clear();
- }
- _out.endElement("topic");
- _out.newline();
- }
-
- /**
- * Serializes an association.
- *
- * @param assoc The association to serialize.
- * @throws IOException If an error occurs.
- */
- private void _writeAssociation(final Association assoc) throws IOException {
- _out.startElement("association", _attributes(assoc, _indexOf(assoc)));
- _out.newline();
- _writeType(assoc);
- for (Role role: _getRoles(assoc)) {
- _out.startElement("role", _attributes(role, _indexOf(role)));
- _out.newline();
- _out.startElement("player", _topicRef(role.getPlayer()));
- _out.endElement("player");
- _out.newline();
- _writeType(role);
- _writeItemIdentifiers(role);
- _out.endElement("role");
- _out.newline();
- }
- _writeScope(assoc);
- _writeItemIdentifiers(assoc);
- _out.endElement("association");
- _out.newline();
- }
-
- /**
- * Serializes an occurrence.
- *
- * @param occ The occurrence to serialize.
- * @param pos The position of the occurrence within the parent container.
- * @throws IOException If an error occurs.
- */
- private void _writeOccurrence(final Occurrence occ, int pos) throws IOException {
- _out.startElement("occurrence", _attributes(occ, pos));
- _out.newline();
- _writeDatatyped(occ);
- _writeType(occ);
- _writeScope(occ);
- _writeItemIdentifiers(occ);
- _out.endElement("occurrence");
- _out.newline();
- }
-
- /**
- * Writes the value/datatype pair of an occurrence or variant.
- *
- * @param obj The construct to serialize.
- * @throws IOException If an error occurs.
- */
- private void _writeDatatyped(final DatatypeAware obj) throws IOException {
- final String value = XSD.ANY_URI.equals(obj.getDatatype())
- ? _normalizeLocator(obj.locatorValue())
- : obj.getValue();
- _out.startElement("value");
- _out.characters(value);
- _out.endElement("value");
- _out.newline();
- _out.startElement("datatype");
- _out.characters(_normalizeLocator(obj.getDatatype()));
- _out.endElement("datatype");
- _out.newline();
- }
-
- /**
- * Serializes a topic name.
- *
- * @param name The name to serialize.
- * @param pos The position of the name within the parent container.
- * @throws IOException If an error occurs.
- */
- private void _writeName(final Name name, int pos) throws IOException {
- _out.startElement("name", _attributes(name, pos));
- _out.newline();
- _out.startElement("value");
- _out.characters(name.getValue());
- _out.endElement("value");
- _out.newline();
- _writeType(name);
- _writeScope(name);
- Variant[] variants = _getVariants(name);
- Variant variant = null;
- for (int i=0; i<variants.length; i++) {
- variant = variants[i];
- _out.startElement("variant", _attributes(variant, i+1));
- _out.newline();
- _writeDatatyped(variant);
- _writeScope(variant);
- _writeItemIdentifiers(variant);
- _out.endElement("variant");
- _out.newline();
- }
- _writeItemIdentifiers(name);
- _out.endElement("name");
- _out.newline();
- }
-
- /**
- * Serializes the type of a typed Topic Maps construct.
- *
- * @param typed The typed Topic Maps construct from which the type should be
- * serialized.
- * @throws IOException If an error occurs.
- */
- private void _writeType(final Typed typed) throws IOException {
- _out.startElement("type", _topicRef(typed.getType()));
- _out.endElement("type");
- _out.newline();
- }
-
- /**
- * Serializes the scope of a scoped Topic Maps construct.
- *
- * If the scope is unconstrained, this method does nothing.
- *
- * @param scoped The scoped Topic Maps construct.
- * @throws IOException If an error occurs.
- */
- private void _writeScope(final Scoped scoped) throws IOException {
- Set<Topic> scope = scoped.getScope();
- if (scope.isEmpty()) {
- return;
- }
- _out.startElement("scope");
- _out.newline();
- Topic[] themes = scope.toArray(new Topic[scope.size()]);
- Arrays.sort(themes, _topicComparator);
- for (int i=0; i < themes.length; i++) {
- _out.startElement("scopingTopic", _topicRef(themes[i]));
- _out.endElement("scopingTopic");
- _out.newline();
- }
- _out.endElement("scope");
- _out.newline();
- }
-
- /**
- * Serializes a locator.
- *
- * A normalized locator value is created which is serialized.
- *
- * @param loc The locator to serialize.
- * @throws IOException If an error occurs.
- */
- private void _writeLocator(final Locator loc) throws IOException {
- _out.startElement("locator");
- _out.characters(_normalizeLocator(loc));
- _out.endElement("locator");
- _out.newline();
- }
-
- /**
- * Serializes the item identifiers of the specified Topic Maps construct.
- *
- * @param tmo The Topic Maps construct to take the item identifiers from.
- * @throws IOException If an error occurs.
- */
- private void _writeItemIdentifiers(final Construct tmo) throws IOException {
- _writeLocatorSet("itemIdentifiers", tmo.getItemIdentifiers());
- }
-
- /**
- * Serializes the <tt>locators</tt> using the <tt>localName</tt> as
- * element name.
- *
- * If the set of <tt>locators</tt> is empty, this method does nothing.
- *
- * @param localName The element's name.
- * @param locators The locators to serialize.
- * @throws IOException If an error occurs.
- */
- private void _writeLocatorSet(final String localName, final Set<Locator> locators) throws IOException {
- if (locators.isEmpty()) {
- return;
- }
- Locator[] locs = locators.toArray(new Locator[locators.size()]);
- Arrays.sort(locs, _locComparator);
- _out.startElement(localName);
- _out.newline();
- for (int i=0; i < locs.length; i++) {
- _writeLocator(locs[i]);
- }
- _out.endElement(localName);
- _out.newline();
- }
-
- /**
- * Returns attributes which contains a reference to the provided topic.
- *
- * @param topic The topic to which the reference should point to.
- * @return Attributes with a topic reference.
- */
- private Attributes _topicRef(final Topic topic) {
- if (topic == null) {
- _reportInvalid("The topic reference is null");
- return CXTMWriter.EMPTY_ATTRS;
- }
- AttributesImpl attrs = new AttributesImpl();
- attrs.addAttribute("", "topicref", null, null, "" + _indexOf(topic));
- return attrs;
- }
-
- /**
- * Returns attributes which contain the reifier (if any) and the number
- * of the provided Topic Maps construct (not a topic).
- *
- * @param reifiable The Topic Maps construct.
- * @param The position of the reifiable within the parent container.
- * @return Attributes which contain a reference to the reifier (if any) and
- * the number of the provided Topic Maps construct.
- */
- private Attributes _attributes(final Reifiable reifiable, int i) {
- AttributesImpl attrs = new AttributesImpl();
- _addReifier(attrs, reifiable);
- attrs.addAttribute("", "number", null, null, "" + i);
- return attrs;
- }
-
- /**
- * Adds a reference to the reifier of the Topic Maps construct to the
- * provided attributes. If the Topic Maps construct has no reifier, the
- * provided attributes are not modified.
- *
- * @param attrs The attributes.
- * @param reifiable The reifiable Topic Maps construct.
- */
- private void _addReifier(final AttributesImpl attrs, final Reifiable reifiable) {
- Topic reifier = reifiable.getReifier();
- if (reifier != null) {
- attrs.addAttribute("", "reifier", null, null, "" + _indexOf(reifier));
- }
- }
-
- /**
- * Normalizes the locator according to CXTM 3.19.
- *
- * @param locator The locator to normalize.
- * @return A normalized representation of the locator.
- */
- private String _normalizeLocator(final Locator locator) {
- String normLoc = _locator2Norm.get(locator);
- if (normLoc != null) {
- return normLoc;
- }
- normLoc = locator.getReference();
- if (normLoc.startsWith(_normBase)) {
- normLoc = normLoc.substring(_normBase.length());
- }
- else {
- int i = 0;
- int slashPos = -1;
- final int max = Math.min(_normBase.length(), normLoc.length());
- while(i < max && _normBase.charAt(i) == normLoc.charAt(i)) {
- if (_normBase.charAt(i) == '/') {
- slashPos = i;
- }
- i++;
- }
- if (slashPos > -1) {
- normLoc = normLoc.substring(slashPos);
- }
- }
- if (normLoc.startsWith("/")) {
- normLoc = normLoc.substring(1);
- }
- _locator2Norm.put(locator, normLoc);
- return normLoc;
- }
-
- /**
- * Normalizes the base locator according to the following procedure
- * (CXTM 3.19 - 1.):
- * <cite>[...] the base locator with any fragment identifier and query
- * removed and any trailing "/" character removed.[...]</cite>
- *
- * @param baseLocator
- * @return
- */
- private static String _normalizeBaseLocator(final String baseLocator) {
- String loc = baseLocator;
- int i = loc.indexOf('#');
- if (i > 0) {
- loc = loc.substring(0, i);
- }
- i = loc.indexOf('?');
- if (i > 0) {
- loc = loc.substring(0, i);
- }
- if (loc.endsWith("/")) {
- loc = loc.substring(0, loc.length()-1);
- }
- return loc;
- }
-
- /**
- * Writes a warning msg to the log.
- *
- * This method is used to inform the user that the serialized topic map
- * is not valid acc. to CXTM.
- *
- * @param msg The warning message.
- */
- private static void _reportInvalid(final String msg) {
- LOG.warning("Invalid CXTM: '" + msg + "'");
- }
-
-
- /*
- * Comparators.
- */
-
- private final class TopicComparator implements Comparator<Topic> {
-
- public int compare(Topic o1, Topic o2) {
- if (o1 == o2) {
- return 0;
- }
- if (o1 != null && o2 == null) {
- _reportInvalid("Comparing topics where one topic is null");
- return +1;
- }
- else if (o1 == null && o2 != null) {
- _reportInvalid("Comparing topics where one topic is null");
- return -1;
- }
- int res = _locSetComparator.compare(o1.getSubjectIdentifiers(), o2.getSubjectIdentifiers());
- if (res == 0) {
- res = _locSetComparator.compare(o1.getSubjectLocators(), o2.getSubjectLocators());
- if (res == 0) {
- res = _locSetComparator.compare(o1.getItemIdentifiers(), o2.getItemIdentifiers());
- }
- }
- return res;
- }
- }
-
- /**
- * Abstract comparator that provides some utility methods which handle common
- * comparisons.
- */
- private abstract class AbstractComparator<T> implements Comparator<T> {
- int compareString(String o1, String o2) {
- if (o1 == null && o2 != null) {
- _reportInvalid("The first string value is null");
- return -1;
- }
- if (o1 != null && o2 == null) {
- _reportInvalid("The second string value is null");
- return +1;
- }
- return o1.compareTo(o2);
- }
- /**
- * Extracts the type of the typed Topic Maps constructs and compares
- * the topics.
- *
- * @param o1 The first typed Topic Maps construct.
- * @param o2 The second typed Topic Maps construct.
- * @return A negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than the
- * second.
- */
- int compareType(Typed o1, Typed o2) {
- return _topicComparator.compare(o1.getType(), o2.getType());
- }
- /**
- * Extracts the scope of the scoped Topic Maps constructs and compares
- * them.
- *
- * @param o1 The first scoped Topic Maps construct.
- * @param o2 The second scoped Topic Maps construct.
- * @return A negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than the
- * second.
- */
- int compareScope(Scoped o1, Scoped o2) {
- return _scopeComparator.compare(o1.getScope(), o2.getScope());
- }
- }
-
- /**
- * Enhances the {@link AbstractComparator} with a method to compare the
- * value and datatype of an occurrence or variant.
- */
- private abstract class AbstractDatatypeAwareComparator<T> extends AbstractComparator<T> {
- /**
- * Compares the value and datatype of the occurrences / variants.
- *
- * @param o1 The first occurrence / variant.
- * @param o2 The second occurrence / variant.
- * @return A negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than the
- * second.
- */
- int _compareValueDatatype(DatatypeAware o1, DatatypeAware o2) {
- int res = compareString(o1.getValue(), o2.getValue());
- if (res == 0) {
- res = compareString(o1.getDatatype().getReference(), o2.getDatatype().getReference());
- }
- return res;
- }
- }
-
- /**
- * Canonical sort order:
- * 1. [type]
- * 2. [roles]
- * 3. [scope]
- * 4. [parent]
- */
- private final class AssociationComparator extends AbstractComparator<Association> {
-
- private Comparator<Set<Role>> _roleSetComparator;
-
- AssociationComparator() {
- _roleSetComparator = new RoleSetComparator();
- }
-
- public int compare(Association o1, Association o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = compareType(o1, o2);
- if (res == 0) {
- res = _roleSetComparator.compare(o1.getRoles(), o2.getRoles());
- if (res == 0) {
- res = compareScope(o1, o2);
- }
- }
- return res;
- }
- }
-
- /**
- * Role comparator which ignores the parent association. This comparator
- * is meant to be used for roles where the parent is known to be equal or
- * unequal.
- */
- private class RoleIgnoreParentComparator extends AbstractComparator<Role> {
-
- public int compare(Role o1, Role o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = _topicComparator.compare(o1.getPlayer(), o2.getPlayer());
- if (res == 0) {
- res = compareType(o1, o2);
- }
- return res;
- }
- }
-
- /**
- * Canonical sort order:
- * 1. [player]
- * 2. [type]
- * 3. [parent]
- */
- private final class RoleComparator extends RoleIgnoreParentComparator {
-
- public int compare(Role o1, Role o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = super.compare(o1, o2);
- if (res == 0) {
- res = _assocComparator.compare(o1.getParent(), o2.getParent());
- }
- return res;
- }
- }
-
- /**
- * Canonical sort order:
- * 1. [value]
- * 2. [datatype]
- * 3. [type]
- * 4. [scope]
- * 5. [parent]
- */
- private final class OccurrenceComparator extends AbstractDatatypeAwareComparator<Occurrence> {
-
- public int compare(Occurrence o1, Occurrence o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = _compareValueDatatype(o1, o2);
- if (res == 0) {
- res = compareType(o1, o2);
- if (res == 0) {
- res = compareScope(o1, o2);
- }
- }
- return res;
- }
-
- }
-
- /**
- * Canonical sort order:
- * 1. [value]
- * 2. [type]
- * 3. [scope]
- * 4. [parent]
- */
- private final class NameComparator extends AbstractComparator<Name> {
-
- public int compare(Name o1, Name o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = compareString(o1.getValue(), o2.getValue());
- if (res == 0) {
- res = compareType(o1, o2);
- if (res == 0) {
- res = compareScope(o1, o2);
- }
- }
- return res;
- }
- }
-
- /**
- * Canonical sort order:
- * 1. [value]
- * 2. [datatype]
- * 3. [scope]
- * 4. [parent]
- */
- private final class VariantComparator extends AbstractDatatypeAwareComparator<Variant> {
-
- public int compare(Variant o1, Variant o2) {
- if (o1 == o2) {
- return 0;
- }
- int res = _compareValueDatatype(o1, o2);
- if (res == 0) {
- res = compareScope(o1, o2);
- }
- return res;
- }
- }
-
- /**
- * Comparator which compares the size of the provided set.
- *
- * Iff the size of the sets are equal, another comparison method is used
- * to compare the content of the sets.
- */
- private abstract class AbstractSetComparator<T> implements Comparator<Set<T>> {
-
- public int compare(Set<T> o1, Set<T> o2) {
- int s1 = o1.size();
- int s2 = o2.size();
- int res = s1 - s2;
- if (res == 0) {
- res = compareContent(o1, o2, s1);
- }
- return res;
- }
-
- /**
- * Called iff the size of the sets is equal.
- *
- * This method is used to compare the content of the sets.
- *
- * @param o1 The first set.
- * @param o2 The second set.
- * @param size The size of the set(s).
- * @return A negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than the
- * second.
- */
- abstract int compareContent(Set<T> o1, Set<T> o2, int size);
- }
-
- /**
- * Compares role sets. The parent of the roles is ignored!
- */
- private final class RoleSetComparator extends AbstractSetComparator<Role> {
-
- private RoleIgnoreParentComparator _roleCmp;
-
- RoleSetComparator() {
- _roleCmp = new RoleIgnoreParentComparator();
- }
-
- @Override
- int compareContent(Set<Role> o1, Set<Role> o2,
- int size) {
- int res = 0;
- Role[] roles1 = o1.toArray(new Role[size]);
- Role[] roles2 = o2.toArray(new Role[size]);
- Arrays.sort(roles1, _roleCmp);
- Arrays.sort(roles2, _roleCmp);
- for (int i=0; i < size && res == 0; i++) {
- res = _roleCmp.compare(roles1[i], roles2[i]);
- }
- return res;
- }
-
- }
-
- /**
- * Compares the scope of two scoped Topic Maps constructs.
- */
- private final class ScopeComparator extends AbstractSetComparator<Topic> {
-
- @Override
- int compareContent(Set<Topic> o1, Set<Topic> o2, int size) {
- int res = 0 ;
- Topic[] topics1 = o1.toArray(new Topic[size]);
- Topic[] topics2 = o2.toArray(new Topic[size]);
- Arrays.sort(topics1, _topicComparator);
- Arrays.sort(topics2, _topicComparator);
- for (int i=0; i < size && res == 0; i++) {
- res = _topicComparator.compare(topics1[i], topics2[i]);
- }
- return res;
- }
-
- }
-
- /**
- * Comparator for sets of {@link org.tmapi.core.Locator}s.
- */
- private final class LocatorSetComparator extends AbstractSetComparator<Locator> {
-
- @Override
- int compareContent(Set<Locator> o1, Set<Locator> o2, int size) {
- int res = 0;
- Locator[] locs1 = o1.toArray(new Locator[size]);
- Locator[] locs2 = o2.toArray(new Locator[size]);
- Arrays.sort(locs1, _locComparator);
- Arrays.sort(locs2, _locComparator);
- for (int i=0; i < size && res == 0; i++) {
- res = _locComparator.compare(locs1[i], locs2[i]);
- }
- return res;
- }
- }
-
- /**
- * Compares {@link org.tmapi.core.Locator}s.
- */
- private final class LocatorComparator implements Comparator<Locator> {
-
- public int compare(Locator o1, Locator o2) {
- if (o1 == o2) {
- return 0;
- }
- return _normalizeLocator(o1).compareTo(_normalizeLocator(o2));
- }
-
- }
-
-
- /*
- * Helper classes to treat type-instance relationships, modelled as property
- * of a topic, as associations.
- */
-
- private final class TypeInstanceTopic implements Topic {
-
- private final Set<Locator> _sids;
-
- TypeInstanceTopic(Locator sid) {
- _sids = Collections.singleton(sid);
- }
-
- public Set<Locator> getSubjectIdentifiers() {
- return _sids;
- }
-
- public void addItemIdentifier(Locator arg0) { }
- public void addSubjectIdentifier(Locator arg0) {}
- public void addSubjectLocator(Locator arg0) {}
- public void addType(Topic arg0) {}
- public Set<Occurrence> getOccurrences() { return Collections.emptySet(); }
- public Reifiable getReified() { return null; }
- public Set<Role> getRolesPlayed() { return Collections.emptySet(); }
- public Set<Locator> getSubjectLocators() { return Collections.emptySet(); }
- public Set<Name> getNames() { return Collections.emptySet(); }
- public Set<Topic> getTypes() { return null; }
- public void mergeIn(Topic arg0) { }
- public void remove() throws TopicInUseException { }
- public void removeSubjectIdentifier(Locator arg0) { }
- public void removeSubjectLocator(Locator arg0) { }
- public void removeType(Topic arg0) { }
- public String getId() { return null; }
- public Set<Locator> getItemIdentifiers() { return Collections.emptySet(); }
- public TopicMap getTopicMap() { return null; }
- public void removeItemIdentifier(Locator arg0) { }
- public Name createName(String value, Collection<Topic> scope) { return null; }
- public Name createName(String value, Topic... scope) {return null;}
- public Name createName(Topic type, String value, Collection<Topic> scope) { return null; }
- public Name createName(Topic type, String value, Topic... scope) { return null; }
- public Occurrence createOccurrence(Topic type, Locator value, Collection<Topic> scope) { return null;}
- public Occurrence createOccurrence(Topic type, Locator value, Topic... scope) {return null;}
- public Occurrence createOccurrence(Topic type, String value, Collection<Topic> scope) { return null; }
- public Occurrence createOccurrence(Topic type, String value, Locator datatype, Collection<Topic> scope) { return null; }
- public Occurrence createOccurrence(Topic type, String value, Locator datatype, Topic... scope) { return null; }
- public Occurrence createOccurrence(Topic type, String value, Topic... scope) { return null; }
- public Set<Name> getNames(Topic type) { return null; }
- public Set<Occurrence> getOccurrences(Topic type) { return null;}
- public TopicMap getParent() { return null; }
- public Set<Role> getRolesPlayed(Topic type, Topic assocType) { return null; }
- public Set<Role> getRolesPlayed(Topic type) { return null; }
-
- }
-
- /**
- * Used to represent type-instance relationships which are modelled as
- * [type] property of topics.
- */
- private final class TypeInstanceAssociation implements Association {
-
- final Set<Role> _roles;
-
- TypeInstanceAssociation(Topic type, Topic instance) {
- Role typeRole = new TypeInstanceRole(this, _type, type);
- Role instanceRole = new TypeInstanceRole(this, _instance, instance);
- _roles = new TypeInstanceRoleSet(typeRole, instanceRole);
- }
-
- public Set<Role> getRoles() {
- return _roles;
- }
-
- public Topic getType() {
- return _typeInstance;
- }
-
- public Set<Topic> getRoleTypes() { return null; }
- public Set<Role> getRoles(Topic type) { return null; }
- public void setReifier(Topic reifier) { }
- public void addItemIdentifier(Locator itemIdentifier) { }
- public Set<Locator> getItemIdentifiers() { return Collections.emptySet(); }
- public TopicMap getParent() { return null; }
- public void removeItemIdentifier(Locator itemIdentifier) { }
- public Role createRole(Topic arg0, Topic arg1) { return null; }
- public Topic getReifier() { return null; }
- public void remove() {}
- public void setType(Topic arg0) {}
- public void addTheme(Topic arg0) {}
- public Set<Topic> getScope() { return Collections.emptySet(); }
- public void removeTheme(Topic arg0) {}
- public String getId() { return null; }
- public TopicMap getTopicMap() { return null; }
- }
-
- /**
- * Immutable association role.
- */
- private class TypeInstanceRole implements Role {
- private final Topic _type;
- private final Topic _player;
- private final Association _parent;
-
- TypeInstanceRole(Association parent, Topic type, Topic player) {
- _type = type;
- _player = player;
- _parent = parent;
- List<Role> roles = _topic2Roles.get(player);
- if (roles == null) {
- roles = CollectionFactory.createList();
- _topic2Roles.put(player, roles);
- }
- roles.add(this);
- }
-
- public Topic getType() {
- return _type;
- }
-
- public Topic getPlayer() {
- return _player;
- }
-
- public void setReifier(Topic reifier) { }
- public void addItemIdentifier(Locator itemIdentifier) { }
- public Set<Locator> getItemIdentifiers() { return Collections.emptySet(); }
- public Association getParent() { return _parent; }
- public void removeItemIdentifier(Locator itemIdentifier) { }
- public Association getAssociation() { return _parent; }
- public Topic getReifier() { return null; }
- public void remove() {}
- public void setPlayer(Topic arg0) {}
- public void setType(Topic arg0) {}
- public String getId() { return null; }
- public TopicMap getTopicMap() { return null; }
- }
-
- /**
- * Immutable 'set' of two roles.
- */
- private static class TypeInstanceRoleSet extends AbstractSet<Role> {
-
- private final Role _role1;
- private final Role _role2;
-
- TypeInstanceRoleSet(Role role1, Role role2) {
- _role1 = role1;
- _role2 = role2;
- }
-
- @Override
- public Iterator<Role> iterator() {
- return new TypeInstanceRoleSetIterator();
- }
-
- @Override
- public int size() {
- return 2;
- }
-
- private class TypeInstanceRoleSetIterator implements Iterator<Role> {
-
- private int _idx;
-
- public boolean hasNext() {
- return _idx < 2;
- }
-
- public Role next() {
- if (_idx > 1) {
- throw new NoSuchElementException();
- }
- return 0 == _idx++ ? _role1 : _role2;
- }
-
- public void remove() {
- new UnsupportedOperationException();
- }
- }
- }
-
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|