/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Kowari Metadata Store.
*
* The Initial Developer of the Original Code is Plugged In Software Pty
* Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions
* created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
* Plugged In Software Pty Ltd. All Rights Reserved.
*
* Contributor(s):
* getModel() contributed by Netymon Pty Ltd on behalf of
* The Australian Commonwealth Government under contract 4500507038.
*
* [NOTE: The text of this Exhibit A may differ slightly from the text
* of the notices in the Source Code files of the Original Code. You
* should use the text of this Exhibit A rather than the text found in the
* Original Code Source Code for Your Modifications.]
*
*/
package org.mulgara.resolver.filesystem;
// Java 2 standard packages
import java.io.*;
import java.net.*;
import javax.transaction.xa.XAResource;
// Third party packages
import org.apache.log4j.Logger;
import org.jrdf.graph.URIReference;
import org.jrdf.graph.Node;
import gnu.trove.TLongObjectHashMap;
// Locally written packages
import org.mulgara.query.*;
import org.mulgara.query.rdf.URIReferenceImpl;
import org.mulgara.resolver.spi.*;
import org.mulgara.store.tuples.Tuples;
/**
* Resolves constraints against file system data specified by the included and
* excluded directories within the model.
*
* @created 2004-11-17
*
* @author Mark Ludlow
*
* @version $Revision: 1.9 $
*
* @modified $Date: 2005/02/22 08:16:13 $
*
* @maintenanceAuthor $Author: newmana $
*
* @company <a href="mailto:info@PIsoftware.com">Plugged In Software</a>
*
* @copyright © 2004 <a href="http://www.PIsoftware.com/">Plugged In
* Software Pty Ltd</a>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public class FileSystemResolver implements Resolver {
/** Logger */
private static final Logger log = Logger.getLogger(FileSystemResolver.class);
/** System model's type URI */
private URI systemModelTypeURI;
/** URI representing the file system model's type */
private URI modelTypeURI;
/** Node id for the file system model */
@SuppressWarnings("unused")
private long fileSystemNode;
/** Node ID for the rdf:type node */
@SuppressWarnings("unused")
private long rdfType;
/** Node ID for the inclusion predicate */
private long includeNode;
/** Node ID for the exclusion predicate */
private long excludeNode;
/** The system model's resolver */
private Resolver systemResolver;
/** Cache for the file system */
private TLongObjectHashMap<Resolution> fileSystemCache;
/** Node id for the system model */
@SuppressWarnings("unused")
private long systemModel;
/** Resolver session for node resolution */
private ResolverSession resolverSession;
/**
* Constructor.
*
* @param resolverSession The session in which the resolver exists
* @param systemResolver The resolver used for the system model
* @param rdfType The rdf:type predicate
* @param systemModel The system model node id
* @param systemModelType The system model's type node id
* @param modelTypeURI The URI representing the file system's model type
* @param fileSystemNode The node id for the file system model
* @param includeNode The inclusion predicate node id
* @param excludeNode The exclusion predicate node id
*
* @throws ResolverFactoryException
*/
FileSystemResolver(ResolverSession resolverSession, Resolver systemResolver,
long rdfType, long systemModel, long systemModelType,
URI modelTypeURI, long fileSystemNode, long includeNode,
long excludeNode) throws ResolverFactoryException {
// Validate "modelType" parameter
if (modelTypeURI == null) {
throw new IllegalArgumentException("Graph type can't be null");
}
// Store the global variable values
this.systemResolver = systemResolver;
this.modelTypeURI = modelTypeURI;
this.fileSystemNode = fileSystemNode;
this.rdfType = rdfType;
this.includeNode = includeNode;
this.excludeNode = excludeNode;
this.systemModel = systemModel;
this.resolverSession = resolverSession;
// Initialise the cache
this.fileSystemCache = new TLongObjectHashMap<Resolution>();
// Container for our system model's type node
Node systemModelTypeURIRef = null;
try {
// Create an actual node for the system model type
systemModelTypeURIRef = resolverSession.globalize(systemModelType);
} catch (GlobalizeException globaliseException) {
throw new ResolverFactoryException("Failed to globalize SystemModel " +
"Type for file system model",
globaliseException);
}
if (systemModelTypeURIRef instanceof URIReference) {
// If we have a uri reference then store the system type's URI
this.systemModelTypeURI = ((URIReference) systemModelTypeURIRef).getURI();
} else {
// We cannot handle literals for the system model
throw new ResolverFactoryException("systemModelType not a URIRef " +
systemModelTypeURIRef);
}
/**
* Retrieves a transaction manager to help sequence resolution transactions.
*
* @return The transaction manager
*/
}
public XAResource getXAResource() {
return new DummyXAResource(10);
}
/**
* Create a model by treating the <var>model</var> as the {@link URL} of an
* RDF document and downloading it into the database.
*
* @param model {@inheritDoc}. In this case, it should be the {@link URL} of
* a file system type model
* @param modelTypeURI {@inheritDoc}. The type must match the value of
* {@link #modelTypeURI}
*
* @throws ResolverException
* @throws LocalizeException
*/
public void createModel(long model, URI modelTypeURI) throws
ResolverException, LocalizeException {
if (log.isDebugEnabled()) {
log.debug("Create FileSystem model " + model + " of type " +
modelTypeURI);
}
// Validate the "modelTypeURI" parameter
if (!modelTypeURI.equals(this.modelTypeURI)) {
throw new ResolverException(
"Can't create " + model + " of type " + modelTypeURI +
", which was never registered by " + getClass());
}
// Obtain the node representing the ?def URI of the model
URIReference defNode = new URIReferenceImpl(definitionURI(model));
// Container for our definition model
long defModel = 0;
try {
// Localise the definition node
defModel = resolverSession.localizePersistent(defNode);
} catch (LocalizeException localiseException) {
throw new ResolverException("Error localizing uri when creating " +
"file system definition model",
localiseException);
}
// Create the definition model
systemResolver.createModel(defModel, systemModelTypeURI);
// Add the definition model to the system model
//addModelToSystemModel(model, modelTypeURI);
}
/**
* @throws ResolverException always -- not yet implemented
*/
public void writeStringPool(Writer w) throws IOException, ResolverException {
throw new ResolverException("Backup of string pool not implemented");
}
/**
* Remove the cached model containing the contents of a URL.
*
* @param model The node id of the model we are removing
*
* @throws ResolverException
*/
public void removeModel(long model) throws ResolverException {
if (log.isDebugEnabled()) {
log.debug("Remove FileSystem model " + model);
}
// Container for the definition model node id
long defModel = 0;
try {
// Obtain the node id of the definition model
defModel = resolverSession.lookupPersistent(new URIReferenceImpl(
definitionURI(model)));
} catch (LocalizeException localiseException) {
throw new ResolverException("Error localizing uri when removing " +
"file system definition model",
localiseException);
}
// Remove the definition model
systemResolver.removeModel(defModel);
}
/**
* Insert or delete RDF statements in a model at a URL.
*
* @param model The model we are modifying
* @param statements The statements we are adding or deleting
* @param occurs Whether the statements should occur or not occur in the model
*
* @throws ResolverException
*/
public void modifyModel(long model, Statements statements, boolean occurs) throws
ResolverException {
if (log.isDebugEnabled()) {
if (occurs) {
log.debug("Asserting " + statements + " in " + model);
} else {
log.debug("Denying " + statements + " in " + model);
}
}
// Validate "statements" parameter
if (statements == null) {
throw new IllegalArgumentException("Null \"statements\" parameter");
}
// Container for our definition model node id
long defModel = 0;
try {
// Obtain the node id of our definition model
defModel = resolverSession.lookupPersistent(new URIReferenceImpl(
definitionURI(model)));
} catch (LocalizeException localiseException) {
throw new ResolverException("Error localizing uri when modifying file " +
"system definition model", localiseException);
}
// Modify the definition model
systemResolver.modifyModel(defModel, statements, occurs);
}
/**
* Resolve a constraint against a model on the Java heap.
*
* @param constraint The constraint to resolve against the model
*
* @return The resolution of our constraint against the model
*
* @throws QueryException
*/
public Resolution resolve(Constraint constraint) throws QueryException {
if (log.isDebugEnabled()) {
log.debug("!! Resolve " + constraint);
}
// Obtain the model of the constraint
ConstraintElement modelElem = constraint.getModel();
// Verify our model node is a local node
if (!(modelElem instanceof LocalNode)) {
if (log.isDebugEnabled()) log.debug("Ignoring solutions for " + constraint);
return new EmptyResolution(constraint, false);
}
// Get the model id for the node
long model = ((LocalNode) modelElem).getValue();
// Container for our definition model node id
long defModel = 0;
try {
// Obtain the definition mode node id
defModel = resolverSession.lookupPersistent(new URIReferenceImpl(
definitionURI(model)));
} catch (LocalizeException localiseException) {
throw new QueryException("Graph " + model +
" did not exist in FileSystem" +
" expansion", localiseException);
} catch (ResolverException resolverException) {
throw new QueryException("Failed to find FileSystem definition node id",
resolverException.getCause());
}
if (!fileSystemCache.containsKey(defModel)) {
// Cache the results of the resolution against the model
fileSystemCache.put(defModel,
fetchFileSystemResolution(defModel, constraint));
}
// Retrieve the definition for our file system
return fetchFileSystemResolution(defModel, constraint);
}
/**
* Fetches the resolution object produced by constraining the tuples produced
* by the included and excluded file systems.
*
* @param defModel The definition model's node id
* @param constraint The constraint we are constraining our results against
*
* @return The files matching the constraints in the included file systems
* exluding those that are excluded
*
* @throws QueryException
*/
private Resolution fetchFileSystemResolution(long defModel,
Constraint constraint) throws
QueryException {
// Obtain all included file systems in the model
Tuples includeTuples = systemResolver.resolve(new ConstraintImpl(
new Variable("fileSystemModel"),
new LocalNode(includeNode),
new Variable("fileSystemRef"),
new LocalNode(defModel)));
// Obtain all excluded file systems in the model
Tuples excludeTuples = systemResolver.resolve(new ConstraintImpl(
new Variable("fileSystemModel"),
new LocalNode(excludeNode),
new Variable("fileSystemRef"),
new LocalNode(defModel)));
if (log.isDebugEnabled()) {
log.debug("-- Including the following file systems: " + includeTuples);
log.debug("-- Excluding the following file systems: " + excludeTuples);
}
// Container for our statements object
FileSystemStatements statements = null;
try {
// Obtain the statements about the file systems included in the model
statements = new FileSystemStatements(includeTuples,
excludeTuples,
resolverSession);
} catch (TuplesException tuplesException) {
throw new QueryException(
"Unable to create statements from file system data",
tuplesException);
}
return new StatementsWrapperResolution(constraint, statements, true);
}
private URI definitionURI(long fileSystemNode) throws ResolverException {
try {
Node modelNode = resolverSession.globalize(fileSystemNode);
if (modelNode instanceof URIReference) {
return definitionURI(((URIReference) modelNode).getURI());
} else {
throw new ResolverException("FileSystemNode not URI");
}
} catch (GlobalizeException eg) {
throw new ResolverException("Failed to globalize FileSystem", eg);
}
}
private URI definitionURI(URI fileSystemURI) throws ResolverException {
try {
URI defURI = new URI(fileSystemURI.getScheme(),
fileSystemURI.getAuthority(),
fileSystemURI.getPath(),
"def",
fileSystemURI.getFragment());
if (log.isInfoEnabled()) {
log.info("Creating defModel with uri = " + defURI);
}
return defURI;
} catch (URISyntaxException eu) {
throw new ResolverException("Invalid URI", eu);
}
}
public void abort() {}
}