/* * #! * 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.entry; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.ontopia.topicmaps.utils.ltm.LTMTopicMapReference; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.utils.ImportExportServiceIF; import net.ontopia.topicmaps.utils.ImportExportUtils; import net.ontopia.topicmaps.xml.ExternalReferenceHandlerIF; import net.ontopia.topicmaps.xml.XTMTopicMapReference; import net.ontopia.utils.OntopiaRuntimeException; /** * INTERNAL: TopicMapSourceIF that can reference individual topic map documents * that contained in the classpath and can be loaded by a ClassLoader. The * properties id, title, resourceName, and syntax are the most commonly used. * * @since 5.1 */ public class ResourceTopicMapSource implements TopicMapSourceIF { // initialization of log facility @SuppressWarnings("unused") private static Logger log = LoggerFactory .getLogger(ResourceTopicMapSource.class.getName()); public enum REF_TYPE { XTM, LTM, RDF } protected String id; protected String refid; protected String title; protected String resourceName; protected REF_TYPE ref_type; protected String syntax; protected boolean hidden; protected LocatorIF base_address; protected boolean duplicate_suppression; protected boolean validate; protected ExternalReferenceHandlerIF ref_handler; protected Collection<TopicMapReferenceIF> reflist; /** * INTERNAL: Create a new empty {@link TopicMapSourceIF} instance. */ public ResourceTopicMapSource() { } /** * INTERNAL: Create a new {@link TopicMapSourceIF} instance that references a * resource that can be located in the classpath. An example for a valid * resource name is 'net/ontopia/topicmaps/examples/ItalianOpera.ltm'. * * @param resourceName the name of the topic map resource. */ public ResourceTopicMapSource(String resourceName) { this.resourceName = resourceName; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } /** * INTERNAL: Gets the id of the topic map reference for this topic map source. */ public String getReferenceId() { return refid; } /** * INTERNAL: Sets the id of the topic map reference for this topic map source. */ public void setReferenceId(String refid) { this.refid = refid; } /** * INTERNAL: Returns the syntax of the document. */ public String getSyntax() { return syntax; } /** * INTERNAL: Specifies the syntax of the document. This property will be used * to ensure that the topic map syntax is correctly recognized. The supported * syntaxes are 'XTM', 'LTM', 'RDF' and 'N3'. If the syntax is not specified * the class will attempt to guess it by looking at the address suffix. */ public void setSyntax(String syntax) { this.syntax = syntax.toUpperCase(); try { ref_type = REF_TYPE.valueOf(this.syntax); } catch (IllegalArgumentException e) { ref_type = null; } if (ref_type == null) { if ("N3".equals(this.syntax) || "RDF/XML".equals(this.syntax) || "N-TYPE".equals(this.syntax)) { ref_type = REF_TYPE.RDF; } } } /** * INTERNAL: Gets the resource name of the source topic map. */ public String getResourceName() { return resourceName; } /** * INTERNAL: Sets the resource name of the source topic map. */ public void setResourceName(String resourceName) { this.resourceName = resourceName; } /** * INTERNAL: Gets the base locator of the topic maps retrieved from the * source. */ public LocatorIF getBase() { return base_address; } /** * INTERNAL: Sets the base locator of the topic maps retrieved from the * source. */ public void setBase(LocatorIF base_address) { this.base_address = base_address; } /** * INTERNAL: Gets the base address of the topic maps retrieved from the * source. The notation is assumed to be 'URI'. */ public String getBaseAddress() { return base_address.getAddress(); } /** * INTERNAL: Sets the base address of the topic maps retrieved from the * source. The notation is assumed to be 'URI'. */ public void setBaseAddress(String base_address) { try { this.base_address = new URILocator(base_address); } catch (MalformedURLException e) { throw new OntopiaRuntimeException(e); } } /** * INTERNAL: Gets the duplicate suppression flag. If the flag is true * duplicate suppression is to be performed when loading the topic maps. */ public boolean getDuplicateSuppression() { return duplicate_suppression; } /** * INTERNAL: Sets the duplicate suppression flag. If the flag is true * duplicate suppression is to be performed when loading the topic maps. */ public void setDuplicateSuppression(boolean duplicate_suppression) { this.duplicate_suppression = duplicate_suppression; } /** * INTERNAL: Turn validation of XTM documents according to DTD on or off. The * validation checks if the documents read follow the DTD, and will abort * import if they do not. * * @param validate Will validate if true, will not if false. */ public void setValidation(boolean validate) { this.validate = validate; } /** * INTERNAL: Returns true if validation is on, false otherwise. */ public boolean getValidation() { return validate; } /** * INTERNAL: Sets the external reference handler. */ public void setExternalReferenceHandler(ExternalReferenceHandlerIF ref_handler) { this.ref_handler = ref_handler; } /** * INTERNAL: Gets the external reference handler. The reference handler will * receive notifications on references to external topics and topic maps. */ public ExternalReferenceHandlerIF getExternalReferenceHandler() { return ref_handler; } // ---- public synchronized Collection<TopicMapReferenceIF> getReferences() { if (reflist == null) refresh(); return reflist; } public synchronized void refresh() { if (resourceName == null) throw new OntopiaRuntimeException( "'resourceName' property has not been set."); if (refid == null) refid = id; if (refid == null) throw new OntopiaRuntimeException( "Neither 'id' nor 'referenceId' properties has been set."); // Look at file suffix and guess file syntax. if (syntax == null) { if (resourceName.endsWith(".xtm")) { setSyntax("XTM"); } else if (resourceName.endsWith(".ltm")) { setSyntax("LTM"); } else if (resourceName.endsWith(".rdf")) { setSyntax("RDF"); } else if (resourceName.endsWith(".n3")) { setSyntax("N3"); } } // if we still do not know the syntax -> fail if (syntax == null) { throw new OntopiaRuntimeException("Syntax not specified for '" + resourceName + "'. Please set the 'syntax' parameter."); } // Get URL from ClassLoader URL url; Enumeration<URL> resources; try { resources = getClass().getClassLoader().getResources(resourceName); } catch (IOException e) { throw new OntopiaRuntimeException(e); } if (!resources.hasMoreElements()) { throw new OntopiaRuntimeException("Topic map with resource name '" + resourceName + "' not available in the classpath."); } else { url = resources.nextElement(); } // Use id if title not set. if (title == null) title = id; switch (ref_type) { case XTM: { // Create XTM reference XTMTopicMapReference ref = new XTMTopicMapReference(url, refid, title, base_address); ref.setSource(this); ref.setDuplicateSuppression(duplicate_suppression); ref.setValidation(validate); if (ref_handler != null) ref.setExternalReferenceHandler(ref_handler); reflist = Collections.singleton((TopicMapReferenceIF)ref); } break; case LTM: { // Create LTM reference LTMTopicMapReference ref = new LTMTopicMapReference(url, refid, title, base_address); ref.setDuplicateSuppression(duplicate_suppression); ref.setSource(this); reflist = Collections.singleton((TopicMapReferenceIF)ref); } break; case RDF: { AbstractURLTopicMapReference ref = null; for (ImportExportServiceIF service : ImportExportUtils.getServices()) { if (service.canRead(url.toString())) { ref = service.createReference(url, refid, title, base_address); break; } } if (ref != null) { ref.setDuplicateSuppression(duplicate_suppression); ref.setSource(this); reflist = Collections.singleton((TopicMapReferenceIF)ref); } else { throw new OntopiaRuntimeException("Topic maps RDF syntax " + syntax + " specified, but no RDF import-export service found on the classpath"); } } break; default: throw new OntopiaRuntimeException("Topic maps syntax '" + syntax + "' not supported."); } } @Override public void close() { // Do nothing } public boolean supportsCreate() { return false; } public boolean supportsDelete() { return false; } public TopicMapReferenceIF createTopicMap(String name, String baseAddress) { throw new UnsupportedOperationException( "Can not create a new topic map referenced by a ReferenceTopicMapSource."); } }