/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.topicmaps.xml; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.core.AssociationIF; import net.ontopia.topicmaps.core.OccurrenceIF; import net.ontopia.topicmaps.core.TMObjectIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.core.TopicNameIF; import net.ontopia.topicmaps.core.VariantNameIF; import net.ontopia.utils.TestFileUtils; import net.ontopia.utils.URIUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class XTMExporterTest extends AbstractXMLTestCase { private final static String testdataDirectory = "canonical"; @Before public void setVersion() { version = 1; // ensure export() uses XTM 1.0 } // --- Test cases @Test public void testEncoding() throws IOException { TopicMapIF tm = load(testdataDirectory, "in", "latin1.xtm"); File out = TestFileUtils.getTestOutputFile(testdataDirectory, "out", "tmp-latin1.xtm"); XTMTopicMapWriter writer = new XTMTopicMapWriter(out, "iso-8859-1"); writer.setVersion(1); writer.write(tm); TopicMapIF tm2 = new XTMTopicMapReader(out).read(); // check for a topic that has at least one name for (Object obj : tm2.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { TopicNameIF bn = names.iterator().next(); Assert.assertTrue("base name value did not survive encoding change roundtrip", bn.getValue().equals("B\u00E6 b\u00E6 lille lam, har du noe \u00F8l")); } } } @Test public void testEncoding2() throws IOException { TopicMapIF tm = load(testdataDirectory, "in", "latin1.xtm"); File out = TestFileUtils.getTestOutputFile(testdataDirectory, "out", "tmp-utf-8.xtm"); XTMTopicMapWriter writer = new XTMTopicMapWriter(out); writer.setVersion(1); writer.write(tm); TopicMapIF tm2 = new XTMTopicMapReader(out).read(); // check for a topic that has at least one name for (Object obj : tm2.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { TopicNameIF bn = names.iterator().next(); Assert.assertTrue("base name value did not survive encoding change roundtrip", bn.getValue().equals("B\u00E6 b\u00E6 lille lam, har du noe \u00F8l")); } } } /// id preservation @Test public void testPreservesTopicmapID() throws IOException { prepareTopicMap(); topicmap.addItemIdentifier(sourceLoc); reload(); check("topic map", topicmap); } @Test public void testPreservesTopicID() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); topic.addItemIdentifier(sourceLoc); reload(); check("topic", getTopicById(topicmap, "id")); } @Test public void testPreservesTopicID2() throws IOException { prepareTopicMap(); LocatorIF loc = tmbase.resolveAbsolute("#ide"); TopicIF topic = builder.makeTopic(); topic.addItemIdentifier(loc); reload(); check("topic", getTopicById(topicmap, "ide"), loc); } @Test public void testPreservesBasenameID() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "bongomonog"); bn.addItemIdentifier(sourceLoc); reload(); // get a topic with at least one name topic = null; for (Object obj : topicmap.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { topic = (TopicIF) obj; break; } } Assert.assertNotNull("no topic found with a topic name after reload", topic); check("base name", (TopicNameIF) topic.getTopicNames().iterator().next()); } @Test public void testPreservesVariantnameID() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "bongomonog"); VariantNameIF vn = builder.makeVariantName(bn, "bongomonog"); vn.addItemIdentifier(sourceLoc); reload(); // get a topic with at least one name topic = null; for (Object obj : topicmap.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { topic = (TopicIF) obj; break; } } Assert.assertNotNull("no topic found with a topic name after reload", topic); bn = (TopicNameIF) topic.getTopicNames().iterator().next(); check("variant name", (VariantNameIF) bn.getVariants().iterator().next()); } @Test public void testPreservesOccurrenceID() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); LocatorIF loc = new URILocator("http://www.ontopia.net"); topic.addSubjectIdentifier(loc); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, loc); occ.addItemIdentifier(sourceLoc); reload(); topic = topicmap.getTopicBySubjectIdentifier(loc); check("occurrence", (OccurrenceIF) topic.getOccurrences().iterator().next()); } // @Test // public void testPreservesAssociationID() throws IOException { // prepareTopicMap(); // AssociationIF assoc = builder.makeAssociation(builder.makeTopic()); // assoc.addItemIdentifier(sourceLoc); // builder.makeAssociationRole(assoc); // reload(); // assoc = (AssociationIF) topicmap.getAssociations().iterator().next(); // check("assoc", assoc); // } /// empty strings and nulls @Test public void testEmptyTopicName() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, ""); reload(); // get a topic with at least one name topic = null; for (Object obj : topicmap.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { topic = (TopicIF) obj; break; } } Assert.assertNotNull("no topic found with a topic name after reload", topic); Iterator it = topic.getTopicNames().iterator(); Assert.assertTrue("empty base name lost on export and re-import", it.hasNext()); bn = (TopicNameIF) it.next(); Assert.assertTrue("empty base name has '" + bn.getValue() + "' instead of empty string on re-import", bn.getValue() != null && bn.getValue().equals("")); } @Test public void testEmptyVariantName() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicNameIF bn = builder.makeTopicName(topic, "empty"); VariantNameIF vn = builder.makeVariantName(bn, ""); reload(); // get a topic with at least one name topic = null; for (Object obj : topicmap.getTopics()) { Collection<TopicNameIF> names = ((TopicIF) obj).getTopicNames(); if (names != null && names.size() > 0) { topic = (TopicIF) obj; break; } } Assert.assertNotNull("no topic found with a topic name after reload", topic); bn = (TopicNameIF) topic.getTopicNames().iterator().next(); Iterator it = bn.getVariants().iterator(); Assert.assertTrue("empty variant name lost on export and re-import", it.hasNext()); vn = (VariantNameIF) it.next(); Assert.assertTrue("empty variant name has '" + vn.getValue() + "' instead of empty string on re-import", vn.getValue() != null && vn.getValue().equals("")); } @Test public void testEmptyOccurrence() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); LocatorIF loc = new URILocator("http://www.ontopia.net"); topic.addSubjectIdentifier(loc); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, ""); reload(); topic = topicmap.getTopicBySubjectIdentifier(loc); Iterator it = topic.getOccurrences().iterator(); Assert.assertTrue("empty occurrence lost on export and re-import", it.hasNext()); occ = (OccurrenceIF) it.next(); Assert.assertTrue("empty occurrence has '" + occ.getValue() + "' instead of empty string on re-import", occ.getValue() != null && occ.getValue().equals("")); } @Test public void testNullOccurrence() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); LocatorIF psi = URILocator.create("test:1"); topic.addSubjectIdentifier(psi); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, ""); reload(); topic = topicmap.getTopicBySubjectIdentifier(psi); Iterator it = topic.getOccurrences().iterator(); Assert.assertTrue("null occurrence lost on export and re-import", it.hasNext()); occ = (OccurrenceIF) it.next(); Assert.assertTrue("null occurrence has '" + occ.getValue() + "' instead of empty string on re-import", occ.getValue() != null && occ.getValue().equals("")); } /// id collisions @Test public void testDuplicateIDs() throws IOException { // importing and exporting this file causes duplicate IDs // these are detected on re-import tmfile = TestFileUtils.getTestOutputFile(testdataDirectory, "out", "duplicate-ids.xtm"); topicmap = load("various", "duplicate-ids.xtm"); reload(); } /// skipping ids @Test public void testOmittingIDs() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, "huhei"); XTMTopicMapWriter writer = new XTMTopicMapWriter(tmfile); writer.setAddIds(false); writer.write(topicmap); XTMTopicMapReader reader = new XTMTopicMapReader(tmfile); topicmap = reader.read(); Iterator it = topicmap.getTopics().iterator(); while (it.hasNext()) { topic = (TopicIF) it.next(); if (!topic.getOccurrences().isEmpty()) break; } occ = (OccurrenceIF) topic.getOccurrences().iterator().next(); Assert.assertTrue("occurrence had ID!", occ.getItemIdentifiers().isEmpty()); } @Test public void testOmittingIDs2() throws IOException { prepareTopicMap(); TopicIF topic = builder.makeTopic(); TopicIF otype = builder.makeTopic(); OccurrenceIF occ = builder.makeOccurrence(topic, otype, "huhei"); TopicIF topic2 = builder.makeTopic(); occ.setReifier(topic2); XTMTopicMapWriter writer = new XTMTopicMapWriter(tmfile); writer.setAddIds(false); writer.write(topicmap); XTMTopicMapReader reader = new XTMTopicMapReader(tmfile); topicmap = reader.read(); Iterator it = topicmap.getTopics().iterator(); while (it.hasNext()) { topic = (TopicIF) it.next(); if (!topic.getOccurrences().isEmpty()) break; } occ = (OccurrenceIF) topic.getOccurrences().iterator().next(); topic2 = occ.getReifier(); Assert.assertTrue("reification relationship was lost on export and reimport", topic2 != null); } // motivated by bug #1426 @Test public void testOmittingIDs3() throws IOException { prepareTopicMap(); sourceLoc = tmbase.resolveAbsolute("#--reified--id"); topicmap.addItemIdentifier(sourceLoc); reload(); // screwup most likely causes crash here Assert.assertTrue("topic map retained syntactically invalid id", !topicmap.getItemIdentifiers().contains(sourceLoc)); } @Test public void testOmittingIDsPreserveReification() throws IOException { prepareTopicMap(); TopicIF reifier = builder.makeTopic(); topicmap.setReifier(reifier); reload(); // now for the real test reifier = topicmap.getReifier(); Assert.assertTrue("reification connection broken on export", reifier != null); } /// exporting invalid structures @Test public void testEmptyAssociation() throws IOException { prepareTopicMap(); AssociationIF assoc = builder.makeAssociation(builder.makeTopic()); reload(true); // validation will make this fail if bug #1024 is present } @Test public void testBug654OnRDBMS() throws IOException { // this test verifies that not are source locators of the form // id34234 not used to form IDs on export, but neither are those // of the form idT34234 prepareTopicMap(); String tid = "idT234212"; TopicIF topic = builder.makeTopic(); topic.addItemIdentifier(tmbase.resolveAbsolute("#" + tid)); XTMTopicMapExporter exp = new XTMTopicMapExporter(); String id = exp.getElementId(topic); Assert.assertTrue("unacceptable ID used", !id.equals(tid)); } // --- Internal helper methods private void reload() throws IOException { reload(false); } private void reload(boolean validate) throws IOException { export(); XTMTopicMapReader reader = new XTMTopicMapReader(tmfile); reader.setValidation(validate); topicmap = reader.read(); } private void check(String what, TMObjectIF obj) { check(what, obj, sourceLoc); } private void check(String what, TMObjectIF obj, LocatorIF srcloc) { Iterator it = obj.getItemIdentifiers().iterator(); Assert.assertTrue(what + " id lost on export and re-import", it.hasNext()); Assert.assertTrue(what + " source locator corrupted", it.next().equals(srcloc)); } private TopicMapIF load(String dir, String subdir, String file) throws IOException { return load(dir + "/" + subdir, file); } private TopicMapIF load(String dir, String file) throws IOException { return new XTMTopicMapReader(URIUtils.getURI(TestFileUtils.getTestInputFile(dir, file))).read(); } }