/*
* #!
* 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.File;
import java.io.FileFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.ontopia.infoset.core.LocatorIF;
import net.ontopia.infoset.impl.basic.URILocator;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.utils.ResourcesDirectoryReader;
import net.ontopia.utils.URIUtils;
/**
* INTERNAL: Abstract class implementing TopicMapSourceIF; locates
* topic map file references from a given directory on the local file
* system. Only files that match the given suffix are used.<p>
*/
public abstract class AbstractPathTopicMapSource
implements TopicMapSourceIF, FileFilter {
protected String id;
protected String title;
protected String path;
protected String suffix;
protected LocatorIF base_address;
protected boolean duplicate_suppression;
protected boolean hidden;
protected Map<String, TopicMapReferenceIF> refmap;
private FileFilter filter;
public AbstractPathTopicMapSource() {
this.filter = this;
}
public AbstractPathTopicMapSource(String path, String suffix) {
this(path, suffix, null);
this.filter = this;
}
public AbstractPathTopicMapSource(String path, FileFilter filter) {
this(path, filter, null);
}
public AbstractPathTopicMapSource(String path, String suffix,
LocatorIF base_address) {
this.path = path;
this.suffix = suffix;
this.base_address = base_address;
this.filter = this;
}
public AbstractPathTopicMapSource(String path, FileFilter filter,
LocatorIF base_address) {
this.path = path;
this.base_address = base_address;
this.filter = filter;
}
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 path in which the source locates its references.
*/
public String getPath() {
return path;
}
/**
* INTERNAL: Sets the path in which the source locates its references.
*/
public void setPath(String path) {
this.path = path;
}
/**
* INTERNAL: Gets the file suffix that should be used for filtering.
*/
public String getSuffix() {
return suffix;
}
/**
* INTERNAL: Sets the file suffix that should be used for filtering.
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* INTERNAL: Gets the base locator of the topic maps retrieved from
* the source.
*
* @since 1.3.2
*/
public LocatorIF getBase() {
return base_address;
}
/**
* INTERNAL: Sets the base locator of the topic maps retrieved from
* the source.
*
* @since 1.3.2
*/
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'.
*
* @since 1.2.5
*/
public String getBaseAddress() {
return (base_address == null ? null : base_address.getAddress());
}
/**
* INTERNAL: Sets the base address of the topic maps retrieved from
* the source. The notation is assumed to be 'URI'.
*
* @since 1.2.5
*/
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.
*
* @since 1.4.2
*/
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.
*
* @since 1.4.2
*/
public void setDuplicateSuppression(boolean duplicate_suppression) {
this.duplicate_suppression = duplicate_suppression;
}
public synchronized Collection<TopicMapReferenceIF> getReferences() {
if (refmap == null) refresh();
return refmap.values();
}
public boolean supportsCreate() {
return false;
}
public boolean supportsDelete() {
return false;
}
public TopicMapReferenceIF createTopicMap(String name, String baseAddress) {
throw new UnsupportedOperationException();
}
public synchronized void refresh() {
if (path == null)
throw new OntopiaRuntimeException("'path' property has not been set.");
if ((suffix == null) && (filter==this))
throw new OntopiaRuntimeException("'suffix' property for filter has not "+
"been set");
refmap = (path.startsWith("classpath:")) ? refreshFromClasspath() : refreshFromFilesystem();
}
@Override
public void close() {
// Do nothing
}
protected Map<String, TopicMapReferenceIF> refreshFromFilesystem() {
Map<String, TopicMapReferenceIF> newmap = new HashMap<String, TopicMapReferenceIF>();
// Initialize filter
File directory = new File(path);
if (!directory.exists())
throw new OntopiaRuntimeException("Directory " + directory +
" does not exist!");
if (!directory.isDirectory())
throw new OntopiaRuntimeException(directory + " is a file, not a directory");
// Filter filenames
File[] files;
if (filter != null)
files = directory.listFiles(filter);
else
files = directory.listFiles();
// Loop over matched files.
for (int i=0; i < files.length; i++) {
try {
String filename = files[i].getName();
String id = filename;
URL url = URIUtils.toURL(files[i]);
TopicMapReferenceIF ref = createReference(url, id, filename);
if (ref != null)
newmap.put(id, ref);
} catch (MalformedURLException e) {
throw new OntopiaRuntimeException(e);
}
}
return newmap;
}
protected Map refreshFromClasspath() {
if (!filter.equals(this)) {
throw new OntopiaRuntimeException("AbstractPathTopicMapSource.refreshFromClasspath does not yet support filtering");
}
Map newmap = new HashMap();
ResourcesDirectoryReader reader = new ResourcesDirectoryReader(path.substring("classpath:".length()), suffix);
for (String resource : reader.getResources()) {
try {
String filename = resource.substring(resource.lastIndexOf("/") + 1);
String id = filename;
URL url = new URL(URIUtils.getURI("classpath:" + resource).getAddress());
TopicMapReferenceIF ref = createReference(url, id, filename);
if (ref != null) {
newmap.put(id, ref);
}
} catch (MalformedURLException e) {
throw new OntopiaRuntimeException(e);
}
}
return newmap;
}
protected TopicMapReferenceIF createReference(URL url, String id, String title) {
// Do not create new reference if reference is already open.
if (refmap != null) {
TopicMapReferenceIF ref = refmap.get(id);
if (ref != null && ref.isOpen()) {
// Use existing reference
return ref;
}
}
// Create new topic map reference
return createReference(url, id, title, base_address);
}
protected abstract TopicMapReferenceIF createReference(URL url,
String id,
String title,
LocatorIF base_address);
/**
* INTERNAL: Returns the FileFilter used to in the specified
* path.<p>
*
* @since 1.3.4
*/
public FileFilter getFileFilter() {
return filter;
}
/**
* INTERNAL: Sets a FileFilter used to filter the files in the
* specified path.<p>
*
* @param filter a java.io.FileFilter object for filtering the files
*
* @since 1.3.4
*/
public void setFileFilter(FileFilter filter) {
this.filter = filter;
}
/**
* INTERNAL: A file filter method implementation. It accepts a file
* if it is not a directory and the filename ends with the specified
* suffix.
*/
public boolean accept(File file) {
// default FileFilter implementation
return (!file.isDirectory() && file.getName().endsWith(suffix));
}
public boolean getHidden() {
return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
}