/*
* #!
* 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.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import net.ontopia.infoset.core.LocatorIF;
import net.ontopia.topicmaps.core.TopicMapImporterIF;
import net.ontopia.topicmaps.core.TopicMapReaderIF;
import net.ontopia.topicmaps.core.TopicMapWriterIF;
import net.ontopia.topicmaps.impl.rdbms.RDBMSTopicMapReader;
import net.ontopia.topicmaps.utils.ctm.CTMTopicMapReader;
import net.ontopia.topicmaps.utils.ltm.LTMTopicMapReader;
import net.ontopia.topicmaps.utils.ltm.LTMTopicMapWriter;
import net.ontopia.topicmaps.xml.TMXMLReader;
import net.ontopia.topicmaps.xml.TMXMLWriter;
import net.ontopia.topicmaps.xml.XTM2TopicMapWriter;
import net.ontopia.topicmaps.xml.XTMTopicMapReader;
import net.ontopia.topicmaps.xml.XTMTopicMapWriter;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.utils.ServiceUtils;
import net.ontopia.utils.URIUtils;
import org.apache.commons.collections4.set.UnmodifiableSet;
import org.slf4j.LoggerFactory;
/**
* PUBLIC: Utilities for importing and exporting topic maps.
*
* @since 1.2
*/
public class ImportExportUtils {
private static Set<ImportExportServiceIF> services;
static {
loadServices();
}
private static void loadServices() {
try {
services = ServiceUtils.loadServices(ImportExportServiceIF.class);
} catch (IOException ex) {
LoggerFactory.getLogger(ImportExportUtils.class).error("Could not load import-export services", ex);
}
}
/**
* Returns the loaded ImportExportServiceIF services.
* @return the loaded ImportExportServiceIF services.
*/
@SuppressWarnings("unchecked")
public static Set<ImportExportServiceIF> getServices() {
return UnmodifiableSet.unmodifiableSet(services);
}
/**
* PUBLIC: Given the topic map store properties file and file name
* or URL of a topic map, returns a topic map reader of the right
* class. Uses the file extension to determine what reader to
* create. Supports the suffixes '.xtm' and '.ltm' and URI schemes
* 'x-ontopia:tm-rdbms:'.
*
* @since 1.2.4
*/
public static TopicMapReaderIF getReader (String propfile,
String filename_or_url) {
if (filename_or_url.startsWith ("x-ontopia:tm-rdbms:"))
return new RDBMSTopicMapReader (propfile, getTopicMapId (filename_or_url));
// Otherwise fall back to the property-less getReader method
return getReader (filename_or_url);
}
/**
* PUBLIC: Given the topic map store properties and file name or URL
* of a topic map, returns a topic map reader of the right
* class. Uses the file extension to determine what reader to
* create. Supports the suffixes '.xtm' and '.ltm' and URI schemes
* 'x-ontopia:tm-rdbms:'.
*
* @since 1.2.4
*/
public static TopicMapReaderIF getReader (Map<String, String> properties,
String filename_or_url) {
if (filename_or_url.startsWith ("x-ontopia:tm-rdbms:"))
return new RDBMSTopicMapReader (properties,
getTopicMapId (filename_or_url));
// Otherwise fall back to the property-less getReader method
return getReader (filename_or_url);
}
/**
* PUBLIC: Given a file reference to a topic map, returns a topic
* map reader of the right class. Uses the file extension to
* determine what reader to create. Supports '.xtm', and '.ltm'.
*
* @since 2.0
*/
public static TopicMapReaderIF getReader (java.io.File file)
throws java.io.IOException {
return getReader (file.toURL ().toExternalForm ());
}
/**
* PUBLIC: Given the file name or URL of a topic map, returns a
* topic map reader of the right class. Uses the file extension to
* determine what reader to create. Supports '.xtm', and '.ltm'.
*/
public static TopicMapReaderIF getReader (String filename_or_url) {
return getReader (URIUtils.getURI (filename_or_url));
}
/**
* PUBLIC: Given a locator referring to a topic map, returns a topic
* map reader of the right class. Uses the file extension to
* determine what reader to create. Supports '.xtm', '.tmx', and
* '.ltm'.
*
* @since 2.0
*/
public static TopicMapReaderIF getReader (LocatorIF url) {
String address = url.getAddress ();
if (address.startsWith ("x-ontopia:tm-rdbms:"))
return new RDBMSTopicMapReader (getTopicMapId (address));
else if (address.endsWith (".xtm"))
return new XTMTopicMapReader (url);
else if (address.endsWith (".ltm"))
return new LTMTopicMapReader (url);
else if (address.endsWith (".tmx"))
return new TMXMLReader (url);
else if (address.endsWith (".xml"))
return new TMXMLReader(url);
else if (address.endsWith (".ctm"))
return new CTMTopicMapReader(url);
else {
for (ImportExportServiceIF service : services) {
if (service.canRead(address)) {
return service.getReader(address);
}
}
// fallback
return new XTMTopicMapReader (url);
}
}
/**
* PUBLIC: Given the file name or URL of a topic map, returns a
* topic map importer of the right class. Uses the file extension to
* determine what importer to create. Supports '.xtm', and '.ltm'.
*/
public static TopicMapImporterIF getImporter (String filename_or_url) {
return getImporter (URIUtils.getURI (filename_or_url));
}
/**
* PUBLIC: Given a locator referring to a topic map, returns a topic
* map reader of the right class. Uses the file extension to
* determine what reader to create. Supports '.xtm', '.tmx', and
* '.ltm'.
*
* @since 2.0
*/
public static TopicMapImporterIF getImporter (LocatorIF url) {
String address = url.getAddress ();
if (address.endsWith (".xtm"))
return new XTMTopicMapReader (url);
else if (address.endsWith (".ltm"))
return new LTMTopicMapReader (url);
else if (address.endsWith (".tmx"))
return new TMXMLReader (url);
else if (address.endsWith (".xml"))
return new TMXMLReader(url);
else if (address.endsWith (".ctm"))
return new CTMTopicMapReader(url);
else {
for (ImportExportServiceIF service : services) {
if (service.canRead(address)) {
return service.getImporter(address);
}
}
// fallback
return new XTMTopicMapReader (url);
}
}
/**
* PUBLIC: Given the file name of a topicmap, returns a topicmap
* writer of the right class. Uses the file extension to determine
* what writer to create. Supports '.xtm' and '.tmx'. If the suffix
* is unknown, the default writer is a XTM writer.
*/
public static TopicMapWriterIF getWriter (String tmfile)
throws java.io.IOException {
if (tmfile.endsWith (".ltm"))
return new LTMTopicMapWriter (new FileOutputStream (tmfile));
else if (tmfile.endsWith (".tmx"))
return new TMXMLWriter (tmfile);
else if (tmfile.endsWith (".xtm1"))
return new XTMTopicMapWriter (new File (tmfile));
else {
for (ImportExportServiceIF service : services) {
if (service.canWrite(tmfile)) {
return service.getWriter(new FileOutputStream(tmfile));
}
}
// fallback
return new XTM2TopicMapWriter (new File (tmfile));
}
}
/**
* PUBLIC: Given the file name of a topicmap, returns a topicmap writer of the
* right class. Uses the file extension to determine what writer to create.
* Supports '.xtm' and '.tmx'. If the suffix is unknown, the default
* writer is a XTM writer.
*/
public static TopicMapWriterIF getWriter (String tmfile, String encoding)
throws java.io.IOException {
if (encoding == null)
return getWriter(tmfile);
if (tmfile.endsWith(".tmx"))
return new TMXMLWriter (tmfile, encoding);
else if (tmfile.endsWith(".xtm1"))
return new XTMTopicMapWriter(new File(tmfile), encoding);
else
return new XTM2TopicMapWriter(new File(tmfile), encoding);
}
/**
* INTERNAL: Gets the numeric topic map id from an RDBMS URI or a
* simple topic map id reference. Examples: x-ontopia:tm-rdbms:123,
* x-ontopia:tm-rdbms:M123, 123 and M123.
*/
public static long getTopicMapId (String address) {
int offset = 0;
if (address.startsWith("M"))
offset = 1;
else if (address.startsWith("x-ontopia:tm-rdbms:")) {
// Syntax: x-ontopia:tm-rdbms:12345
offset = "x-ontopia:tm-rdbms:".length ();
// Ignore M suffix on topic map id
if (address.charAt (offset) == 'M')
offset = offset + 1;
}
try {
return Long.parseLong (address.substring (offset));
} catch (NumberFormatException e) {
throw new OntopiaRuntimeException ("'" + address
+ " is not a valid rdbms topic map URI.");
}
}
}