/*
* #!
* 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.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
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 by their URL address. The properties id, title, url, and
* syntax are the most commonly used. The syntaxes XTM, HyTM, and LTM
* are currently supported.<p>
*
* @since 2.0
*/
public class URLTopicMapSource implements TopicMapSourceIF {
// initialization of log facility
private static Logger log = LoggerFactory.getLogger(URLTopicMapSource.class.getName());
protected String id;
protected String refid;
protected String title;
protected String url;
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;
public URLTopicMapSource() {
}
public URLTopicMapSource(String url) {
this.url = url;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* 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;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
/**
* 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', 'HyTM', and
* 'LTM'. 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;
}
/**
* INTERNAL: Gets the URL of the source topic map.
*/
public String getUrl() {
return url;
}
/**
* INTERNAL: Sets the URL of the source topic map.
*/
public void setUrl(String url) {
this.url = url;
}
/**
* 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 (url == null)
throw new OntopiaRuntimeException("'url' 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 (url.endsWith(".xtm"))
syntax = "XTM";
else if (url.endsWith(".ltm"))
syntax = "LTM";
else if (url.endsWith(".rdf"))
syntax = "RDF";
else if (url.endsWith(".n3"))
syntax = "N3";
}
// Create proper URL object
URL url2;
try {
url2 = new URL(url);
} catch (MalformedURLException e) {
throw new OntopiaRuntimeException(e);
}
// Use id if title not set.
if (title == null)
title = id;
if (syntax == null) {
throw new OntopiaRuntimeException("Syntax not specified for '" + url + "'. Please set the 'syntax' parameter.");
} else if (syntax.equalsIgnoreCase("XTM")) {
// Create XTM reference
XTMTopicMapReference ref = new XTMTopicMapReference(url2, 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);
} else if (syntax.equalsIgnoreCase("LTM")) {
// Create LTM reference
LTMTopicMapReference ref = new LTMTopicMapReference(url2, refid, title, base_address);
ref.setDuplicateSuppression(duplicate_suppression);
ref.setSource(this);
reflist = Collections.singleton((TopicMapReferenceIF)ref);
} else if (syntax.equalsIgnoreCase("RDF/XML") ||
syntax.equalsIgnoreCase("RDF") ||
syntax.equalsIgnoreCase("N3") ||
syntax.equalsIgnoreCase("N-TRIPLE")) {
// Create RDF reference
AbstractURLTopicMapReference ref = null;
for (ImportExportServiceIF service : ImportExportUtils.getServices()) {
if (service.canRead(url.toString())) {
ref = service.createReference(url2, 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");
}
} else
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();
}
public boolean getHidden() {
return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
}