[Mulgara-svn] r347 - in branches/nw-interface/src/jar: itql/java/org/mulgara itql/java/org/mulgara/itql itql/java/org/mulgara/query itql/java/org/mulgara/query/ast jrdf/java/org/mulgara/jrdf query/java/org/mulgara/query query/java/org/mulgara/server
pag at mulgara.org
pag at mulgara.org
Fri Aug 10 21:12:10 UTC 2007
Author: pag
Date: 2007-08-10 16:12:09 -0500 (Fri, 10 Aug 2007)
New Revision: 347
Added:
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/Interpreter.java
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/URIUtil.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/ApplyRules.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CommandAst.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Commit.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CreateGraph.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/DropGraph.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Help.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/LocalAst.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Quit.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Rollback.java
branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/SetUser.java
Modified:
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ConstraintExpressionBuilder.java
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ItqlInterpreter.java
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ModelExpressionBuilder.java
branches/nw-interface/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java
branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFGraphUnitTest.java
branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFLocalGraphUnitTest.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelExpression.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelIntersection.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelLiteral.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelOperation.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelPartition.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelResource.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelUnion.java
branches/nw-interface/src/jar/query/java/org/mulgara/query/Query.java
branches/nw-interface/src/jar/query/java/org/mulgara/server/Session.java
Log:
Copied ItqlInterpreter into TqlInterpreter, and am slowly converting actions into an AST structure (to be run independently of the parsing process). The AST is in a new package called org.mulgara.query.ast. TqlInterpreter is a long way from compiling, but on its way.
Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ConstraintExpressionBuilder.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ConstraintExpressionBuilder.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ConstraintExpressionBuilder.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -100,7 +100,7 @@
/**
* The iTQL interpreter
*/
- private ItqlInterpreter interpreter;
+ private Interpreter interpreter;
/**
* Create a new builder. Requires methods on the interpreter in order to
@@ -108,7 +108,7 @@
*
* @param newInterpreter the interpreter to use.
*/
- public ConstraintExpressionBuilder(ItqlInterpreter newInterpreter) {
+ public ConstraintExpressionBuilder(Interpreter newInterpreter) {
interpreter = newInterpreter;
}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/Interpreter.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/Interpreter.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/Interpreter.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,104 @@
+package org.mulgara.itql;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.mulgara.itql.node.PLiteral;
+import org.mulgara.itql.node.TResource;
+import org.mulgara.itql.node.Token;
+import org.mulgara.query.Query;
+import org.mulgara.query.QueryException;
+import org.mulgara.query.Variable;
+import org.mulgara.query.rdf.LiteralImpl;
+
+
+/**
+ * This interface defines the namespaces used while interpreting RDF code.
+ * @author pag
+ *
+ */
+public interface Interpreter {
+
+ //
+ // Constants
+ //
+ /** The rdf namespace prefix. */
+ public static final String RDF = "rdf";
+
+ /** The rdfs namespace prefix. */
+ public static final String RDFS = "rdfs";
+
+ /** The owl namespace prefix. */
+ public static final String OWL = "owl";
+
+ /** The mulgara namespace prefix. */
+ public static final String MULGARA = "mulgara";
+
+ /** The krule namespace prefix. */
+ public static final String KRULE = "krule";
+
+ /** The URI of the rdf namespace. */
+ public static final String RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+
+ /** The URI of the rdfs namespace. */
+ public static final String RDFS_NS = "http://www.w3.org/2000/01/rdf-schema#";
+
+ /** The URI of the owl namespace. */
+ public static final String OWL_NS = "http://www.w3.org/2002/07/owl#";
+
+ /** The URI of the mulgara namespace. */
+ public static final String MULGARA_NS = "http://mulgara.org/mulgara#";
+
+ /** The URI of the krule namespace. */
+ public static final String KRULE_NS = "http://mulgara.org/owl/krule/#";
+
+ /**
+ * Construct a {@link LiteralImpl} from a {@link PLiteral}.
+ *
+ * @param p the instance to convert
+ */
+ public LiteralImpl toLiteralImpl(PLiteral p);
+
+ /**
+ * Returns an anonymous variable unique for this interpreter.
+ * Note: We really should introduce a new subclass of Variable
+ * that is explicitly anonymous, but for now this will do.
+ */
+ public Variable nextAnonVariable();
+
+ /**
+ * Executes a query and returns its results.
+ *
+ * @param rawQuery a select query, represented as either a {@link
+ * org.mulgara.itql.node.ASelectCommand} or a {@link
+ * org.mulgara.itql.node.ASelectSetOfTriples}
+ * @return the answer to the query
+ * @throws QueryException if the query cannot be executed
+ * @throws URISyntaxException if the <code>query</code> contains a resource
+ * whose text violates <a href="http://www.isi.edu/in-notes/rfc2396.txt">
+ * RFC\uFFFD2396</a>
+ */
+ public Query buildQuery(org.mulgara.itql.node.Node rawQuery) throws QueryException,
+ URISyntaxException;
+
+ /**
+ * Convert SableCC-generated {@link TResource} tokens into {@link URI}s.
+ *
+ * Resolution will treat the token as an XML
+ * <a href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">qualified
+ * names</a> if the {@link #aliasMap} <code>aliasMap</code> contains a key
+ * for the URI scheme part that can be treated as an XML namespace prefix.
+ * For example, <kbd>dc:title</kbd> is treated as a qname and mapped to the
+ * to the URI <kbd>http://purl.org/dc/elements/1.1/title</kbd>, assuming the
+ * {@link #aliasMap} had an entry mapping <code>"dc"</code> to the Dublin
+ * Core namespace.
+ *
+ * @param token the token to be converted, which should actually be a
+ * {@link TResource}
+ * @throws Error if the <var>token</var> text isn't syntactically
+ * a {@link URI}; this shouldn't ever occur, assuming the <var>token</var>
+ * is a {@link TResource}
+ */
+ URI toURI(Token token);
+
+}
\ No newline at end of file
Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ItqlInterpreter.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ItqlInterpreter.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ItqlInterpreter.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -90,7 +90,7 @@
* @copyright ©2005 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
-public class ItqlInterpreter extends DepthFirstAdapter {
+public class ItqlInterpreter extends DepthFirstAdapter implements Interpreter {
//
// Constants
@@ -1353,8 +1353,7 @@
if (databaseURI == null) {
return;
}
- }
- else {
+ } else {
if (serverURI.equals(databaseURI)) {
return;
}
@@ -1370,8 +1369,7 @@
// Switch the underlying session to point at the required server
if (databaseURI == null) {
setSession(null, null);
- }
- else {
+ } else {
if (providedSession != null) {
if (session != providedSession) {
session = providedSession;
@@ -1398,11 +1396,9 @@
}
setSession(session, sessionFactory.getSecurityDomain());
- }
- catch (SessionFactoryFinderException e) {
+ } catch (SessionFactoryFinderException e) {
throw new QueryException("Unable to reconnect to " + databaseURI, e);
- }
- catch (NonRemoteSessionException e) {
+ } catch (NonRemoteSessionException e) {
throw new QueryException("Error connecting to the local server", e);
}
}
@@ -1605,7 +1601,7 @@
// get the type of model to create; default to mulgara:Model is unspecified
URI modelTypeURI = (node.getModelType() == null)
- ? Session.MULGARA_MODEL_URI
+ ? Session.MULGARA_GRAPH_URI
: toURI(node.getModelType());
try {
Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ModelExpressionBuilder.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ModelExpressionBuilder.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/ModelExpressionBuilder.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -94,6 +94,8 @@
* org.mulgara.itql.node.PModelExpression}, using an <code>aliasMap</code>
* to resolve aliases.
*
+ * TODO: aliasMap is currently ignored!
+ *
* @param aliasMap the map from targets to aliases
* @param expression a model expression from the parser
* @return RETURNED VALUE TO DO
@@ -103,7 +105,7 @@
* a resource whose text violates <a
* href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
- public static ModelExpression build(Map aliasMap,
+ public static ModelExpression build(Map<String,URI> aliasMap,
PModelExpression expression) throws QueryException, URISyntaxException {
// validate aliasMap parameter
@@ -126,7 +128,7 @@
}
// build the model expression from the parser input
- ModelExpression modelExpression = buildModelExpression(expression);
+ ModelExpression modelExpression = buildModelExpression(expression, aliasMap);
// logger that we've building successfully built a model expression
if (logger.isDebugEnabled()) {
@@ -156,7 +158,7 @@
* href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
private static ModelExpression buildModelExpression(
- PModelExpression rawModelExpression)
+ PModelExpression rawModelExpression, Map<String,URI> aliasMap)
throws QueryException, URISyntaxException {
// validate the rawModelExpression parameter
@@ -198,8 +200,8 @@
}
// get the LHS and RHS operands of the union
- ModelExpression lhs = buildModelExpression(orModelExpression);
- ModelExpression rhs = buildModelExpression(modelTerm);
+ ModelExpression lhs = buildModelExpression(orModelExpression, aliasMap);
+ ModelExpression rhs = buildModelExpression(modelTerm, aliasMap);
// logger that we've resolved the operands
if (logger.isDebugEnabled()) {
@@ -209,8 +211,7 @@
// apply the union
modelExpression = new ModelUnion(lhs, rhs);
- }
- else if (rawModelExpression instanceof ATermModelExpression) {
+ } else if (rawModelExpression instanceof ATermModelExpression) {
// logger that we've got a term model expression
if (logger.isDebugEnabled()) {
@@ -218,8 +219,7 @@
}
// get the model term
- PModelTerm modelTerm =
- ((ATermModelExpression) rawModelExpression).getModelTerm();
+ PModelTerm modelTerm = ((ATermModelExpression)rawModelExpression).getModelTerm();
// logger that we're about to resolve the term into an expression
if (logger.isDebugEnabled()) {
@@ -227,7 +227,7 @@
}
// drill down into the model term
- modelExpression = buildModelExpression(modelTerm);
+ modelExpression = buildModelExpression(modelTerm, aliasMap);
}
// end if
@@ -263,8 +263,9 @@
* a resource whose text violates <a
* href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
- private static ModelExpression buildModelExpression(PModelTerm rawModelTerm)
- throws QueryException, URISyntaxException {
+ private static ModelExpression buildModelExpression(
+ PModelTerm rawModelTerm, Map<String,URI> aliasMap
+ ) throws QueryException, URISyntaxException {
// validate the rawModelTerm parameter
if (rawModelTerm == null) {
@@ -299,20 +300,20 @@
}
// drill down into the model part
- modelExpression = buildModelExpression(modelPart);
- }
- else if (rawModelTerm instanceof AAndModelTerm) {
+ modelExpression = buildModelExpression(modelPart, aliasMap);
+ } else if (rawModelTerm instanceof AAndModelTerm) {
+
// logger that we've got a AND model term
if (logger.isDebugEnabled()) {
logger.debug("Found AND contraint term " + rawModelTerm);
}
// get the model term
- PModelTerm modelTerm = ((AAndModelTerm) rawModelTerm).getModelTerm();
+ PModelTerm modelTerm = ((AAndModelTerm)rawModelTerm).getModelTerm();
// get the model part
- PModelPart modelPart = ((AAndModelTerm) rawModelTerm).getModelPart();
+ PModelPart modelPart = ((AAndModelTerm)rawModelTerm).getModelPart();
// logger that we've found the operands of the union
if (logger.isDebugEnabled()) {
@@ -321,8 +322,8 @@
}
// get the LHS and RHS operands of the intersection
- ModelExpression lhs = buildModelExpression(modelTerm);
- ModelExpression rhs = buildModelExpression(modelPart);
+ ModelExpression lhs = buildModelExpression(modelTerm, aliasMap);
+ ModelExpression rhs = buildModelExpression(modelPart, aliasMap);
// logger that we've resolved the operands
if (logger.isDebugEnabled()) {
@@ -338,8 +339,7 @@
// we should not be returning null
if (modelExpression == null) {
- throw new QueryException("Unable to parse ITQL model term " +
- "into a valid model expression");
+ throw new QueryException("Unable to parse ITQL model term into a valid model expression");
}
// end if
@@ -367,8 +367,9 @@
* a resource whose text violates <a
* href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
- private static ModelExpression buildModelExpression(PModelPart rawModelPart)
- throws QueryException, URISyntaxException {
+ private static ModelExpression buildModelExpression(
+ PModelPart rawModelPart, Map<String,URI> aliasMap
+ ) throws QueryException, URISyntaxException {
// validate the rawModelPart parameter
if (rawModelPart == null) {
@@ -394,8 +395,7 @@
}
// get the model factor
- PModelFactor modelFactor =
- ((AFactorModelPart) rawModelPart).getModelFactor();
+ PModelFactor modelFactor = ((AFactorModelPart)rawModelPart).getModelFactor();
// logger that we're recursing with a model factor
if (logger.isDebugEnabled()) {
@@ -403,9 +403,8 @@
}
// drill down into the model part
- modelExpression = buildModelExpression(modelFactor);
- }
- else if (rawModelPart instanceof AXorModelPart) {
+ modelExpression = buildModelExpression(modelFactor, aliasMap);
+ } else if (rawModelPart instanceof AXorModelPart) {
// logger that we've got a AND model term
if (logger.isDebugEnabled()) {
@@ -413,21 +412,19 @@
}
// get the model term
- PModelPart modelPart = ((AXorModelPart) rawModelPart).getModelPart();
+ PModelPart modelPart = ((AXorModelPart)rawModelPart).getModelPart();
// get the model factor
- PModelFactor modelFactor =
- ((AXorModelPart) rawModelPart).getModelFactor();
+ PModelFactor modelFactor = ((AXorModelPart)rawModelPart).getModelFactor();
// logger that we've found the operands of the union
if (logger.isDebugEnabled()) {
- logger.debug("Recursing with model part " + modelPart + " & model factor " +
- modelFactor);
+ logger.debug("Recursing with model part " + modelPart + " & model factor " + modelFactor);
}
// get the LHS and RHS operands of the intersection
- ModelExpression lhs = buildModelExpression(modelPart);
- ModelExpression rhs = buildModelExpression(modelFactor);
+ ModelExpression lhs = buildModelExpression(modelPart, aliasMap);
+ ModelExpression rhs = buildModelExpression(modelFactor, aliasMap);
// logger that we've resolved the operands
if (logger.isDebugEnabled()) {
@@ -443,8 +440,7 @@
// we should not be returning null
if (modelExpression == null) {
- throw new QueryException("Unable to parse ITQL model term " +
- "into a valid model expression");
+ throw new QueryException("Unable to parse ITQL model term into a valid model expression");
}
// end if
@@ -473,13 +469,13 @@
* href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
private static ModelExpression buildModelExpression(
- PModelFactor rawModelFactor) throws QueryException, URISyntaxException {
+ PModelFactor rawModelFactor, Map<String,URI> aliasMap
+ ) throws QueryException, URISyntaxException {
// validate the rawModelFactor parameter
if (rawModelFactor == null) {
- throw new IllegalArgumentException("Null \"rawModelFactor\" " +
- "parameter");
+ throw new IllegalArgumentException("Null \"rawModelFactor\" parameter");
}
// end if
@@ -500,8 +496,7 @@
}
// get the resource
- String resource =
- ((AResourceModelFactor) rawModelFactor).getResource().getText();
+ String resource = ((AResourceModelFactor)rawModelFactor).getResource().getText();
// logger that we've found a resource
if (logger.isDebugEnabled()) {
@@ -509,10 +504,9 @@
}
// this resource is what we're looking for
- URI modelURI = new URI(resource);
+ URI modelURI = URIUtil.convertToURI(resource, aliasMap);
modelExpression = new ModelResource(ServerURIHandler.removePort(modelURI));
- }
- else if (rawModelFactor instanceof AExpressionModelFactor) {
+ } else if (rawModelFactor instanceof AExpressionModelFactor) {
// logger that we've got an expression model factor
if (logger.isDebugEnabled()) {
@@ -520,8 +514,7 @@
}
// get the model expression
- PModelExpression embeddedModelExpression =
- ((AExpressionModelFactor) rawModelFactor).getModelExpression();
+ PModelExpression embeddedModelExpression = ((AExpressionModelFactor)rawModelFactor).getModelExpression();
// logger that we're recursing with a model expression
if (logger.isDebugEnabled()) {
@@ -529,7 +522,7 @@
}
// build the model expression
- modelExpression = buildModelExpression(embeddedModelExpression);
+ modelExpression = buildModelExpression(embeddedModelExpression, aliasMap);
}
// end if
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,2726 @@
+/*
+ * 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 at 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):
+ * Copywrite in the anon-variable support:
+ * The Australian Commonwealth Government
+ * Department of Defense
+ * Developed by Netymon Pty Ltd
+ * under contract 4500507038
+ * contributed to the Mulgara Project under the
+ * Mozilla Public License version 1.1
+ * per clause 4.1.3 and 4.1.4 of the above contract.
+ *
+ * [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.itql;
+
+// Java 2 standard packages
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.RemoteException;
+import java.rmi.NoSuchObjectException;
+
+// Third party packages
+import org.apache.log4j.Logger; // Apache Log4J
+import org.jrdf.graph.*; // JRDF
+
+// Locally written packages
+
+// Automatically generated packages (SableCC)
+import org.mulgara.itql.analysis.*;
+import org.mulgara.itql.lexer.*;
+import org.mulgara.itql.node.*;
+import org.mulgara.itql.parser.*;
+import org.mulgara.query.*;
+import org.mulgara.query.ast.ApplyRules;
+import org.mulgara.query.ast.CommandAst;
+import org.mulgara.query.ast.Commit;
+import org.mulgara.query.ast.CreateGraph;
+import org.mulgara.query.ast.DropGraph;
+import org.mulgara.query.ast.Help;
+import org.mulgara.query.ast.Quit;
+import org.mulgara.query.ast.Rollback;
+import org.mulgara.query.ast.SetUser;
+import org.mulgara.query.rdf.*;
+import org.mulgara.rules.*;
+import org.mulgara.server.NonRemoteSessionException;
+import org.mulgara.server.Session;
+import org.mulgara.server.SessionFactory;
+import org.mulgara.server.driver.SessionFactoryFinder;
+import org.mulgara.server.driver.SessionFactoryFinderException;
+
+// emory util package
+import edu.emory.mathcs.util.remote.io.*;
+import edu.emory.mathcs.util.remote.io.server.impl.*;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipInputStream;
+
+/**
+ * Interactive TQL (ITQL) command interpreter.
+ * <p>
+ * Performs parsing and converting TQL requests to query objects for execution;
+ * Based on ItqlInterpreter.
+ * </p>
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright ©2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class TqlInterpreter extends DepthFirstAdapter implements Interpreter {
+
+ /** Get line separator. */
+ private static final String EOL = System.getProperty("line.separator");
+
+ /** The logger */
+ static final Logger logger = Logger.getLogger(TqlInterpreter.class.getName());
+
+ /** A constraint expression builder. */
+ private ConstraintExpressionBuilder builder = new ConstraintExpressionBuilder(this);
+
+ /** Variable factory for this interpreter. */
+ private VariableFactory variableFactory = new VariableFactoryImpl();
+
+ /** Lexer... */
+ Lexer2 lexer = new Lexer2();
+
+ //
+ // Members
+ //
+
+ /** The map from targets to aliases */
+ private Map<String,URI> aliasMap = null;
+
+ /** The log file to record all iTQL requests */
+ private PrintWriter itqlLog = null;
+
+ /** The location of the log iTQL file */
+ private String itqlLogFile = null;
+
+ /** The command for the callbacks to fill, while parseCommand is running */
+ CommandAst lastCommand = null;
+
+ /** The last exception or error, to be filled in during the callback operations. */
+ Throwable lastError = null;
+
+ //
+ // Interpreter options
+ //
+
+
+ /** The next anonymous variable suffix. */
+ private int anonSuffix = 0;
+
+ //
+ // Constructors
+ //
+
+ /**
+ * Creates a new ITQL command interpreter.
+ *
+ * @param aliasMap the map from targets to aliases, never <code>null</code>
+ */
+ public TqlInterpreter(Map<String,URI> aliasMap) {
+
+ // validate aliasMap parameter
+ if (aliasMap == null) {
+ throw new IllegalArgumentException("Null \"alias\" parameter");
+ }
+
+ // set members
+ this.setAliasMap(aliasMap);
+
+ // log the creation of this interpreter
+ if (logger.isDebugEnabled()) {
+ logger.debug("Itql interpreter created");
+ }
+
+ // is this session configured for logging.
+ if (System.getProperty("itql.command.log") != null) {
+ itqlLogFile = System.getProperty("itql.command.log");
+ logger.info("iTQL command logging has been enabled. Logging to " + System.getProperty("itql.command.log"));
+ }
+ }
+
+ /**
+ * Set up default aliases.
+ *
+ * @return A map of aliases to their fully qualified names
+ */
+ public static Map<String,URI> getDefaultAliases() {
+ Map<String,URI> aliases = new HashMap<String,URI>();
+ aliases.put(RDF, URI.create(RDF_NS));
+ aliases.put(RDFS, URI.create(RDFS_NS));
+ aliases.put(OWL, URI.create(OWL_NS));
+ aliases.put(MULGARA, URI.create(MULGARA_NS));
+ aliases.put(KRULE, URI.create(KRULE_NS));
+ return aliases;
+ }
+
+
+ //
+ // Public API
+ //
+
+ /**
+ * Parses the given TQL command.
+ *
+ * @param command the command to parse in TQL syntax
+ * @return A {@link List} of ASTs, one for each command
+ * @throws ParserException if the syntax of the command is incorrect
+ * @throws LexerException if the syntax of the command is incorrect
+ * @throws IOException if the <var>command</var> cannot be paersed
+ * @throws IllegalArgumentException if the <var>command</var> is <code>null</code>
+ */
+ public List<CommandAst> parseCommand(String command) throws ParserException, LexerException, Exception {
+
+ // validate command parameter
+ if ((command == null) || command.equals("")) {
+ throw new IllegalArgumentException("Null \"command\" parameter");
+ }
+
+ // log that we're going to execute the command
+ if (logger.isDebugEnabled()) {
+ logger.debug("Parsing command " + command);
+ }
+
+ // log the iTQL command - system property itql.command.log must be set
+ this.logItql(command);
+
+ // Reset the variable incrementer in the query.
+ variableFactory.reset();
+
+ // push the command into the lexer
+ lexer.add(command);
+
+ // create a list of AST versions of the command
+ List<CommandAst> commandList = new LinkedList<CommandAst>();
+
+ // if the lexer saw terminators, parse the associated commands
+ while (lexer.nextCommand()) {
+
+ Start commandTree = null;
+
+ // parse the command
+ try {
+ Parser parser = new Parser(lexer);
+ commandTree = parser.parse();
+
+ } catch (ParserException pe) {
+ // clear the parser
+ flush();
+ throw pe;
+
+ } catch (LexerException le) {
+
+ // clear the parser
+ flush();
+ throw le;
+ }
+
+ // build the command
+ try {
+ // this populates lastCommand
+ resetInterpreter();
+ commandTree.apply(this);
+ // take the lastCommand result, and add it to the list of results
+ commandList.add(lastCommand);
+ } catch (Exception e) {
+ flush();
+ throw e;
+ } catch (Error e) {
+ flush();
+ throw e;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Successfully parsed command " + command);
+ }
+ }
+ return commandList;
+ }
+
+ /**
+ * Discard any unparsed tokens.
+ *
+ */
+ private void flush() {
+ lexer.leftoverTokenList.clear();
+ }
+
+ // isQuitRequested()
+
+ /**
+ * Parse a string into a {@link Query}. Convenience method over parseCommand.
+ *
+ * @param queryString a string containing an ITQL query
+ * @return the corresponding {@link Query} instance
+ * @throws IOException if <var>queryString</var> can't be buffered.
+ * @throws LexerException if <var>queryString</var> can't be tokenized.
+ * @throws ParserException if <var>queryString</var> is not syntactic.
+ */
+ public Query parseQuery(String queryString) throws IOException,
+ LexerException, ParserException {
+
+ if (queryString == null) {
+ throw new IllegalArgumentException("Null \"queryString\" parameter");
+ }
+
+ // clean up query
+ queryString = queryString.trim();
+ while (queryString.endsWith(";")) {
+ queryString = queryString.substring(0, queryString.length() - 1);
+ }
+
+ // log that we're going to execute the command
+ if (logger.isDebugEnabled()) {
+ logger.debug("Parsing query \"" + queryString + "\"");
+ }
+
+ // execute the command
+ Parser parser = new Parser(new Lexer(new PushbackReader(new StringReader(queryString), 256)));
+ resetInterpreter();
+ parser.parse().apply(this);
+
+ if (lastCommand == null) throw new ParserException(null, "Parameter was not a query");
+
+ // return the results of the command
+ if (!(lastCommand instanceof Query)) throw new IllegalArgumentException("Command was not a query: " + queryString);
+ return (Query)lastCommand;
+ }
+
+
+ //
+ // Methods overridden from DepthFirstAdapter
+ // Provides callback mechanism for SableCC
+ //
+
+ /**
+ * Displays help information to the user.
+ *
+ * @param node the help command
+ */
+ public void outAHelpCommand(AHelpCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing help command " + node);
+
+ lastCommand = new Help(node.getCommandPrefix());
+ }
+
+
+ /**
+ * Quits a session.
+ *
+ * @param node the quit command
+ */
+ public void outAQuitCommand(AQuitCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing quit command " + node);
+
+ lastCommand = new Quit();
+ }
+
+
+ /**
+ * Commits a transaction.
+ *
+ * @param node the commit command
+ */
+ public void outACommitCommand(ACommitCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing commit command " + node);
+
+ lastCommand = new Commit();
+ }
+
+
+ /**
+ * Rolls back a transaction.
+ *
+ * @param node the rollback command
+ */
+ public void outARollbackCommand(ARollbackCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing rollback command " + node);
+ lastCommand = new Rollback();
+ }
+
+
+ /**
+ * Creates a query.
+ *
+ * @param node the query command
+ */
+ public void outASelectCommand(ASelectCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing select command " + node);
+
+ resetInterpreter();
+
+ // build the query
+ try {
+ lastCommand = this.buildQuery(node.getQuery());
+ } catch (QueryException qe) {
+ logger.warn("Couldn't answer query", qe);
+ lastError = qe;
+ } catch (URISyntaxException use) {
+ logger.warn("Invalid resource URI. " + use.getMessage());
+ lastError = use;
+ }
+ }
+
+
+ /**
+ * Substitutes the user associated with this session.
+ *
+ * @param node the su command
+ */
+ public void outASuCommand(ASuCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing su command " + node);
+
+ lastCommand = new SetUser(node.getUser().getText(), node.getPassword().getText(), toURI(node.getResource()));
+ }
+
+
+ /**
+ * Associates an alias prefix with a target.
+ *
+ * @param node the alias command
+ */
+ public void outAAliasCommand(AAliasCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing alias command " + node);
+
+ // get the prefix and target
+ String aliasPrefix = node.getPrefix().getText();
+ String aliasTarget = node.getTarget().getText();
+
+ try {
+
+ // convert the target to a URI
+ URI aliasTargetURI = new URI(aliasTarget);
+
+ // log the conversion
+ if (logger.isDebugEnabled()) logger.debug("Converted " + aliasTarget + " to URI " + aliasTargetURI);
+
+ // add the alias pair to the map
+ this.addAliasPair(aliasPrefix, aliasTargetURI);
+
+ // log that we've added the pair to the map
+ if (logger.isDebugEnabled()) logger.debug("Aliased " + aliasTarget + " as " + aliasPrefix);
+
+ } catch (URISyntaxException use) {
+ // log the failed URI creation
+ logger.warn("Unable to create URI from alias target " + aliasTarget);
+ }
+ }
+
+
+ /**
+ * Applies a set of rules in a model to data in another model.
+ *
+ * @param node the alias command
+ */
+ public void outAApplyCommand(AApplyCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing apply command " + node);
+
+ // get the rule graph and target graph
+ URI ruleGraph = toURI(node.getRules());
+ URI baseGraph = toURI(node.getBase());
+ Token dest = node.getDestination();
+ URI destGraph = (dest == null) ? baseGraph : toURI(dest);
+
+ lastCommand = new ApplyRules(ruleGraph, baseGraph, destGraph);
+ }
+
+
+ /**
+ * Creates a new database/model.
+ *
+ * @param node the create command
+ */
+ public void outACreateCommand(ACreateCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing create command " + node);
+
+ // get the name of the model to create
+ URI graphURI = toURI(node.getModel());
+
+ // get the type of model to create; default to mulgara:Model is unspecified
+ URI graphTypeURI = (node.getModelType() == null)
+ ? Session.MULGARA_GRAPH_URI
+ : toURI(node.getModelType());
+
+ // log that we're asking the driver to create the resource
+ if (logger.isDebugEnabled()) logger.debug("Creating new graph " + graphURI);
+
+ graphURI = getCanonicalUriAlias(graphURI);
+
+ if (logger.isDebugEnabled()) logger.debug("Model is alias for " + graphURI);
+
+ lastCommand = new CreateGraph(graphURI, graphTypeURI);
+ }
+
+ /**
+ * Drop (delete) a database/model.
+ *
+ * @param node the drop command
+ */
+ public void outADropCommand(ADropCommand node) {
+
+ // log the command
+ if (logger.isDebugEnabled()) logger.debug("Processing drop command " + node);
+
+ // get the name of the database/model to drop
+ lastCommand = new DropGraph(toURI(node.getResource()));
+ }
+
+ /**
+ * Load the contents of a file into a database/model.
+ *
+ * @param node the load command
+ */
+ public void outALoadCommand(ALoadCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ RemoteInputStream remoteInputStream = null;
+ RemoteInputStreamSrvImpl srv = null;
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing load command " + node);
+ }
+
+ // get constituents of the load command
+ URI sourceURI = toURI(node.getSource());
+ URI destinationURI = toURI(node.getDestination());
+
+ try {
+
+ long stmtCount = 0;
+
+ // update the session
+ this.updateSession(new ModelResource(destinationURI));
+
+
+ // are we loading the file locally from the client?
+ if ( node.getLocality() != null &&
+ (node.getLocality() instanceof ALocalLocality) ) {
+
+ if ( logger.isInfoEnabled() ) {
+ logger.info("loading local resource : " + sourceURI );
+ }
+
+ try {
+
+ //open an InputStream
+ InputStream inputStream = sourceURI.toURL().openStream();
+
+ //is the file/stream compressed?
+ String path = (sourceURI == null) ? "" : sourceURI.toString();
+ inputStream = adjustForCompression(path, inputStream);
+
+ // open and wrap the inputstream
+ srv = new RemoteInputStreamSrvImpl(inputStream);
+
+ // prepare it for exporting
+ UnicastRemoteObject.exportObject(srv);
+
+ remoteInputStream = new RemoteInputStream(srv);
+
+ // modify the database
+ stmtCount =
+ this.getSession().setModel(remoteInputStream,
+ destinationURI, // model to redefine
+ new ModelResource(sourceURI));
+ }
+ catch (IOException ex) {
+ logger.error("Error attempting to load : " + sourceURI, ex);
+ throw new QueryException("Error attempting to load : " + sourceURI, ex);
+ } finally {
+ if ( srv != null ) {
+ try {
+ UnicastRemoteObject.unexportObject(srv, false);
+ } catch ( NoSuchObjectException ex ) {};
+ }
+ }
+ }
+ else {
+
+ if ( logger.isInfoEnabled() ) {
+ logger.info("loading remote resource : " + sourceURI );
+ }
+
+ // modify the database using a remote file located on the server
+ // default behaviour
+
+ stmtCount =
+ this.getSession().setModel(destinationURI, // model to redefine
+ new ModelResource(sourceURI));
+ }
+ update();
+
+ // log that we've loaded the contents of the file
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Loaded " + stmtCount + " statements from " + sourceURI +
+ " into " + destinationURI);
+ }
+
+ // tell the user
+ if (stmtCount > 0L) {
+
+ this.setLastMessage("Successfully loaded " + stmtCount +
+ " statements from " + sourceURI + " into " +
+ destinationURI);
+ }
+ else {
+
+ this.setLastMessage("WARNING: No valid RDF statements found in " +
+ sourceURI);
+ } // end if
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not load " + sourceURI + " into " +
+ destinationURI + EOL + this.getCause(qe, 2));
+ logger.warn("Failed to load " + sourceURI + " into " + destinationURI,
+ qe);
+ }
+ catch (RuntimeException re) {
+
+ // let the user know the problem
+ this.setLastError(re);
+ this.setLastAnswer(null);
+ this.setLastMessage("Failed to load statements:" + this.getCause(re, 0));
+ logger.fatal("Failed to load statements", re);
+ }
+ finally {
+
+ // close the inputstream in-case the server was not able to
+ // complete the task.
+ if ( remoteInputStream != null ) {
+ try {
+ remoteInputStream.close();
+ } catch ( Exception ex ) {};
+ }
+
+ }
+ // try-catch
+
+ }
+
+ // outALoadCommand()
+
+ /**
+ * Executes an iTQL script.
+ *
+ * @param node the execute command
+ */
+ public void outAExecuteCommand(AExecuteCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing execute command " + node);
+ }
+
+ // get the name of the script to execute
+ String resource = node.getResource().getText();
+
+ // keep a record of the line number
+ int line = 0;
+
+ try {
+
+ // convert the script to a URL
+ URL scriptURL = new URL(resource);
+
+ // log that we're executing a script
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Executing script " + scriptURL);
+ }
+
+ // create a buffer to hold the results in
+ StringBuffer resultsMsg = new StringBuffer();
+
+ // create a reader to read the contents of the script
+ BufferedReader scriptIn =
+ new BufferedReader(new InputStreamReader(scriptURL.openStream()));
+
+ // execute the script!
+ String command = scriptIn.readLine();
+
+ while (command != null) {
+
+ // increment the line number
+ line++;
+
+ if (!command.equals("")) {
+
+ // execute the command
+ executeCommand(command);
+ }
+
+ // end if
+ // get the next command
+ command = scriptIn.readLine();
+ }
+
+ // end if
+ // tell the user
+ resultsMsg.append("Completed execution of script " + resource);
+ this.setLastMessage(resultsMsg.toString());
+ }
+ catch (ParserException pe) {
+
+ // let the user know the problem
+ this.setLastError(pe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Syntax error in script (line " + line + "): " +
+ pe.getMessage());
+ logger.warn("Unable to execute script - " + resource + EOL +
+ this.getCause(pe, 0));
+ }
+ catch (LexerException le) {
+
+ // let the user know the problem
+ this.setLastError(le);
+ this.setLastAnswer(null);
+ this.setLastMessage("Syntax error in script (line " + line + "): " +
+ le.getMessage());
+ logger.warn("Unable to execute script - " + resource + EOL +
+ this.getCause(le, 0));
+ }
+ catch (MalformedURLException mue) {
+
+ // let the user know the problem
+ this.setLastError(mue);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not execute script: Invalid script URL.");
+ logger.warn("Invalid script source URL." + EOL + this.getCause(mue, 0));
+ }
+ catch (Exception e) {
+
+ // let the user know the problem
+ this.setLastError(e);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not execute script." + EOL +
+ this.getCause(e, 0));
+ logger.error("Unable to execute script - " + resource + EOL +
+ this.getCause(e, 0));
+ }
+ // try-catch
+ }
+
+ // outAExecuteCommand()
+
+ /**
+ * Inserts a triple, model, database or the results of a query into a model or
+ * database.
+ *
+ * @param node the insert command
+ */
+ public void outAInsertCommand(AInsertCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing insert command " + node);
+ }
+
+ // get the resource we're inserting data into
+ URI resourceURI = toURI(node.getResource());
+
+ try {
+
+ // log that we're inserting the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Inserting statements into " + resourceURI);
+ }
+
+ // update the session
+ this.updateSession(new ModelResource(resourceURI));
+
+ // insert the statements into the model
+ insertStatements(resourceURI, node.getTripleFactor());
+ update();
+
+ // log that we've inserted the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Completed inserting statements into " + resourceURI);
+ }
+
+ // tell the user
+ this.setLastMessage(
+ "Successfully inserted statements into " + resourceURI
+ );
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not insert statements into " + resourceURI +
+ EOL + this.getCause(qe, 2));
+ logger.warn("Failed to insert statements into " + resourceURI, qe);
+ }
+ catch (URISyntaxException use) {
+
+ // let the user know the problem
+ this.setLastError(use);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not insert into resource: Invalid resource " +
+ "URI.");
+ logger.warn("Invalid resource URI." + EOL + this.getCause(use, 0));
+ }
+ catch (RuntimeException re) {
+
+ // let the user know the problem
+ this.setLastError(re);
+ this.setLastAnswer(null);
+ this.setLastMessage("Failed to insert statements:" + this.getCause(re, 0));
+ logger.fatal("Failed to insert statements", re);
+ }
+ }
+
+ // outAInsertCommand()
+
+ /**
+ * Deletes a triple, model, database or the results of a query from a model or
+ * database.
+ *
+ * @param node the delete command
+ */
+ public void outADeleteCommand(ADeleteCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing delete command " + node);
+ }
+
+ // get the resource we're deleting data from
+ URI resourceURI = toURI(node.getResource());
+
+ try {
+
+ // log that we're deleting the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Deleting statements from " + resourceURI);
+ }
+
+ // update the session
+ this.updateSession(new ModelResource(resourceURI));
+
+ // delete the statements from the model
+ deleteStatements(resourceURI, node.getTripleFactor());
+ update();
+
+ // log that we've inserted the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Completed deleting statements from " + resourceURI);
+ }
+
+ // tell the user
+ this.setLastMessage(
+ "Successfully deleted statements from " + resourceURI
+ );
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not delete statements from " + resourceURI +
+ EOL + this.getCause(qe, 2));
+ logger.warn("Failed to delete statements from " + resourceURI, qe);
+ }
+ catch (URISyntaxException use) {
+
+ // let the user know the problem
+ this.setLastError(use);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not delete from resource: Invalid resource " +
+ "URI.");
+ logger.warn("Invalid resource URI." + EOL + this.getCause(use, 0));
+ }
+ catch (RuntimeException re) {
+
+ // let the user know the problem
+ this.setLastError(re);
+ this.setLastAnswer(null);
+ this.setLastMessage("Failed to delete statements:" + this.getCause(re, 0));
+ logger.fatal("Failed to delete statements", re);
+ }
+
+ // try-catch
+ }
+
+ // outADeleteCommand()
+
+ /**
+ * Sets an interpreter property.
+ *
+ * @param node the set command
+ */
+ public void outASetCommand(ASetCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing set command " + node);
+ }
+
+ // get the option to set
+ PSetOption option = node.getSetOption();
+
+ // log that we've got the option
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Found option " + option);
+ }
+
+ // get the value
+ PSetOptionMode optionMode = node.getSetOptionMode();
+ boolean optionSet = false;
+
+ if (optionMode instanceof AOffSetOptionMode) {
+
+ optionSet = false;
+ }
+ else {
+
+ optionSet = true;
+ } // end if
+
+ // set the option
+ if (option instanceof ATimeSetOption) {
+
+ // set the time option
+ this.setTimeOption(optionSet);
+
+ // return the user a message
+ this.setLastMessage("Command timing is " + (optionSet ? "on" : "off"));
+ }
+ else if (option instanceof AAutocommitSetOption) {
+
+ /* Do not assume this. As the server may have
+ encountered an error.
+ if (optionSet == autoCommit) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Autocommit option is already " + autoCommit);
+ } // end if
+ return;
+ }
+ */
+
+ try {
+
+ // log that we got a autocommit option
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Found autocommit option, setting to " +
+ (optionSet ? "on" : "off"));
+ } // end if
+
+ // set the auto commit status
+ if (session != null) {
+ this.getSession().setAutoCommit(optionSet);
+ update();
+ }
+ autoCommit = optionSet;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Set autocommit to " + (optionSet ? "on" : "off"));
+ }
+
+ // return the user a message
+ this.setLastMessage("Auto commit is " + (optionSet ? "on" : "off"));
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Unable to set interpreter option" + EOL +
+ this.getCause(qe, 2));
+ logger.warn("Unable to set interpreter property", qe);
+ }
+
+ // try-catch
+ }
+ else {
+
+ // this should never get through the parser, if it does it probably
+ // means the grammar has been updated
+ this.setLastMessage("Unknown interpreter option");
+ }
+
+ // end if
+ // log the option setting
+ if (logger.isDebugEnabled()) {
+
+ logger.debug(option + "has been set to " + optionSet);
+ }
+ }
+
+ // outASetCommand()
+
+ /**
+ * Backs up the contents of a server to a local or remote file.
+ *
+ * @param node the backup command
+ */
+ public void outABackupCommand(ABackupCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ RemoteOutputStream outputStream = null;
+ RemoteOutputStreamSrvImpl srv = null;
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing backup command " + node);
+ }
+
+ // get the server we'll be backing up
+ URI sourceURI = toURI(node.getSource());
+
+ // get the resource we're writing to
+ URI destinationURI = toURI(node.getDestination());
+
+ try {
+
+ // set the server uri given a possible model
+ this.setBackupServer(sourceURI);
+
+ // are we backing up a file locally to the client?
+ if ( node.getLocality() != null &&
+ (node.getLocality() instanceof ALocalLocality) ) {
+
+ if ( logger.isInfoEnabled() ) {
+ logger.info("backing up local resource : " + sourceURI );
+ }
+
+ try {
+
+ // open and wrap the outputstream
+ srv = new RemoteOutputStreamSrvImpl(
+ new FileOutputStream(destinationURI.getPath()));
+
+ // prepare it for exporting
+ UnicastRemoteObject.exportObject(srv);
+
+ outputStream = new RemoteOutputStream(srv);
+
+ }
+ catch (IOException ex) {
+ logger.error("Error attempting to backing up : " + sourceURI, ex);
+ }
+
+ try {
+
+ // back it up to the local file system
+ this.getSession().backup(sourceURI, outputStream);
+
+ } finally {
+
+ // ensure the stream is closed in case the server was not able
+ // to close it.
+ if ( outputStream != null ) {
+ try {
+ outputStream.close();
+ } catch ( IOException ioex ) {};
+ if ( srv != null ) {
+ try {
+ UnicastRemoteObject.unexportObject(srv, false);
+ } catch ( NoSuchObjectException ex ) {};
+ }
+ }
+ }
+
+ }
+ else {
+
+ // back it up via the server
+ this.getSession().backup(sourceURI, destinationURI);
+ }
+
+ // log that we've inserted the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Completed backing up " + sourceURI +
+ " to " + destinationURI);
+ }
+
+ // tell the user
+ this.setLastMessage("Successfully backed up " + sourceURI +
+ " to " + destinationURI + ".");
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not backup " + sourceURI + " to " +
+ destinationURI + EOL + this.getCause(qe, 2) + ".");
+ logger.warn("Failed to backup server " + sourceURI + " to " +
+ destinationURI,
+ qe);
+ }
+
+ // try-catch
+ }
+
+ // outABackupCommand()
+
+ /**
+ * Restores the contents of a server from a file.
+ *
+ * @param node the restore command
+ */
+ public void outARestoreCommand(ARestoreCommand node) {
+
+ this.setLastError(null);
+ this.setLastAnswer(null);
+ this.setLastMessage("");
+
+ RemoteInputStream inputStream = null;
+ RemoteInputStreamSrvImpl srv = null;
+
+ // log the command
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Processing restore command " + node);
+ }
+
+ // get the server we'll be restoring to
+ URI destinationURI = toURI(node.getDestination());
+
+ // get the resource we're reading from
+ URI sourceURI = toURI(node.getSource());
+
+ try {
+
+ // log that we're backing up a server
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Restoring server " + destinationURI + " from " +
+ sourceURI);
+ }
+
+ setServerURI(destinationURI);
+
+ // are we loading the file locally from the client?
+ if ( node.getLocality() != null &&
+ (node.getLocality() instanceof ALocalLocality) ) {
+
+ if ( logger.isInfoEnabled() ) {
+ logger.info("restoring local resource : " + sourceURI );
+ }
+
+ try {
+
+ // open and wrap the inputstream
+ srv = new RemoteInputStreamSrvImpl(sourceURI.toURL().openStream());
+
+ // prepare it for exporting
+ UnicastRemoteObject.exportObject(srv);
+
+ inputStream = new RemoteInputStream(srv);
+
+ // modify the database
+ this.getSession().restore( inputStream, destinationURI, sourceURI);
+ }
+ catch (IOException ex) {
+ logger.error("Error attempting to restore : " + sourceURI, ex);
+ throw new QueryException("Error attempting to restore : " + sourceURI, ex);
+ }
+ finally {
+ if ( srv != null ) {
+ try {
+ UnicastRemoteObject.unexportObject(srv, false);
+ } catch ( NoSuchObjectException ex ) {};
+ }
+ }
+ }
+ else {
+
+ // restore it from the server
+ this.getSession().restore(destinationURI, sourceURI);
+
+ }
+
+ update();
+
+ // log that we've inserted the statments
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Completed restoring " + destinationURI + " from " +
+ sourceURI);
+ }
+
+ // tell the user
+ this.setLastMessage("Successfully restored " + destinationURI + " from " +
+ sourceURI);
+ }
+ catch (QueryException qe) {
+
+ // let the user know the problem
+ this.setLastError(qe);
+ this.setLastAnswer(null);
+ this.setLastMessage("Could not restore " + destinationURI + " from " +
+ sourceURI + EOL + this.getCause(qe, 2));
+ logger.warn("Failed to restore server " + destinationURI + " from " +
+ sourceURI, qe);
+ }
+ finally {
+
+ // close the inputstream in-case the server was not able to
+ // complete the task.
+ if ( inputStream != null ) {
+ try {
+ inputStream.close();
+ }
+ catch ( Exception ex ) {};
+ }
+ }
+ }
+
+ /**
+ * Returns a set of statements from the iTQL query object.
+ *
+ * @param setOfTriples the set of statements defined in the query.
+ * @param variableMap the variable map to store the value of the variable
+ * against the variable object.
+ * @throws URISyntaxException if <code>tripleFactor</code> contains a query or
+ * a resource that that violates <a
+ * href="http://www.isi.edu/in-notes/rfc2396.txt">RFC\uFFFD2396</a>
+ * @throws QueryException if an invalid node is used in the set of triples.
+ * @return a set of statements from the iTQL query.
+ */
+ @SuppressWarnings("unchecked")
+ public Set<org.jrdf.graph.Triple> getStatements(ATripleSetOfTriples setOfTriples, Map<String,VariableNodeImpl> variableMap)
+ throws QueryException, URISyntaxException {
+
+ List<ATriple> tripleList = (List<ATriple>)setOfTriples.getTriple();
+ HashSet<org.jrdf.graph.Triple> statements = new HashSet<org.jrdf.graph.Triple>();
+
+ // Check that each set of triples has the predicate bound.
+ for (Iterator<ATriple> i = tripleList.iterator(); i.hasNext(); ) {
+
+ // get the triple
+ ATriple triple = i.next();
+
+ // Convert the Subject, Predicate and Object.
+ org.jrdf.graph.Node subject = toNode(triple.getSubject(), variableMap);
+ org.jrdf.graph.Node predicate = toNode(triple.getPredicate(), variableMap);
+ org.jrdf.graph.Node object = toNode(triple.getObject(), variableMap);
+
+ // Predicate cannot be a blank node.
+ if (predicate instanceof BlankNode) {
+ throw new QueryException("Predicate must be a valid URI");
+ }
+
+ // Check that the subject or predicate node is not a literal.
+ if (subject instanceof LiteralImpl ||
+ predicate instanceof LiteralImpl) {
+
+ // throw an exception indicating we have a bad triple
+ throw new QueryException(
+ "Subject or Predicate cannot be a literal");
+ }
+
+ // Create a new statement using the triple elements
+ org.jrdf.graph.Triple jrdfTriple = new TripleImpl(
+ (SubjectNode) subject, (PredicateNode) predicate,
+ (ObjectNode) object);
+
+ // add the statement to the statement set
+ statements.add(jrdfTriple);
+ }
+
+ return statements;
+ }
+
+ /**
+ * Executes a query and returns its results.
+ *
+ * @param rawQuery a select query, represented as either a {@link
+ * org.mulgara.itql.node.ASelectCommand} or a {@link
+ * org.mulgara.itql.node.ASelectSetOfTriples}
+ * @return the answer to the query
+ * @throws QueryException if the query cannot be executed
+ * @throws URISyntaxException if the <code>query</code> contains a resource
+ * whose text violates <a href="http://www.isi.edu/in-notes/rfc2396.txt">
+ * RFC\uFFFD2396</a>
+ */
+ public Query buildQuery(org.mulgara.itql.node.Node rawQuery) throws
+ QueryException, URISyntaxException {
+
+ // validate query parameter
+ if (rawQuery == null) {
+
+ throw new IllegalArgumentException("Null \"rawQuery\" parameter");
+ }
+
+ // end if
+ // create the variables needed...
+ LinkedList variables = null;
+ AFromClause fromClause;
+ AWhereClause whereClause;
+ AOrderClause orderClause;
+ AHavingClause havingClause;
+ ALimitClause limitClause;
+ AOffsetClause offsetClause;
+
+ // cast the correct way (we don't have a common superclass, event though we
+ // have methods with the same names)
+ if (rawQuery instanceof AQuery) {
+
+ AQuery query = (AQuery) rawQuery;
+ PSelectClause selectClause = query.getSelectClause();
+ if (selectClause instanceof ANormalSelectSelectClause) {
+ variables = ( (ANormalSelectSelectClause) selectClause).getElement();
+ }
+ fromClause = ( (AFromClause) query.getFromClause());
+ whereClause = ( (AWhereClause) query.getWhereClause());
+ orderClause = ( (AOrderClause) query.getOrderClause());
+ havingClause = ( (AHavingClause) query.getHavingClause());
+ limitClause = ( (ALimitClause) query.getLimitClause());
+ offsetClause = ( (AOffsetClause) query.getOffsetClause());
+ }
+ else if (rawQuery instanceof ASelectSetOfTriples) {
+
+ ASelectSetOfTriples query = (ASelectSetOfTriples) rawQuery;
+ variables = new LinkedList();
+ variables.add(query.getSubject());
+ variables.add(query.getPredicate());
+ variables.add(query.getObject());
+ fromClause = ( (AFromClause) query.getFromClause());
+ whereClause = ( (AWhereClause) query.getWhereClause());
+ orderClause = ( (AOrderClause) query.getOrderClause());
+ havingClause = ( (AHavingClause) query.getHavingClause());
+ limitClause = ( (ALimitClause) query.getLimitClause());
+ offsetClause = ( (AOffsetClause) query.getOffsetClause());
+ }
+ else {
+
+ // we only handle AQuery and ASelectSetOfTriples
+ throw new IllegalArgumentException("Invalid type for \"rawQuery\" " +
+ "parameter");
+ }
+
+ if (fromClause == null) {
+
+ throw new QueryException("FROM clause missing.");
+ }
+
+ if (whereClause == null) {
+
+ throw new QueryException("WHERE clause missing.");
+ }
+
+ // end if
+ // log that we're about to build the variable list
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building query variable list from " + variables);
+ }
+
+ // build the variable list
+ List variableList = this.buildVariableList(variables);
+
+ // log that we've built the variable list
+ if (logger.isDebugEnabled()) {
+ logger.debug("Built variable list " + variableList);
+ }
+
+ // get the model expression from the parser
+ PModelExpression rawModelExpression = fromClause.getModelExpression();
+
+ // log that we're about to build the model expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building model expression from " + rawModelExpression);
+ }
+
+ // parse the text into a model expression
+ ModelExpression modelExpression =
+ ModelExpressionBuilder.build(this.getAliasMap(), rawModelExpression);
+
+ // log that we've built the model expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Built model expression " + modelExpression);
+ }
+
+ // get the constraint expression from the parser
+ PConstraintExpression rawConstraintExpression =
+ whereClause.getConstraintExpression();
+
+ // log that we're about to build the constraint expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building constraint expression from " +
+ rawConstraintExpression);
+ }
+
+ // parse the text into a constraint expression
+ ConstraintExpression constraintExpression = build(rawConstraintExpression);
+
+ // log that we've build the constraint expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Built constraint expression " + constraintExpression);
+ }
+
+ // build the order list
+ List orderList = Collections.EMPTY_LIST;
+
+ if (orderClause != null) {
+
+ orderList = buildOrderList(orderClause.getOrderElement());
+ }
+
+ // build the having clause
+ ConstraintHaving havingExpression = null;
+
+ if (havingClause != null) {
+ // get the constraint expression from the parser
+ PConstraintExpression rawHavingExpression =
+ havingClause.getConstraintExpression();
+
+ // log that we're about to build the constraint expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building constraint expression from " +
+ rawHavingExpression);
+ }
+
+ // parse the text into a constraint expression
+ havingExpression = buildHaving(rawHavingExpression);
+ }
+
+ // build the limit
+ Integer limit = null;
+
+ if (limitClause != null) {
+
+ try {
+
+ limit = new Integer(limitClause.getNumber().getText());
+ }
+ catch (NumberFormatException e) {
+
+ throw new Error("Sable parser permitted non-integer limit", e);
+ }
+ }
+
+ // build the offset
+ int offset = 0;
+
+ if (offsetClause != null) {
+
+ try {
+
+ offset = Integer.parseInt(offsetClause.getNumber().getText());
+ }
+ catch (NumberFormatException e) {
+
+ throw new Error("Sable parser permitted non-integer offset", e);
+ }
+ }
+
+ // build a query using the information we've obtained from the parser
+ // (all answers are acceptable)
+ lastQuery = new Query(variableList, modelExpression, constraintExpression,
+ havingExpression, orderList, limit, offset, new UnconstrainedAnswer());
+
+ return lastQuery;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mulgara.itql.QueryInterpreter#toLiteralImpl(org.mulgara.itql.node.PLiteral)
+ */
+ public LiteralImpl toLiteralImpl(PLiteral p) {
+
+ ALiteral aLiteral = (ALiteral) p;
+
+ // Determine the datatype URI, if present
+ URI datatypeURI = null;
+ if (aLiteral.getDatatype() != null) {
+ datatypeURI = toURI( ( (ADatatype) aLiteral.getDatatype()).getResource());
+ }
+
+ // Determine the language code
+ String language = (datatypeURI == null) ? "" : null;
+
+ if (datatypeURI == null) {
+ return new LiteralImpl(getLiteralText(aLiteral), language);
+ }
+ else {
+ return new LiteralImpl(getLiteralText(aLiteral), datatypeURI);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.mulgara.itql.QueryInterpreter#toURI(org.mulgara.itql.node.Token)
+ */
+ public URI toURI(Token token) {
+
+ assert token instanceof TResource;
+ return URIUtil.convertToURI(token.getText(), aliasMap);
+ }
+
+ //
+ // Static methods brought in from the late ConstraintExpressionBuilder
+ //
+
+ /**
+ * Builds a {@link org.mulgara.query.ConstraintExpression} object from a
+ * {@link org.mulgara.itql.node.PConstraintExpression}, using an <code>aliasMap</code>
+ * to resolve aliases.
+ *
+ * @param expression a constraint expression from the parser
+ * @return RETURNED VALUE TO DO
+ * @throws QueryException if <code>rawConstraintExpression</code> does not
+ * represent a valid query
+ * @throws URISyntaxException if the <code>rawConstraintExpression</code>
+ * contains a resource whose text violates <a
+ * href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
+ */
+ public ConstraintExpression build(PConstraintExpression expression) throws
+ QueryException, URISyntaxException {
+
+ // validate aliasMap parameter
+ if (aliasMap == null) {
+ throw new IllegalArgumentException("Null \"aliasMap\" parameter");
+ }
+
+ // validate expression parameter
+ if (expression == null) {
+ throw new IllegalArgumentException("Null \"expression\" parameter");
+ }
+
+ // log that we're building a constraint expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building constraint expression from " + expression);
+ }
+
+ // build the contraint expression from the parser input
+ expression.apply( (Switch) builder);
+ ConstraintExpression constraintExpression = builder.
+ getConstraintExpression();
+
+ // log that we've building successfully built a constraint expression
+ if (logger.isDebugEnabled()) {
+ logger.debug("Successfully built constraint expression from " +
+ expression);
+ }
+
+ // return the contraint expression
+ return constraintExpression;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mulgara.itql.QueryInterpreter#nextAnonVariable()
+ */
+ public Variable nextAnonVariable() {
+ return new Variable("av__" + this.anonSuffix++);
+ }
+
+ /**
+ * Returns the text of the given <code>literal</code>.
+ *
+ * @param literal the literal to retrieve the text from
+ * @return The LiteralText value
+ */
+ public static String getLiteralText(ALiteral literal) {
+
+ // validate the literal parameter
+ if (literal == null) {
+
+ throw new IllegalArgumentException("Null \"literal\" " + "parameter");
+ }
+
+ // end if
+ // the text of the literal
+ StringBuffer literalText = new StringBuffer();
+
+ // get all the strands in this literal
+ List strands = literal.getStrand();
+
+ // add each strand together to make the literal text
+ for (Iterator i = strands.iterator(); i.hasNext(); ) {
+
+ // get the strand
+ PStrand strand = (PStrand) i.next();
+
+ // add the strand to the literal text
+ if (strand instanceof AUnescapedStrand) {
+
+ literalText.append( ( (AUnescapedStrand) strand).getText().getText());
+ }
+ else if (strand instanceof AEscapedStrand) {
+
+ literalText.append( ( (AEscapedStrand) strand).getEscapedtext().getText());
+ } // end if
+
+ } // end for
+
+ // return the text
+ return literalText.toString();
+ }
+
+ /**
+ * Sets the error of the last query. Methods overriding <code>DepthFirstAdapter</code>
+ * are expected to set a result for successful queries, and <code>null</code>
+ * for failed ones.
+ *
+ * @param lastError the exception of the last command execution
+ */
+ void setLastError(Exception lastError) {
+
+ // carefully set the answer by value rather than reference
+ this.lastError =
+ (lastError == null) ? null : new ItqlInterpreterException(lastError);
+ }
+
+ /**
+ * Sets the results of the last command execution. Methods overriding <code>DepthFirstAdapter</code>
+ * are expected to set a results message, even if that message is null.
+ *
+ * @param lastMessage the results of the last command execution
+ */
+ void setLastMessage(String lastMessage) {
+
+ this.lastMessage = lastMessage;
+ }
+
+ // setLastMessage()
+
+ /**
+ * Returns the driver used to communicate with the database.
+ *
+ * @return the driver used to communicate with the database
+ */
+ Session getSession() throws QueryException {
+
+ if (providedSession != null) {
+ if (session != providedSession) {
+ session = providedSession;
+ }
+ }
+
+ if (this.session == null) {
+ throw new QueryException("Null session");
+ }
+ return this.session;
+ }
+
+ // getCause()
+
+ // outASelectCommand()
+
+ // getCommandStartTime()
+
+ /**
+ * Sets the driver used to communicate with the database.
+ *
+ * @param session the driver used to communicate with the database
+ * @param securityDomainURI the security domain of the <var>session</var>
+ * @throws QueryException if the state of the original session couldn't be
+ * propagated to the new <var>session</var>.
+ */
+ void setSession(Session session, URI securityDomainURI) throws QueryException {
+ // override all sessions with the provided one.
+ if (providedSession != null) {
+ session = providedSession;
+ return;
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "Setting session to " + session + ", security domain " +
+ securityDomainURI
+ );
+ }
+
+ // Short-circuit reassignment of the same session
+ if (this.session == session) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Didn't need to set session");
+ }
+ return;
+ }
+
+ // We can't change sessions if we're in the midst of a transaction which
+ // has already updated the server
+ if (transactionUpdated) {
+ throw new QueryException(
+ "Can't access more than one server in a transaction"
+ );
+ }
+
+ // Propagate the autoCommit property to the new session
+ if (!autoCommit) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Setting autocommit to " + autoCommit + " on " + serverURI);
+ }
+ if (session != null) {
+ session.setAutoCommit(autoCommit);
+ }
+ if (this.session != null) {
+ this.session.setAutoCommit(true); // TODO: this requires a compensating
+ // transaction in case of
+ // failure
+ }
+ }
+
+ // Propagate the login to the new session
+ Login login = (Login) loginMap.get(securityDomainURI);
+ if (login != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Logging " + login.username + " into " + serverURI);
+ }
+ session.login(securityDomainURI, login.username, login.password);
+ }
+ else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("No credentials to propagate for " + securityDomainURI);
+ }
+ }
+
+ if (this.session != null) {
+ // Close existing session
+ if (logger.isDebugEnabled()) {
+ logger.debug("Closing session");
+ }
+
+ try {
+ this.session.close();
+ }
+ catch (QueryException e) {
+ logger.warn("Couldn't close session (abandoning)", e);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Closed session");
+ }
+ }
+
+ // Reassign session
+ if (session != null) {
+ isLocal = session.isLocal();
+ }
+ this.session = session;
+ this.securityDomainURI = securityDomainURI;
+ }
+
+ // getCommandStartTime()
+
+ /**
+ * Sets the alias map associated with this session.
+ *
+ * @param aliasMap the alias map associated with this session
+ */
+ void setAliasMap(Map<String,URI> aliasMap) {
+ this.aliasMap = aliasMap;
+ }
+
+ /**
+ * Returns the alias map associated with this session.
+ *
+ * @return the alias namespace map associated with this session
+ */
+ Map<String,URI> getAliasMap() {
+ return this.aliasMap;
+ }
+
+ /**
+ * Builds a list of {@link org.mulgara.query.Variable}s from a list of
+ * {@link org.mulgara.itql.node.PVariable}s. Note. Variables in both the
+ * <code>rawVariableList</code> and the returned list will <strong>not
+ * </strong> contain the variable prefix <code>$</code> in their name.
+ *
+ * @param rawVariableList a list of {@link
+ * org.mulgara.itql.node.PVariable}s from the parser
+ * @return a list of {@link org.mulgara.query.Variable}s, suitable for use
+ * in creating a {@link org.mulgara.query.Query}
+ * @throws QueryException if the <code>rawVariableList</code> cannot be parsed
+ * into a list of {@link org.mulgara.query.Variable}s
+ */
+ List<Object> buildVariableList(LinkedList rawVariableList) throws
+ QueryException, URISyntaxException {
+
+ // Empty variable list.
+ if (rawVariableList == null) {
+ return (List<Object>)Collections.EMPTY_LIST;
+ }
+
+ // validate rawVariableList parameter
+ if (rawVariableList.size() == 0) {
+ throw new IllegalArgumentException("Empty \"rawVariableList\" parameter");
+ }
+
+ // Construct the required builder
+ VariableBuilder variableBuilder = new VariableBuilder(this,
+ variableFactory);
+
+ // end if
+ // log that we're building the variable list
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building variable list from " + rawVariableList);
+ }
+
+ // copy each variable from the query into the list
+ for (Iterator i = rawVariableList.iterator(); i.hasNext(); ) {
+ PElement element = (PElement) i.next();
+ element.apply( (Switch) variableBuilder);
+ }
+
+ // Get the variable list
+ List<Object> variableList = variableBuilder.getVariableList();
+
+ // make sure that we return a list with something in it
+ if (variableList.size() == 0) {
+ throw new QueryException("No variables parseable from query");
+ }
+
+ // log that we've successfully built the variable list
+ if (logger.isDebugEnabled()) {
+ logger.debug("Built variable list " + variableList);
+ }
+
+ // return the list
+ return variableList;
+ }
+
+ /**
+ * Builds a list of {@link org.mulgara.query.Variable}s from a list of
+ * {@link org.mulgara.itql.node.POrderElement}s. Note. Variables in both
+ * the <code>rawVariableList</code> and the returned list will <strong>not
+ * </strong> contain the variable prefix <code>$</code> in their name.
+ *
+ * @param rawOrderList PARAMETER TO DO
+ * @return a list of {@link org.mulgara.query.Variable}s, suitable for use
+ * in creating a {@link org.mulgara.query.Query}
+ * @throws QueryException if the <code>rawOrderElementList</code> cannot be
+ * parsed into a list of {@link org.mulgara.query.Variable}s
+ */
+ List buildOrderList(LinkedList rawOrderList) throws QueryException {
+
+ // validate rawOrderElementList parameter
+ if ( (rawOrderList == null) || (rawOrderList.size() == 0)) {
+
+ throw new IllegalArgumentException("Null \"rawOrderList\" parameter");
+ }
+
+ // end if
+ // log that we're building the variable list
+ if (logger.isDebugEnabled()) {
+ logger.debug("Building order list from " + rawOrderList);
+ }
+
+ // create a list for the parsed variables
+ List orderList = new ArrayList(rawOrderList.size());
+
+ // copy each variable from the query into the list
+ for (Iterator i = rawOrderList.iterator(); i.hasNext(); ) {
+
+ AOrderElement order = (AOrderElement) i.next();
+
+ // get the name of this variable
+ String variableName =
+ ( (AVariable) order.getVariable()).getIdentifier().getText();
+
+ // log that we've found a variable
+ if (logger.isDebugEnabled()) {
+ logger.debug("Found variable $" + variableName);
+ }
+
+ // Figure out which way to order, ascending or descending
+ boolean ascending;
+ PDirection direction = order.getDirection();
+
+ if (direction == null) {
+ ascending = true;
+ }
+ else if (direction instanceof AAscendingDirection) {
+ ascending = true;
+ }
+ else if (direction instanceof ADescendingDirection) {
+ ascending = false;
+ }
+ else {
+ throw new Error("Unknown direction field in order");
+ }
+
+ // add a new variable to the list
+ orderList.add(new Order(new Variable(variableName), ascending));
+ }
+
+ // end for
+ // make sure that we return a list with something in it
+ if (orderList.size() == 0) {
+
+ throw new QueryException("No variables parseable from query");
+ }
+
+ // log that we've successfully built the order list
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Built order list " + orderList);
+ }
+
+ // return the list
+ return orderList;
+ }
+
+ /**
+ * Resets the parser state in preparation for a new command.
+ */
+ private void resetInterpreter() {
+ lastCommand = null;
+ lastError = null;
+ }
+
+
+ /**
+ * Notify that the current session has been updated.
+ */
+ private void update() {
+ transactionUpdated = !autoCommit;
+ }
+
+ // outASelectCommand()
+
+ /**
+ * If the <code>FROM</code> clause of query refers to models in a different
+ * server than the one we're pointed at, change the {@link #session}.
+ *
+ * @param modelExpression a <code>FROM</code> clause, never <code>null</code>
+ * @throws QueryException if the <var>modelExpression</var> can't be resolved
+ * by any single server
+ */
+ private void updateSession(ModelExpression modelExpression) throws
+ QueryException {
+ assert modelExpression != null;
+
+ if (providedSession != null) {
+ session = providedSession;
+ return;
+ }
+
+ URI databaseURI = null;
+
+ // Check to see that we're aimed at the right server
+ Set databaseURISet = modelExpression.getDatabaseURIs();
+ assert databaseURISet != null;
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "Current server is " + serverURI + ", updating for " + databaseURISet
+ );
+ }
+ switch (databaseURISet.size()) {
+ case 0:
+
+ // Query presumably contains only URLs -- any server can deal with
+ // this, including the current one
+ if (session == null) {
+ try {
+ serverURI = SessionFactoryFinder.findServerURI();
+
+ SessionFactory sessionFactory =
+ SessionFactoryFinder.newSessionFactory(serverURI, !isLocal);
+
+ // Switch the underlying session to point at the required server
+ setSession(sessionFactory.newSession(),
+ sessionFactory.getSecurityDomain());
+ }
+ catch (SessionFactoryFinderException e) {
+ throw new QueryException("Unable to connect to a server", e);
+ }
+ catch (NonRemoteSessionException e) {
+ throw new QueryException("Error connecting to the local server", e);
+ }
+ }
+ assert session != null;
+ break;
+
+ case 1:
+
+ // Query must go to a particular server
+ databaseURI = (URI) databaseURISet.iterator().next();
+ assert databaseURI != null;
+ if (!databaseURI.equals(serverURI)) {
+ setServerURI(databaseURI);
+ }
+ assert databaseURI.equals(serverURI);
+ break;
+
+ default:
+
+ // Query must be distributed between multiple servers
+ assert databaseURISet.size() > 1;
+
+ if (!databaseURISet.contains(serverURI)) {
+ // We're not even aimed at one of the servers involved in this query,
+ // so choose one arbitrarily and switch to it
+ databaseURI = (URI) databaseURISet.iterator().next();
+ assert databaseURI != null;
+ setServerURI(databaseURI);
+ assert databaseURI.equals(serverURI);
+ }
+
+ // We're now connected to one of the servers involved in this query.
+ assert databaseURISet.contains(serverURI);
+ break;
+ }
+ }
+
+ /**
+ * Sets the option to enable the timing of commands.
+ *
+ * @param timeOption the option to enable the timing of commands
+ */
+ private void setTimeOption(boolean timeOption) {
+
+ this.timeOption = timeOption;
+ }
+
+ // getTimeOption()
+
+ /**
+ * Sets the time a command started.
+ *
+ * @param commandStartTime the time a command started
+ */
+ private void setCommandStartTime(long commandStartTime) {
+
+ this.commandStartTime = commandStartTime;
+ }
+
+ // getCommandStartTime()
+
+ /**
+ * Sets the results of the last query. Methods overriding <code>DepthFirstAdapter</code>
+ * are expected to set a result for successful queries, and <code>null</code>
+ * for failed ones.
+ *
+ * @param lastAnswer the results of the last command execution
+ */
+ private void setLastAnswer(Answer lastAnswer) {
+
+ this.lastAnswer = lastAnswer;
+ }
+
+ /**
+ * Insert a set of triples. Calls the server if it can be done only on the
+ * server.
+ *
+ * @param tripleFactor a triple, model or query from the parser
+ * @throws QueryException if <code>tripleFactor</code> contains a query that
+ * cannot be executed, or after evaluation contains no statements
+ * @throws URISyntaxException if <code>tripleFactor</code> contains a query or
+ * a resource that that violates <a
+ * href="http://www.isi.edu/in-notes/rfc2396.txt">RFC\uFFFD2396</a>
+ */
+ private void insertStatements(URI modelURI, PTripleFactor tripleFactor) throws
+ QueryException, URISyntaxException {
+
+ // validate tripleFactor parameter
+ if (tripleFactor == null) {
+
+ throw new IllegalArgumentException("Null \"tripleFactor\" parameter");
+ }
+
+ // log that we're finding statements
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Finding statements in expression " + tripleFactor);
+ }
+
+ // get the set of triples out of the factor
+ PSetOfTriples setOfTriples = null;
+
+ if (tripleFactor instanceof ABracedTripleFactor) {
+
+ setOfTriples = ((ABracedTripleFactor)tripleFactor).getSetOfTriples();
+ } else if (tripleFactor instanceof AUnbracedTripleFactor) {
+
+ setOfTriples = ((AUnbracedTripleFactor)tripleFactor).getSetOfTriples();
+ }
+
+ // drill down into the set of triples
+ if (setOfTriples instanceof AResourceSetOfTriples) {
+
+ // log that we've found a resource
+ if (logger.isDebugEnabled()) {
+
+ URI resourceURI = toURI(((AResourceSetOfTriples)setOfTriples).getResource());
+ logger.debug("Found resource " + resourceURI + "in triple factor");
+ }
+
+ // TODO: implement this once we can select all triples from a model
+ // we cannot currently handle inserting or deleting a complete model
+ // into/from another
+ throw new UnsupportedOperationException("Models cannot be inserted " +
+ "into or deleted from other models");
+ } else if (setOfTriples instanceof ASelectSetOfTriples) {
+
+ // build the query
+ Query query = this.buildQuery(((ASelectSetOfTriples)setOfTriples));
+
+ // log that we've created the query and will execute it
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Executing query " + query);
+ }
+
+ getSession().insert(modelURI, query);
+ } else if (setOfTriples instanceof ATripleSetOfTriples) {
+
+ Map<String,VariableNodeImpl> variableMap = new HashMap<String,VariableNodeImpl>();
+ Set<org.jrdf.graph.Triple> statements = getStatements((ATripleSetOfTriples)setOfTriples, variableMap);
+ getSession().insert(modelURI, statements);
+ }
+ }
+
+ /**
+ * Delete a set of triples. Calls the server if it can be done only on the
+ * server.
+ *
+ * @param tripleFactor a triple, model or query from the parser
+ * @throws QueryException if <code>tripleFactor</code> contains a query that
+ * cannot be executed, or after evaluation contains no statements
+ * @throws URISyntaxException if <code>tripleFactor</code> contains a query or
+ * a resource that that violates <a
+ * href="http://www.isi.edu/in-notes/rfc2396.txt">RFC\uFFFD2396</a>
+ */
+ private void deleteStatements(URI modelURI, PTripleFactor tripleFactor) throws
+ QueryException, URISyntaxException {
+
+ // validate tripleFactor parameter
+ if (tripleFactor == null) {
+
+ throw new IllegalArgumentException("Null \"tripleFactor\" parameter");
+ }
+
+ // log that we're finding statements
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Finding statements in expression " + tripleFactor);
+ }
+
+ // get the set of triples out of the factor
+ PSetOfTriples setOfTriples = null;
+
+ if (tripleFactor instanceof ABracedTripleFactor) {
+
+ setOfTriples = ( (ABracedTripleFactor) tripleFactor).getSetOfTriples();
+ } else if (tripleFactor instanceof AUnbracedTripleFactor) {
+
+ setOfTriples = ( (AUnbracedTripleFactor) tripleFactor).getSetOfTriples();
+ }
+
+ // drill down into the set of triples
+ if (setOfTriples instanceof AResourceSetOfTriples) {
+
+ // log that we've found a resource
+ if (logger.isDebugEnabled()) {
+
+ URI resourceURI = toURI(((AResourceSetOfTriples)setOfTriples).getResource());
+ logger.debug("Found resource " + resourceURI + "in triple factor");
+ }
+
+ // TODO: implement this once we can select all triples from a model
+ // we cannot currently handle inserting or deleting a complete model
+ // into/from another
+ throw new UnsupportedOperationException("Models cannot be inserted " +
+ "into or deleted from other models");
+ } else if (setOfTriples instanceof ASelectSetOfTriples) {
+
+ // build the query
+ Query query = this.buildQuery( ( (ASelectSetOfTriples) setOfTriples));
+
+ // log that we've created the query and will execute it
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Executing query " + query);
+ }
+
+ getSession().delete(modelURI, query);
+
+ } else if (setOfTriples instanceof ATripleSetOfTriples) {
+
+ Map<String,VariableNodeImpl> variableMap = new HashMap<String,VariableNodeImpl>();
+ Set<org.jrdf.graph.Triple> statements = getStatements((ATripleSetOfTriples)setOfTriples, variableMap);
+ if (variableMap.size() > 0) {
+ throw new QueryException("Cannot use variables when deleting statements");
+ }
+ getSession().delete(modelURI, statements);
+ }
+ }
+
+ /**
+ * Builds a set of {@link org.jrdf.graph.Triple}s from a
+ * {@link org.mulgara.query.Answer}.
+ *
+ * @param answer the results of a query
+ * @return a set of {@link org.jrdf.graph.Triple}s, suitable for use in
+ * inserting or deleting data to or from a model
+ * @throws QueryException EXCEPTION TO DO
+ */
+ private Set getStatements(Answer answer) throws QueryException {
+
+ // validate answer parameter
+ if (answer == null) {
+
+ throw new IllegalArgumentException("Null \"answer\" parameter");
+ } // end if
+
+ // log that we're parsing an answer into a set of statements
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Parsing answer into set of statements");
+ }
+
+ try {
+ Set statements = new HashSet();
+ answer.beforeFirst();
+
+ while (answer.next()) {
+
+ if (! (answer.getObject(0) instanceof ObjectNode)) {
+
+ throw new QueryException("Subject is not a resource for [" +
+ answer.getObject(0) + " " +
+ answer.getObject(1) +
+ " " +
+ answer.getObject(2) + "]");
+ }
+
+ if (! (answer.getObject(1) instanceof URIReference)) {
+
+ throw new QueryException("Predicate is not a resource for [" +
+ answer.getObject(0) + " " +
+ answer.getObject(1) +
+ " " +
+ answer.getObject(2) + "]");
+ }
+
+ statements.add(new TripleImpl( (SubjectNode) answer.getObject(0),
+ (PredicateNode) answer.getObject(1),
+ (ObjectNode) answer.getObject(2)));
+ }
+
+ logger.debug("Parsed answer into " + statements.size());
+
+ return statements;
+ }
+ catch (TuplesException e) {
+ throw new QueryException("Couldn't parse answer into statements", e);
+ }
+ } // setStatements
+
+ /**
+ * Returns the option to enable the timing of commands.
+ *
+ * @return the option to enable the timing of commands
+ */
+ private boolean getTimeOption() {
+
+ return timeOption;
+ }
+
+ /**
+ * Return the time a command started.
+ *
+ * @return the time a command started
+ */
+ private long getCommandStartTime() {
+
+ return commandStartTime;
+ }
+
+ /**
+ * Constructs a {@link org.jrdf.graph.Node} from a {@link
+ * org.mulgara.itql.node.PTripleElement}.
+ *
+ * @param element dd
+ * @param variableMap a {@link Map} of variable names (as string) to
+ * {@link VariableNodeImpl} that are used to contain all variables.
+ * @return dd
+ * @throws QueryException if <code>element</code> is a {@link
+ * org.mulgara.itql.node.AResourceTripleElement} whose text contains a
+ * <a href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">qualified
+ * name</a> with a prefix not defined in the <code>aliasMap</code>
+ * @throws URISyntaxException if <code>element</code> is a {@link
+ * org.mulgara.itql.node.AResourceTripleElement} whose text doesn't
+ * conform to <a href="http://www.isi.edu/in-notes/rfc2396.txt">
+ * RFC\uFFFD2396</a>
+ */
+ private org.jrdf.graph.Node toNode(PTripleElement element, Map<String,VariableNodeImpl> variableMap) throws
+ QueryException, URISyntaxException {
+
+ // validate the element parameter
+ if (element == null) {
+
+ throw new IllegalArgumentException("Null \"element\" parameter");
+ }
+
+ // end if
+ // log what we're doing
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Resolving " + element + "to a RDF node");
+ }
+
+ // create the node
+ org.jrdf.graph.Node node = null;
+
+ // get the node
+ if (element instanceof ALiteralTripleElement) {
+
+ // create a new literal with the given text
+ node = toLiteralImpl( ( (ALiteralTripleElement) element).getLiteral());
+ }
+ else if (element instanceof AResourceTripleElement) {
+
+ // create a new resource
+ node = new URIReferenceImpl(toURI(
+ ( (AResourceTripleElement) element).getResource()
+ ));
+ }
+ else if (element instanceof AVariableTripleElement) {
+
+ // get the variable
+ String variableName =
+ ( (AVariable) ( (AVariableTripleElement) element).getVariable()).
+ getIdentifier().getText();
+
+ // log what we're doing
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Resolved " + element + " to variable " + variableName);
+ }
+
+ if (variableMap.containsKey(variableName)) {
+
+ node = (VariableNodeImpl) variableMap.get(variableName);
+ }
+ else {
+
+ VariableNodeImpl variable = new VariableNodeImpl(variableName);
+ variableMap.put(variableName, variable);
+ node = variable;
+ }
+ } // end if
+
+ // return the node
+ return node;
+ }
+
+ /**
+ * Determines if the stream is compressed by inspecting the fileName extension.
+ *
+ * Returns a new "Compressed" stream if the file is compressed or the original
+ * InputStream if the file is not compressed.
+ *
+ * @param fileName String
+ * @param inputStream InputStream
+ * @throws IOException
+ * @return InputStream
+ */
+ private InputStream adjustForCompression(String fileName,
+ InputStream inputStream) throws IOException {
+
+ //validate
+ if (fileName == null) {
+ throw new IllegalArgumentException("File name is null");
+ }
+ if (inputStream == null) {
+ throw new IllegalArgumentException("InputStream is null");
+ }
+
+ InputStream stream = inputStream;
+
+ // Guess at transfer encoding (compression scheme) based on file extension
+ if (fileName.toLowerCase().endsWith(".gz")) {
+ // The file name ends with ".gz", so assume it's a gzip'ed file
+ stream = new GZIPInputStream(inputStream);
+ }
+ else if (fileName.toLowerCase().endsWith(".zip")) {
+ // The file name ends with ".zip", so assume it's a zip'ed file
+ stream = new ZipInputStream(inputStream);
+ }
+
+ assert stream != null;
+ return stream;
+ }
+
+ /**
+ * Adds a name/value pair to the alias map. This method will add associate a
+ * prefix for a target for subsequent commands, making commands like the
+ * following possible: <PRE>
+ * alias http://purl.org/dc/elements/1.1 as dc;
+ * select $title where $uri dc:title $title ;
+ * </PRE>
+ *
+ * @param aliasPrefix the alias that denotes the target
+ * @param aliasTarget the target associated with the prefix
+ */
+ private void addAliasPair(String aliasPrefix, URI aliasTarget) {
+
+ // validate the aliasPrefix parameter
+ if (aliasPrefix == null) throw new IllegalArgumentException("Null \"aliasPrefix\" " + "parameter");
+
+ // validate the aliasTarget parameter
+ if (aliasTarget == null) throw new IllegalArgumentException("Null \"aliasTarget\" " + "parameter");
+
+ // add the pair to the map
+ getAliasMap().put(aliasPrefix, aliasTarget);
+ }
+
+ /**
+ * Log the iTQL command to a specified file
+ *
+ * @param command PARAMETER TO DO
+ */
+ private void logItql(String command) {
+
+ // Has this session been constructed for logging.
+ // the constructor initialise this if
+ // system property itql.command.log is set
+ if (itqlLogFile == null) {
+
+ return;
+ }
+
+ try {
+ // has the log file been opened?
+ if (itqlLog == null) {
+ itqlLog = new PrintWriter(new FileWriter(itqlLogFile, true), true);
+ }
+
+ // append the command to the file
+ itqlLog.println(command);
+ }
+ catch (Exception ex) {
+ logger.error("Unable to log itql commands", ex);
+ }
+ }
+
+ /**
+ * Builds a HAVING compliant {@link org.mulgara.query.ConstraintExpression} object from a
+ * {@link org.mulgara.itql.node.PConstraintExpression}, using an <code>aliasMap</code>
+ * to resolve aliases. To comply with a HAVING clause the predicate must be one of:
+ * mulgara:occurs mulgara:occursLessThan mulgara:occursMoreThan.
+ *
+ * @param expression a constraint expression from the parser
+ * @return RETURNED VALUE TO DO
+ * @throws QueryException if <code>rawConstraintExpression</code> does not
+ * represent a valid query
+ * @throws URISyntaxException if the <code>rawConstraintExpression</code>
+ * contains a resource whose text violates <a
+ * href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
+ */
+ ConstraintHaving buildHaving(PConstraintExpression expression)
+ throws QueryException, URISyntaxException {
+ ConstraintExpression hExpr = build(expression);
+
+ if (hExpr instanceof ConstraintOperation) {
+ throw new QueryException("Having currently supports only one constraint");
+ }
+
+ if (!checkHavingPredicates(hExpr)) {
+ throw new QueryException("Only \"occurs\" predicates can be used in a Having clause");
+ }
+ return (ConstraintHaving) hExpr;
+ }
+
+
+ /**
+ * Checks that all predicates in a constraint expression are valid Having predicates
+ * from {@link SpecialPredicates}.
+ *
+ * @param e The constraint expression to check.
+ * @return true if all constraints have special predicates.
+ */
+ private boolean checkHavingPredicates(ConstraintExpression e) {
+ if (e instanceof Constraint) {
+ return e instanceof ConstraintHaving;
+ } else if (e instanceof ConstraintOperation) {
+ // check all sub expressions
+ Iterator i = ((ConstraintOperation)e).getElements().iterator();
+ while (i.hasNext()) {
+ if (checkHavingPredicates((ConstraintExpression)i.next())) {
+ return false;
+ }
+ }
+ // all sub expressions returned true
+ return true;
+ } else {
+ // An unexpected type
+ return false;
+ }
+ }
+
+
+ /**
+ * Set the active server for a backup given either a server URI or
+ * a model URI.
+ *
+ * @param sourceURI URI
+ */
+
+ private void setBackupServer( URI sourceURI ) throws QueryException {
+
+ //Determine if a model or a server is being backed up.
+ if ( (sourceURI != null)
+ && (sourceURI.getFragment() != null)) {
+
+ // make a note that a model is being backed up
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Model Found. Backing up model " + sourceURI );
+ }
+
+ //remove fragment from the model URI
+ String fragment = sourceURI.getFragment();
+ String serverURI = sourceURI.toString().replaceAll("#" + fragment, "");
+
+ //create URI for the model's server
+ try {
+
+ URI uri = new URI(serverURI);
+
+ //get session for the model's server.
+ setServerURI(uri);
+
+ //update the session (required if this is the first query)
+ this.updateSession(new ModelResource(uri));
+
+ }
+ catch (URISyntaxException uriException) {
+
+ //this will be caught below
+ throw new QueryException("Could not connect to model's Server.",
+ uriException);
+ }
+ }
+ else {
+
+ // log that we're backing up a server
+ if (logger.isDebugEnabled()) {
+
+ logger.debug("Backing up server " + sourceURI );
+ }
+
+ //source is a server.
+ setServerURI(sourceURI);
+ }
+ }
+
+
+ /**
+ * Try to recognise a uri alias, and return the canonical form instead.
+ *
+ * @param uri The URI being checked.
+ * @return The updated URI. May be the same as the uri parameter.
+ */
+ private URI getCanonicalUriAlias(URI uri) {
+ // only do this for remote protocols
+ if (!"rmi".equals(uri.getScheme()) && !"soap".equals(uri.getScheme())) {
+ return uri;
+ }
+ logger.debug("Checking for an alias on: " + uri);
+ // extract the host name
+ String host = uri.getHost();
+ if (host == null) {
+ return uri;
+ }
+ Set hostnames = getHostnameAliases();
+ // Check with a DNS server to see if this host is recognised
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getByName(host);
+ } catch (UnknownHostException uhe) {
+ // The host was unknown, so allow resolution to continue as before
+ return uri;
+ }
+ // check the various names against known aliases and the given name
+ if (
+ hostnames.contains(host) ||
+ hostnames.contains(addr.getHostName()) ||
+ hostnames.contains(addr.getCanonicalHostName()) ||
+ hostnames.contains(addr.getHostAddress())
+ ) {
+ // change the host name to one that is recognised
+ // use the system uri to find the local host name
+ URI serverURI = getServerURI();
+ if (serverURI == null) {
+ return uri;
+ }
+ String newHost = serverURI.getHost();
+ try {
+ return new URI(uri.getScheme(), newHost, uri.getPath(), uri.getFragment());
+ } catch (URISyntaxException e) { /* fall through */ }
+ }
+
+ // not found, so return nothing
+ return uri;
+ }
+
+
+ /**
+ * Method to ask the ServerInfo for the local server aliases.
+ * This will return an empty set if ServerInfo is not available -
+ * ie. being run on a host which has no local database, such an an iTQL client.
+ *
+ * @return The set of server aliases as strings
+ */
+ private static Set getHostnameAliases() {
+ Set names = (Set)getServerInfoProperty("HostnameAliases");
+ return (names == null) ? java.util.Collections.EMPTY_SET : names;
+ }
+
+
+ /**
+ * Method to ask the ServerInfo for the local server URI.
+ * This will return null if ServerInfo is not available -
+ * ie. being run on a host which has no local database, such an an iTQL client.
+ *
+ * @return The URI of the local server, or null if this is not a server.
+ */
+ private static URI getServerURI() {
+ return (URI)getServerInfoProperty("ServerURI");
+ }
+
+
+ /**
+ * Method to get the value of a property from the ServerInfo for the local database session.
+ * This will return null if ServerInfo is not available -
+ * ie. being run on a host which has no local database, such an an iTQL client.
+ *
+ * @param property The property to return, with the correct case.
+ * @return The object returned from the accessor method named, or null if ServerInfo is not available.
+ */
+ private static Object getServerInfoProperty(String property) {
+ Object o = null;
+ try {
+ Class rsf = Class.forName("org.mulgara.server.ServerInfo");
+ java.lang.reflect.Method getter = rsf.getMethod("get" + property, null);
+ o = getter.invoke(null, null);
+ } catch (Exception e) { /* no op */ }
+ return o;
+ }
+
+ private class Lexer2 extends Lexer {
+
+ int commandCount = 0;
+ final LinkedList leftoverTokenList = new LinkedList();
+
+ public Lexer2() {
+ super(null);
+ }
+
+ public int getCommandCount() {
+ return commandCount;
+ }
+
+ public void add(String command) throws LexerException, IOException {
+ Lexer lexer = new Lexer(new PushbackReader(new StringReader(command), 256));
+ Token t;
+ while (! ( (t = lexer.next()) instanceof EOF)) {
+ if (t instanceof TTerminator) {
+ t = new EOF();
+ commandCount++;
+ }
+ leftoverTokenList.add(t);
+ }
+ }
+
+ public Token next() throws LexerException, IOException {
+ return leftoverTokenList.isEmpty() ? new EOF() : (Token) leftoverTokenList.removeFirst();
+ }
+
+ public Token peek() throws LexerException, IOException {
+ return leftoverTokenList.isEmpty() ? new EOF() : (Token) leftoverTokenList.getFirst();
+ }
+
+ public boolean nextCommand() {
+ if (commandCount == 0) {
+ return false;
+ }
+ else {
+ //assert commandCount > 0;
+ commandCount--;
+ return true;
+ }
+ }
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/URIUtil.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/URIUtil.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/URIUtil.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,51 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.itql;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Map;
+
+/**
+ * A set of methods for managing common URI operations.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class URIUtil {
+
+ /**
+ * Replace an alias in a URI, if one is recognized.
+ * @param uriString A string with the initial uri to check for aliases.
+ * @param aliasMap The map of known aliases to the associated URIs
+ * @return A new URI with the alias replaced, or the original if no alias is found.
+ */
+ public static URI convertToURI(String uriString, Map<String,URI> aliasMap) {
+ try {
+ URI uri = new URI(uriString);
+ if (uri.isOpaque()) {
+ // Attempt qname-to-URI substitution for aliased namespace prefixes
+ URI mapping = aliasMap.get(uri.getScheme());
+ if (mapping != null) {
+ uri = new URI(mapping + uri.getSchemeSpecificPart());
+ }
+ }
+ return uri;
+ } catch (URISyntaxException e) {
+ throw new Error("Bad URI syntax in resource: " + e);
+ }
+ }
+
+}
Modified: branches/nw-interface/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/VariableBuilder.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -88,14 +88,14 @@
private QueryException queryException = null;
/**
- * The list of variables
+ * The list of variables - these are mixed object types
*/
- private List variableList;
+ private List<Object> variableList;
/**
* The iTQL interpreter
*/
- private ItqlInterpreter interpreter;
+ private Interpreter interpreter;
/**
* Create a new builder. Requires methods on the interpreter in order to
@@ -103,10 +103,10 @@
*
* @param newInterpreter the interpreter to use.
*/
- public VariableBuilder(ItqlInterpreter newInterpreter,
+ public VariableBuilder(Interpreter newInterpreter,
VariableFactory newVariableFactory) {
- variableList = new ArrayList();
+ variableList = new ArrayList<Object>();
interpreter = newInterpreter;
variableFactory = newVariableFactory;
}
@@ -209,10 +209,10 @@
* @throws URISyntaxException if the variable contains a resource whose
* text violates <a href="http://www.isi.edu/in-notes/rfc2396.txt">RFC?2396</a>
*/
- public List getVariableList() throws QueryException, URISyntaxException {
+ public List<Object> getVariableList() throws QueryException, URISyntaxException {
try {
- List tmpVariableList = new ArrayList(variableList);
+ List<Object> tmpVariableList = new ArrayList<Object>(variableList);
if (uriException != null) {
throw uriException;
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/ApplyRules.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/ApplyRules.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/ApplyRules.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,91 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+/**
+ * Represents a command to apply rules to a set of data.
+ *
+ * @created Aug 10, 2007
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class ApplyRules implements CommandAst {
+
+ /** The graph containing the rules to be run. */
+ private URI ruleGraph;
+
+ /** The graph containing the data to apply the rules to. */
+ private URI baseGraph;
+
+ /** The graph to put the rule productions into. */
+ private URI destGraph;
+
+ /**
+ * Create a new rules command.
+ * @param ruleGraph The graph containing the rules to be run.
+ * @param baseGraph The graph containing the data to apply the rules to.
+ * @param destGraph The graph to put the rule productions into.
+ */
+ public ApplyRules(URI ruleGraph, URI baseGraph, URI destGraph) {
+ this.ruleGraph = ruleGraph;
+ this.baseGraph = baseGraph;
+ this.destGraph = destGraph;
+ }
+
+ /**
+ * @return The URI of the graph containing rule productions.
+ */
+ public URI getServerURI() throws UnsupportedOperationException {
+ return destGraph;
+ }
+
+ /**
+ * Returns false to indicate that this is a server-side operation.
+ * @return Always <code>false</code>
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+ /**
+ * Returns false to indicate that this operation is not tied to a UI.
+ * @return Always <code>false</code>
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+ /**
+ * @return the ruleGraph
+ */
+ public URI getRuleGraph() {
+ return ruleGraph;
+ }
+
+ /**
+ * @return the baseGraph
+ */
+ public URI getBaseGraph() {
+ return baseGraph;
+ }
+
+ /**
+ * @return the destGraph
+ */
+ public URI getDestGraph() {
+ return destGraph;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CommandAst.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CommandAst.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CommandAst.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,46 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+/**
+ * A general Abstract Syntax Tree for TQL commands.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public interface CommandAst {
+
+ /**
+ * Indicates if an AST element is an operation for a local client.
+ * @return <code>true</code> if the operation is only relevant to a client.
+ */
+ boolean isLocalOperation();
+
+ /**
+ * Indicates if an AST represents a command for a user interface.
+ * @return <code>true</code> if the operation is only relevant to a user interface
+ */
+ boolean isUICommand();
+
+ /**
+ * Gets the associated server for a non-local operation.
+ * @return the server URI if one can be determined,
+ * or <code>null</code> if not a valid operation.
+ * @throws UnsupportedOperationException If this command is local only.
+ */
+ URI getServerURI() throws UnsupportedOperationException;
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Commit.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Commit.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Commit.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,55 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+
+/**
+ * An AST element for the COMMIT command.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class Commit implements CommandAst {
+
+ /**
+ * Indicates that this operation may require network access.
+ * @return <code>false</code> as network access may be needed.
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+
+ /**
+ * Indicates that this operation is not specific to a UI.
+ * @return <code>false</code> as operation is not specific to UIs.
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+
+ /**
+ * Requests a server URI for this operation. None available, as it
+ * operates on the local connection.
+ * @return <code>null</code>
+ */
+ public URI getServerURI() {
+ return null;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CreateGraph.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CreateGraph.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/CreateGraph.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,76 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+/**
+ * Represents a command to create a new graph.
+ * @created Aug 10, 2007
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class CreateGraph implements CommandAst {
+
+ /** The URI for the graph. */
+ private URI graphUri;
+
+ /** The URI for the type of the graph. */
+ private URI type;
+
+ public CreateGraph(URI graphUri, URI type) {
+ this.graphUri = graphUri;
+ this.type = type;
+ }
+
+ /**
+ * Finds the server URI for the graph.
+ * @return The URI used to find the server.
+ */
+ public URI getServerURI() {
+ return graphUri;
+ }
+
+ /**
+ * Indicates that this operation is for a server.
+ * @return Always <code>false</code>
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+ /**
+ * Indicates that this operation is not tied to the UI.
+ * @return Always <code>false</code>
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+ /**
+ * Get the URI of the graph to create.
+ * @return the URI of the graph to create.
+ */
+ public URI getGraphUri() {
+ return graphUri;
+ }
+
+ /**
+ * Get the type of the graph to create.
+ * @return the type of the graph.
+ */
+ public URI getType() {
+ return type;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/DropGraph.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/DropGraph.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/DropGraph.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,64 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+/**
+ * Represents a command to drop a graph.
+ * @created Aug 10, 2007
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class DropGraph implements CommandAst {
+
+ /** The URI for the graph. */
+ private URI graphUri;
+
+ public DropGraph(URI graphUri) {
+ this.graphUri = graphUri;
+ }
+
+ /**
+ * Finds the server URI for the graph.
+ * @return The URI used to find the server.
+ */
+ public URI getServerURI() {
+ return graphUri;
+ }
+
+ /**
+ * Indicates that this operation is for a server.
+ * @return Always <code>false</code>
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+ /**
+ * Indicates that this operation is not tied to the UI.
+ * @return Always <code>false</code>
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+ /**
+ * Get the URI of the graph to drop.
+ * @return the URI of the graph to drop.
+ */
+ public URI getGraphUri() {
+ return graphUri;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Help.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Help.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Help.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,47 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import org.mulgara.itql.HelpPrinter;
+import org.mulgara.itql.node.PCommandPrefix;
+
+/**
+ * An AST element for the HELP command.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class Help extends LocalAst {
+
+ private PCommandPrefix command;
+
+ public Help(PCommandPrefix command) {
+ this.command = command;
+ }
+
+ /**
+ * Indicates that this operation is for a UI.
+ * @return <code>true</code> as operation is for UI output only.
+ */
+ public boolean isUICommand() {
+ return true;
+ }
+
+ public String getOutput() {
+ // let the user know the help for the selected command
+ return HelpPrinter.getHelp(command);
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/LocalAst.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/LocalAst.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/LocalAst.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,30 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+public abstract class LocalAst implements CommandAst {
+
+ public boolean isLocalOperation() {
+ return true;
+ }
+
+ /**
+ * Gets the associated server for a non-local operation.
+ * @throws UnsupportedOperationException Always thrown for local commands.
+ */
+ public URI getServerURI() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Server URI not available for local commands.");
+ }
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Quit.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Quit.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Quit.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,34 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+
+/**
+ * An AST element for the QUIT command.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class Quit extends LocalAst {
+
+ /**
+ * Indicates that this operation is for a UI.
+ * @return <code>true</code> as operation is for UI output only.
+ */
+ public boolean isUICommand() {
+ return true;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Rollback.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Rollback.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/Rollback.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,53 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+
+/**
+ * An AST element for the ROLLBACK command.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class Rollback implements CommandAst {
+
+ /**
+ * Indicates that this operation may require network access.
+ * @return <code>false</code> as network access may be needed.
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+ /**
+ * Indicates that this operation is not specific to a UI.
+ * @return <code>false</code> as operation is not specific to UIs.
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+ /**
+ * Requests a server URI for this operation. None available, as it
+ * operates on the local connection.
+ * @return <code>null</code>
+ */
+ public URI getServerURI() {
+ return null;
+ }
+
+}
Added: branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/SetUser.java
===================================================================
--- branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/SetUser.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/query/ast/SetUser.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -0,0 +1,100 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.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.opensource.org/licenses/osl-3.0.txt
+ *
+ * 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.
+ */
+
+package org.mulgara.query.ast;
+
+import java.net.URI;
+
+
+/**
+ * An AST element for the COMMIT command.
+ *
+ * @created 2007-08-09
+ * @author Paul Gearon
+ * @copyright © 2007 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public class SetUser implements CommandAst {
+
+ /** The user logging in. */
+ private String user;
+
+ /** The password for the user, as provided in the UI. */
+ private String password;
+
+ /** The security domain to log in to. */
+ private URI securityDomain;
+
+ /**
+ * Create a new SetUser command.
+ * @param user The user logging in.
+ * @param password The password for the user.
+ * @param securityDomain The domain to log in to.
+ */
+ public SetUser(String user, String password, URI securityDomain) {
+ this.user = user;
+ this.password = password;
+ this.securityDomain = securityDomain;
+ }
+
+ /**
+ * Indicates that this operation may require network access.
+ * @return <code>false</code> as network access may be needed.
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+
+ /**
+ * Indicates that this operation is not specific to a UI.
+ * @return <code>false</code> as operation is not specific to UIs.
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+
+ /**
+ * Requests a server URI for this operation. None available, as it
+ * operates on the local connection.
+ * @return <code>null</code>
+ */
+ public URI getServerURI() {
+ return null;
+ }
+
+ /**
+ * Retrieves the user name.
+ * @return the user
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * Retrieves the user password.
+ * @return the password
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Retrieves the URI of the security domain.
+ * @return the securityDomain
+ */
+ public URI getSecurityDomain() {
+ return securityDomain;
+ }
+
+}
Modified: branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFGraphUnitTest.java
===================================================================
--- branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFGraphUnitTest.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFGraphUnitTest.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -305,7 +305,7 @@
*/
private void createModel(URI modelURI) throws Exception {
- this.session.createModel(modelURI, Session.MULGARA_MODEL_URI);
+ this.session.createModel(modelURI, Session.MULGARA_GRAPH_URI);
}
/**
Modified: branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFLocalGraphUnitTest.java
===================================================================
--- branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFLocalGraphUnitTest.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/jrdf/java/org/mulgara/jrdf/JRDFLocalGraphUnitTest.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -220,7 +220,7 @@
*/
private void createModel(URI modelURI) throws Exception {
- this.session.createModel(modelURI, Session.MULGARA_MODEL_URI);
+ this.session.createModel(modelURI, Session.MULGARA_GRAPH_URI);
}
/**
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelExpression.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelExpression.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelExpression.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -67,7 +67,7 @@
*
* @return a set containing the {@link URI}s of the databases
*/
- public Set getDatabaseURIs();
+ public Set<URI> getDatabaseURIs();
/**
* Generate the WHERE constraint equivalent to this FROM constraint. This
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelIntersection.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelIntersection.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelIntersection.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -70,15 +70,7 @@
}
/**
- * METHOD TO DO
- *
- * @param constraint PARAMETER TO DO
- * @param transformation PARAMETER TO DO
- * @param modelProperty PARAMETER TO DO
- * @param systemModel PARAMETER TO DO
- * @param variableFactory PARAMETER TO DO
- * @return RETURNED VALUE TO DO
- * @throws TransformationException EXCEPTION TO DO
+ * {@inheritDoc}
*/
public ConstraintExpression toConstraintExpression(Constraint constraint,
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelLiteral.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelLiteral.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelLiteral.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -122,9 +122,10 @@
/**
* @return an empty {@link Set}
*/
- public Set getDatabaseURIs() {
+ @SuppressWarnings("unchecked")
+ public Set<URI> getDatabaseURIs() {
- return Collections.EMPTY_SET;
+ return (Set<URI>)Collections.EMPTY_SET;
}
//
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelOperation.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelOperation.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelOperation.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -28,6 +28,7 @@
package org.mulgara.query;
// Java 2 standard packages
+import java.net.URI;
import java.util.*;
/**
@@ -110,9 +111,9 @@
*
* @return The DatabaseURIs value
*/
- public Set getDatabaseURIs() {
+ public Set<URI> getDatabaseURIs() {
- Set databaseURIs = new HashSet();
+ Set<URI> databaseURIs = new HashSet<URI>();
databaseURIs.addAll(lhs.getDatabaseURIs());
databaseURIs.addAll(rhs.getDatabaseURIs());
@@ -144,15 +145,15 @@
}
/**
- * METHOD TO DO
+ * Transform to an equivalent WHERE clause expression.
*
- * @param constraint PARAMETER TO DO
- * @param transformation PARAMETER TO DO
+ * @param constraint The constraint to transform with this expression.
+ * @param transformation The transformation to apply to the constraint leaf nodes.
* @param modelProperty PARAMETER TO DO
- * @param systemModel PARAMETER TO DO
- * @param variableFactory PARAMETER TO DO
- * @return RETURNED VALUE TO DO
- * @throws TransformationException EXCEPTION TO DO
+ * @param systemModel name of the system model
+ * @param variableFactory factory for building variables
+ * @return A {@link ConstraintExpression} that represents the transformed constraint.
+ * @throws TransformationException Unable to perform the transformation
*/
public abstract ConstraintExpression toConstraintExpression(
Constraint constraint,
@@ -164,6 +165,7 @@
// #SYSTEM
VariableFactory variableFactory) throws TransformationException;
+
/**
* Transform the left and right hand sides of this operation.
*
@@ -178,70 +180,63 @@
}
/**
- * METHOD TO DO
+ * Compares this model expression to another object. Compares true if of the same
+ * expression type (intersection/partition/union) and operates on objects that also
+ * compare equal.
*
- * @param m PARAMETER TO DO
- * @return RETURNED VALUE TO DO
+ * @param m The object to compare against.
+ * @return <code>true</code> if the objects are the same type,
+ * and applied to the same operands
*/
public boolean equals(Object m) {
+
+ if (!(m instanceof ModelOperation)) return false;
+ if ((m == null) || !m.getClass().equals(getClass())) return false;
+ if (m == this) return true;
- if ( (m == null) || m.getClass().equals(getClass())) {
+ Class<?> type = m.getClass();
- return false;
- }
+ Set<ModelExpression> otherExpressions = new HashSet<ModelExpression>();
+ ((ModelOperation)m).flattenExpression(otherExpressions, type);
- if (m == this) {
-
- return true;
- }
-
- Class type = m.getClass();
-
- Set otherExpressions = new HashSet();
- ( (ModelOperation) m).flattenExpression(otherExpressions, type);
-
- Set myExpressions = new HashSet();
+ Set<ModelExpression> myExpressions = new HashSet<ModelExpression>();
flattenExpression(myExpressions, type);
return myExpressions.equals(otherExpressions);
}
/**
- * METHOD TO DO
+ * Creates a hash code, based on the child expressions and the current operation type.
*
- * @return RETURNED VALUE TO DO
+ * @return The hash code for this object.
*/
public int hashCode() {
- Set myExpressions = new HashSet();
+ Set<ModelExpression> myExpressions = new HashSet<ModelExpression>();
flattenExpression(myExpressions, getClass());
return (getClass().hashCode() * 7) + myExpressions.hashCode();
}
/**
- * METHOD TO DO
+ * Traverse down the binary tree of the current object, and merge any nodes
+ * of the current type into a flattened set.
*
- * @param expressions PARAMETER TO DO
- * @param type PARAMETER TO DO
+ * @param expressions The set to be built up containing all nodes being
+ * operated on in the same way.
+ * @param type The class representing the operation type.
*/
- private void flattenExpression(Set expressions, Class type) {
+ private void flattenExpression(Set<ModelExpression> expressions, Class<?> type) {
if (lhs.getClass().equals(type)) {
-
- ( (ModelOperation) lhs).flattenExpression(expressions, type);
- }
- else {
-
+ ((ModelOperation)lhs).flattenExpression(expressions, type);
+ } else {
expressions.add(lhs);
}
if (rhs.getClass().equals(type)) {
-
- ( (ModelOperation) rhs).flattenExpression(expressions, type);
- }
- else {
-
+ ((ModelOperation)rhs).flattenExpression(expressions, type);
+ } else {
expressions.add(rhs);
}
}
@@ -252,20 +247,16 @@
public Object clone() {
try {
+ ModelOperation cloned = (ModelOperation)super.clone();
- ModelOperation cloned = (ModelOperation) super.clone();
-
// Copy database URIs.
- cloned.lhs = (ModelExpression) lhs.clone();
- cloned.rhs = (ModelExpression) rhs.clone();
+ cloned.lhs = (ModelExpression)lhs.clone();
+ cloned.rhs = (ModelExpression)rhs.clone();
return cloned;
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException("ModelOperation subclass " + getClass() + " not cloneable");
}
- catch (CloneNotSupportedException e) {
- throw new RuntimeException(
- "ModelOperation subclass " + getClass() + " not cloneable"
- );
- }
}
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelPartition.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelPartition.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelPartition.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -83,15 +83,7 @@
}
/**
- * METHOD TO DO
- *
- * @param constraint PARAMETER TO DO
- * @param transformation PARAMETER TO DO
- * @param modelProperty PARAMETER TO DO
- * @param systemModel PARAMETER TO DO
- * @param variableFactory PARAMETER TO DO
- * @return RETURNED VALUE TO DO
- * @throws TransformationException EXCEPTION TO DO
+ * {@inheritDoc}
*/
public ConstraintExpression toConstraintExpression(Constraint constraint,
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelResource.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelResource.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelResource.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -107,7 +107,8 @@
* the server if this is a Java RMI or BEEP model, or the empty {@link Set}
* otherwise
*/
- public Set getDatabaseURIs() {
+ @SuppressWarnings("unchecked")
+ public Set<URI> getDatabaseURIs() {
try {
@@ -121,18 +122,13 @@
uri.getPath(),
null,
null));
+ } else {
+ return (Set<URI>)Collections.EMPTY_SET;
}
- else {
-
- return Collections.EMPTY_SET;
- }
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Couldn't truncate model URI " + uri + " to obtain a database URI");
}
- catch (URISyntaxException e) {
- throw new RuntimeException("Couldn't truncate model URI " + uri +
- " to obtain a database URI");
- }
-
}
//
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelUnion.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelUnion.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/ModelUnion.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -70,15 +70,7 @@
}
/**
- * METHOD TO DO
- *
- * @param constraint PARAMETER TO DO
- * @param transformation PARAMETER TO DO
- * @param modelProperty PARAMETER TO DO
- * @param systemModel PARAMETER TO DO
- * @param variableFactory PARAMETER TO DO
- * @return RETURNED VALUE TO DO
- * @throws TransformationException EXCEPTION TO DO
+ * {@inheritDoc}
*/
public ConstraintExpression toConstraintExpression(Constraint constraint,
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/query/Query.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/query/Query.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/query/Query.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -29,10 +29,12 @@
// Java 2 standard packages;
import java.io.*;
+import java.net.URI;
import java.util.*;
// Third party packages
import org.apache.log4j.*;
+import org.mulgara.query.ast.CommandAst;
/**
* An ITQL query. This is a data structure used as an argument to the
@@ -55,7 +57,7 @@
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
-public class Query implements Cloneable, Serializable {
+public class Query implements Cloneable, Serializable, CommandAst {
/**
* Allow newer compiled version of the stub to operate when changes
@@ -516,4 +518,29 @@
}
out.defaultWriteObject();
}
+
+ /**
+ * Operation can only be run by a server.
+ * @return <code>false</code> as this is AST for a server.
+ */
+ public boolean isLocalOperation() {
+ return false;
+ }
+
+ /**
+ * Operation is not restricted to a user interface.
+ * @return <code>false</code> as this operation has no effect on a UI.
+ */
+ public boolean isUICommand() {
+ return false;
+ }
+
+ /**
+ * Gets the associated server for a non-local operation.
+ * @return the server URI, or <code>null</code> if the data should be found locally.
+ */
+ public URI getServerURI() {
+ Set<URI> dbURIs = getModelExpression().getDatabaseURIs();
+ return dbURIs.isEmpty() ? null : dbURIs.iterator().next();
+ }
}
Modified: branches/nw-interface/src/jar/query/java/org/mulgara/server/Session.java
===================================================================
--- branches/nw-interface/src/jar/query/java/org/mulgara/server/Session.java 2007-08-09 17:48:13 UTC (rev 346)
+++ branches/nw-interface/src/jar/query/java/org/mulgara/server/Session.java 2007-08-10 21:12:09 UTC (rev 347)
@@ -69,7 +69,7 @@
* This constant can be passed to {@link #createModel} to indicate that a
* normal model backed by a triple store is required.
*/
- public final URI MULGARA_MODEL_URI = ConstantFactory.getMulgaraModelURI();
+ public final URI MULGARA_GRAPH_URI = URI.create(Mulgara.NAMESPACE + "Model");
/**
* Insert statements into a model.
@@ -177,7 +177,7 @@
/**
* Creates a new model of a given type. The standard model type is
- * {@link #MULGARA_MODEL_URI}.
+ * {@link #MULGARA_GRAPH_URI}.
*
* @param modelURI the {@link URI} of the new model
* @param modelTypeURI the {@link URI} identifying the type of model to use
@@ -303,19 +303,4 @@
*/
public void login(URI securityDomain, String username, char[] password);
- /**
- * This class is just a devious way to get static initialization for the
- * {@link Session} interface.
- */
- abstract class ConstantFactory {
-
- static URI getMulgaraModelURI() {
- try {
- return new URI(Mulgara.NAMESPACE + "Model");
- }
- catch (URISyntaxException e) {
- throw new Error("Bad hardcoded URI");
- }
- }
- }
}
More information about the Mulgara-svn
mailing list