[Mulgara-svn] r358 - branches/nw-interface/src/jar/itql/java/org/mulgara/itql

pag at mulgara.org pag at mulgara.org
Tue Aug 21 05:37:22 UTC 2007


Author: pag
Date: 2007-08-21 00:37:21 -0500 (Tue, 21 Aug 2007)
New Revision: 358

Modified:
   branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java
Log:
Completely stripped out all functionality outside of processing an AST and maintaining local aliases. Also updated to using generics where possible

Modified: 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-20 20:41:42 UTC (rev 357)
+++ branches/nw-interface/src/jar/itql/java/org/mulgara/itql/TqlInterpreter.java	2007-08-21 05:37:21 UTC (rev 358)
@@ -39,9 +39,6 @@
 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
@@ -56,6 +53,7 @@
 import org.mulgara.itql.parser.*;
 import org.mulgara.query.*;
 import org.mulgara.query.ast.ApplyRules;
+import org.mulgara.query.ast.Backup;
 import org.mulgara.query.ast.CommandAst;
 import org.mulgara.query.ast.Commit;
 import org.mulgara.query.ast.CreateGraph;
@@ -67,22 +65,15 @@
 import org.mulgara.query.ast.Load;
 import org.mulgara.query.ast.Modification;
 import org.mulgara.query.ast.Quit;
+import org.mulgara.query.ast.Restore;
 import org.mulgara.query.ast.Rollback;
+import org.mulgara.query.ast.SetAutoCommit;
+import org.mulgara.query.ast.SetTime;
 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;
 import org.mulgara.util.Reflect;
 
-// 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.
@@ -98,9 +89,6 @@
  */
 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());
 
@@ -209,9 +197,7 @@
     }
 
     // log that we're going to execute the command
-    if (logger.isDebugEnabled()) {
-      logger.debug("Parsing command " + command);
-    }
+    if (logger.isDebugEnabled()) logger.debug("Parsing command " + command);
 
     // log the iTQL command - system property itql.command.log must be set
     this.logItql(command);
@@ -234,26 +220,16 @@
       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 {
+        // build the command
         // this populates lastCommand
         resetInterpreter();
         commandTree.apply(this);
         // take the lastCommand result, and add it to the list of results
         commandList.add(lastCommand);
+
+        if (logger.isDebugEnabled()) logger.debug("Successfully parsed command " + command);
+
       } catch (Exception e) {
         flush();
         throw e;
@@ -262,23 +238,11 @@
         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.
    *
@@ -291,9 +255,7 @@
   public Query parseQuery(String queryString) throws IOException,
       LexerException, ParserException {
 
-    if (queryString == null) {
-      throw new IllegalArgumentException("Null \"queryString\" parameter");
-    }
+    if (queryString == null) throw new IllegalArgumentException("Null \"queryString\" parameter");
 
     // clean up query
     queryString = queryString.trim();
@@ -302,19 +264,19 @@
     }
 
     // log that we're going to execute the command
-    if (logger.isDebugEnabled()) {
-      logger.debug("Parsing query \"" + queryString + "\"");
-    }
+    if (logger.isDebugEnabled()) logger.debug("Parsing query \"" + queryString + "\"");
 
-    // execute the command
+    // parse the command via double dispatch
     Parser parser = new Parser(new Lexer(new PushbackReader(new StringReader(queryString), 256)));
     resetInterpreter();
     parser.parse().apply(this);
 
+    // should now have the command parsed into lastCommand.
+    // check the the command worked as expected
     if (lastCommand == null) throw new ParserException(null, "Parameter was not a query");
+    if (!(lastCommand instanceof Query)) throw new IllegalArgumentException("Command was not a query: " + queryString);
 
     // return the results of the command
-    if (!(lastCommand instanceof Query)) throw new IllegalArgumentException("Command was not a query: " + queryString);
     return (Query)lastCommand;
   }
 
@@ -610,76 +572,18 @@
     // set the option
     if (option instanceof ATimeSetOption) {
 
-      // set the time option
-      this.setTimeOption(optionSet);
+      if (logger.isDebugEnabled()) logger.debug("Found set time: " + (optionSet ? "on" : "off"));
+      lastCommand = new SetTime(optionSet);
+    } else if (option instanceof AAutocommitSetOption) {
 
-      // return the user a message
-      this.setLastMessage("Command timing is " + (optionSet ? "on" : "off"));
-    }
-    else if (option instanceof AAutocommitSetOption) {
+      if (logger.isDebugEnabled()) logger.debug("Found autocommit: " + (optionSet ? "on" : "off"));
+      lastCommand = new SetAutoCommit(optionSet);
 
-      /* 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 {
+      lastError = new ItqlInterpreterException("Unknown interpreter option for \"SET\"");
     }
-    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.
    *
@@ -687,110 +591,16 @@
    */
   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()) {
+    if (logger.isDebugEnabled()) logger.debug("Processing backup command " + node);
 
-      logger.debug("Processing backup command " + node);
-    }
-
-    // get the server we'll be backing up
+    // get constituents of the backup command
     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
+    lastCommand = new Backup(sourceURI, destinationURI);
   }
 
-  // outABackupCommand()
-
   /**
    * Restores the contents of a server from a file.
    *
@@ -798,110 +608,15 @@
    */
   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()) {
+    if (logger.isDebugEnabled()) logger.debug("Processing restore command " + node);
 
-      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 ) {};
-      }
-    }
+    lastCommand = new Restore(sourceURI, destinationURI);
   }
 
   /**
@@ -960,8 +675,12 @@
     return statements;
   }
 
+
   /**
-   * Executes a query and returns its results.
+   * Creates a query from iTQL syntax and grammar.
+   * Despite onyl being accessed from within this package (both locally and from
+   * {@link VariableBuilder}) this method must be public, as it has to appear in
+   * the {@link Interpreter} interface.
    *
    * @param rawQuery a select query, represented as either a {@link
    *      org.mulgara.itql.node.ASelectCommand} or a {@link
@@ -972,18 +691,14 @@
    *      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 {
+  @SuppressWarnings("unchecked")
+  public Query buildQuery(org.mulgara.itql.node.Node rawQuery) throws QueryException, URISyntaxException {
   
     // validate query parameter
-    if (rawQuery == null) {
+    if (rawQuery == null) throw new IllegalArgumentException("Null \"rawQuery\" parameter");
   
-      throw new IllegalArgumentException("Null \"rawQuery\" parameter");
-    }
-  
-    // end if
-    // create the variables needed...
-    LinkedList variables = null;
+    // create the variables.  May contain a PElement; Count; URI literal; or a sub query
+    LinkedList<Object> variables = null;
     AFromClause fromClause;
     AWhereClause whereClause;
     AOrderClause orderClause;
@@ -998,184 +713,104 @@
       AQuery query = (AQuery) rawQuery;
       PSelectClause selectClause = query.getSelectClause();
       if (selectClause instanceof ANormalSelectSelectClause) {
-        variables = ( (ANormalSelectSelectClause) selectClause).getElement();
+        variables = (LinkedList<Object>)((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) {
+      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 = new LinkedList<Object>();
       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 {
+      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");
+      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);
-    }
-  
+    if (fromClause == null) throw new QueryException("FROM clause missing.");
+    if (whereClause == null) throw new QueryException("WHERE clause missing.");
+
     // build the variable list
-    List variableList = this.buildVariableList(variables);
+    if (logger.isDebugEnabled()) logger.debug("Building query variable list from " + variables);
+    List<Object> variableList = this.buildVariableList(variables);
+    if (logger.isDebugEnabled()) logger.debug("Built variable list " + variableList);
   
-    // 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);
-    }
-  
+    if (logger.isDebugEnabled()) logger.debug("Building model expression from " + rawModelExpression);
     // parse the text into a model expression
-    ModelExpression modelExpression =
-        ModelExpressionBuilder.build(this.getAliasMap(), rawModelExpression);
+    ModelExpression modelExpression = ModelExpressionBuilder.build(this.getAliasMap(), rawModelExpression);
+    if (logger.isDebugEnabled()) logger.debug("Built model expression " + modelExpression);
   
-    // 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);
-    }
-  
+    PConstraintExpression rawConstraintExpression = whereClause.getConstraintExpression();
+    if (logger.isDebugEnabled()) logger.debug("Building constraint expression from " + rawConstraintExpression);
     // parse the text into a constraint expression
     ConstraintExpression constraintExpression = build(rawConstraintExpression);
+    if (logger.isDebugEnabled()) logger.debug("Built constraint expression " + constraintExpression);
   
-    // 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());
-    }
-  
+    List<Order> orderList = buildOrderList(orderClause);
+
     // build the having clause
-    ConstraintHaving havingExpression = null;
+    ConstraintHaving havingExpression = buildHaving(havingClause);
   
-    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
+    // build the limit and offset
     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);
-      }
+    try {
+      if (limitClause != null) limit = new Integer(limitClause.getNumber().getText());
+      if (offsetClause != null) offset = Integer.parseInt(offsetClause.getNumber().getText());
+    } catch (NumberFormatException e) {
+      String failedType = (limit == null) ? "limit" : "offset";
+      throw new Error("Parser permitted non-integer for " + failedType, e);
     }
   
     // build a query using the information we've obtained from the parser
-    // (all answers are acceptable)
-    lastQuery = new Query(variableList, modelExpression, constraintExpression,
+    return 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)
+   * Despite onyl being accessed from within this package (both locally and from
+   * {@link VariableBuilder}) this method must be public, as it has to appear in
+   * the {@link Interpreter} interface.
    */
   public LiteralImpl toLiteralImpl(PLiteral p) {
   
-    ALiteral aLiteral = (ALiteral) p;
+    ALiteral aLiteral = (ALiteral)p;
   
     // Determine the datatype URI, if present
-    URI datatypeURI = null;
-    if (aLiteral.getDatatype() != null) {
-      datatypeURI = toURI( ( (ADatatype) aLiteral.getDatatype()).getResource());
-    }
+    ADatatype type = (ADatatype)aLiteral.getDatatype();
+    URI datatypeURI = (type != null) ? toURI(type.getResource()) : null;
   
-    // Determine the language code
-    String language = (datatypeURI == null) ? "" : null;
-  
-    if (datatypeURI == null) {
+    if (datatypeURI != null) {
+      return new LiteralImpl(getLiteralText(aLiteral), datatypeURI);
+    } else {
+      // Determine the language code
+      String language = toLanguageId((ALanguage)aLiteral.getLanguage());
       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) {
@@ -1184,17 +819,23 @@
     return URIUtil.convertToURI(token.getText(), aliasMap);
   }
 
-  //
-  // Static methods brought in from the late ConstraintExpressionBuilder
-  //
+
+  /**
+   * @see org.mulgara.itql.QueryInterpreter#nextAnonVariable()
+   * Called by {@link ConstraintExpressionBuilder}
+   */
+  public Variable nextAnonVariable() {
+    return new Variable("av__" + this.anonSuffix++);
+  }
+
   
   /**
    * Builds a {@link org.mulgara.query.ConstraintExpression} object from a
    * {@link org.mulgara.itql.node.PConstraintExpression}, using an <code>aliasMap</code>
-   * to resolve aliases.
+   * to resolve aliases.  Uses double-dispatch into the AST for the expression.
    *
    * @param expression a constraint expression from the parser
-   * @return RETURNED VALUE TO DO
+   * @return A new constraint expression, based on the AST passed as "expression".
    * @throws QueryException if <code>rawConstraintExpression</code> does not
    *      represent a valid query
    * @throws URISyntaxException if the <code>rawConstraintExpression</code>
@@ -1204,42 +845,21 @@
   public ConstraintExpression build(PConstraintExpression expression) throws
       QueryException, URISyntaxException {
   
-    // validate aliasMap parameter
-    if (aliasMap == null) {
-      throw new IllegalArgumentException("Null \"aliasMap\" parameter");
-    }
+    // validate parameters
+    if (aliasMap == null) throw new IllegalArgumentException("Null \"aliasMap\" parameter");
+    if (expression == null) throw new IllegalArgumentException("Null \"expression\" parameter");
   
-    // validate expression parameter
-    if (expression == null) {
-      throw new IllegalArgumentException("Null \"expression\" parameter");
-    }
+    if (logger.isDebugEnabled()) logger.debug("Building constraint expression from " + expression);
   
-    // 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();
+    expression.apply((Switch)builder);
+    ConstraintExpression constraintExpression = builder.getConstraintExpression();
+    if (logger.isDebugEnabled()) logger.debug("Successfully built constraint expression from " + expression);
   
-    // 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 the new constraint 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>.
@@ -1247,191 +867,36 @@
    * @param literal the literal to retrieve the text from
    * @return The LiteralText value
    */
+  @SuppressWarnings("unchecked")
   public static String getLiteralText(ALiteral literal) {
   
     // validate the literal parameter
-    if (literal == null) {
+    if (literal == null) throw new IllegalArgumentException("Null \"literal\" " + "parameter");
   
-      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();
+    List<PStrand> strands = (List<PStrand>)literal.getStrand();
   
     // add each strand together to make the literal text
-    for (Iterator i = strands.iterator(); i.hasNext(); ) {
+    for (Iterator<PStrand> i = strands.iterator(); i.hasNext(); ) {
   
-      // get the strand
-      PStrand strand = (PStrand) i.next();
+      PStrand strand = i.next();
   
       // add the strand to the literal text
       if (strand instanceof AUnescapedStrand) {
-  
-        literalText.append( ( (AUnescapedStrand) strand).getText().getText());
+        literalText.append(((AUnescapedStrand)strand).getText().getText());
+      } else if (strand instanceof AEscapedStrand) {
+        literalText.append(((AEscapedStrand)strand).getEscapedtext().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;
+    return literalText.toString();
   }
 
-  // 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
@@ -1440,6 +905,7 @@
     this.aliasMap = aliasMap;
   }
 
+
   /**
    * Returns the alias map associated with this session.
    *
@@ -1449,6 +915,7 @@
     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
@@ -1462,18 +929,15 @@
    * @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
+  @SuppressWarnings("unchecked")
+  List<Object> buildVariableList(LinkedList<Object> rawVariableList) throws
       QueryException, URISyntaxException {
   
     // Empty variable list.
-    if (rawVariableList == null) {
-      return (List<Object>)Collections.EMPTY_LIST;
-    }
+    if (rawVariableList == null) return (List<Object>)Collections.EMPTY_LIST;
   
     // validate rawVariableList parameter
-    if (rawVariableList.size() == 0) {
-      throw new IllegalArgumentException("Empty \"rawVariableList\" parameter");
-    }
+    if (rawVariableList.size() == 0) throw new IllegalArgumentException("Empty \"rawVariableList\" parameter");
   
     // Construct the required builder
     VariableBuilder variableBuilder = new VariableBuilder(this,
@@ -1481,12 +945,10 @@
   
     // end if
     // log that we're building the variable list
-    if (logger.isDebugEnabled()) {
-      logger.debug("Building variable list from " + rawVariableList);
-    }
+    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(); ) {
+    for (Iterator<Object> i = rawVariableList.iterator(); i.hasNext(); ) {
       PElement element = (PElement) i.next();
       element.apply( (Switch) variableBuilder);
     }
@@ -1514,42 +976,38 @@
    * 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
+   * @param rawOrderList The SableCC list of elements to order by.
    * @return a list of {@link org.mulgara.query.Variable}s, suitable for use
-   *      in creating a {@link org.mulgara.query.Query}
+   *      in creating a {@link org.mulgara.query.Query}, or an empty list if
+   *      there are no elements to be ordered by.
    * @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 {
+  @SuppressWarnings("unchecked")
+  List<Order> buildOrderList(AOrderClause orderClause) throws QueryException {
+
+    // short circuit for an empty clause 
+    if (orderClause == null) return (List<Order>)Collections.EMPTY_LIST;
+    
+    // get the list of elements in the clause
+    LinkedList<AOrderElement> rawOrderList = (LinkedList<AOrderElement>)orderClause.getOrderElement();
+    
+    assert rawOrderList != null && !rawOrderList.isEmpty();
   
-    // validate rawOrderElementList parameter
-    if ( (rawOrderList == null) || (rawOrderList.size() == 0)) {
+    if (logger.isDebugEnabled()) logger.debug("Building order list from " + rawOrderList);
   
-      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());
+    List<Order> orderList = new ArrayList<Order>(rawOrderList.size());
   
     // copy each variable from the query into the list
-    for (Iterator i = rawOrderList.iterator(); i.hasNext(); ) {
+    for (Iterator<AOrderElement> i = rawOrderList.iterator(); i.hasNext(); ) {
   
-      AOrderElement order = (AOrderElement) i.next();
+      AOrderElement order = i.next();
   
       // get the name of this variable
-      String variableName =
-          ( (AVariable) order.getVariable()).getIdentifier().getText();
+      String variableName = ((AVariable)order.getVariable()).getIdentifier().getText();
   
-      // log that we've found a variable
-      if (logger.isDebugEnabled()) {
-        logger.debug("Found variable $" + variableName);
-      }
+      if (logger.isDebugEnabled()) logger.debug("Found variable $" + variableName);
   
       // Figure out which way to order, ascending or descending
       boolean ascending;
@@ -1557,14 +1015,11 @@
   
       if (direction == null) {
         ascending = true;
-      }
-      else if (direction instanceof AAscendingDirection) {
+      } else if (direction instanceof AAscendingDirection) {
         ascending = true;
-      }
-      else if (direction instanceof ADescendingDirection) {
+      } else if (direction instanceof ADescendingDirection) {
         ascending = false;
-      }
-      else {
+      } else {
         throw new Error("Unknown direction field in order");
       }
   
@@ -1572,24 +1027,68 @@
       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) {
+    if (orderList.size() == 0) throw new QueryException("No variables parseable from query");
   
-      throw new QueryException("No variables parseable from query");
-    }
-  
     // log that we've successfully built the order list
-    if (logger.isDebugEnabled()) {
+    if (logger.isDebugEnabled()) logger.debug("Built order list " + orderList);
   
-      logger.debug("Built order list " + orderList);
-    }
-  
     // return the list
     return orderList;
   }
 
+
   /**
+   * 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 A new ConstraintExpression representing the HAVING condition
+   * @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(AHavingClause havingClause) throws QueryException, URISyntaxException {
+  
+    // short circuit if there is no having clause
+    if (havingClause == null) return null;
+    
+    // get the constraint expression from the parser
+    PConstraintExpression rawHavingExpression = havingClause.getConstraintExpression();
+    if (logger.isDebugEnabled()) logger.debug("Building constraint expression from " + rawHavingExpression);
+  
+    ConstraintExpression hExpr = build(rawHavingExpression);
+  
+    // do some gramatical checking on the clause
+    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;
+  }
+
+  /**
+   * Convert a literal's language node into a language ID
+   * @param language The node containing the language node.
+   * @return The 2 or 5 character identifier, or <code>null</code> if no code available.
+   * @throws QueryException if the ID of the language is malformed.
+   */
+  private static String toLanguageId(ALanguage language) {
+    if (language == null) return null;
+    String langId = language.getLangid().getText();
+    int len = langId.length();
+    if (len != 2 && len != 5) {
+      logger.error("Unknown form for language tag: " + langId);
+      langId = null;
+    }
+    return langId;
+  }
+
+
+  /**
    * Resets the parser state in preparation for a new command.
    */
   private void resetInterpreter() {
@@ -1612,7 +1111,9 @@
     } else throw new RuntimeException("Unhandled Grammar Exception: Unknown type of triple factor: " + tripleFactor.getClass().getName());
 
     try {
+      // Create the correct type of modifier for the data 
       if (setOfTriples instanceof AResourceSetOfTriples) {
+        // this is an insert of one model into another.
         throw new UnsupportedOperationException("No support for direct model to model insertion.");
       } else if (setOfTriples instanceof ASelectSetOfTriples) {
         // This is an INSERT/SELECT
@@ -1621,6 +1122,7 @@
         if (logger.isDebugEnabled()) logger.debug("Insert query " + query);
         return Reflect.newInstance(clazz, graphURI, query);
       } else if (setOfTriples instanceof ATripleSetOfTriples) {
+        // This is an inline set of triples
         Set<Triple> statements = getStatements((ATripleSetOfTriples)setOfTriples, new HashMap<String,VariableNodeImpl>());
         return Reflect.newInstance(clazz, graphURI, statements);
       }
@@ -1636,364 +1138,6 @@
 
 
   /**
-   * 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}.
    *
@@ -2010,105 +1154,47 @@
    *   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 {
+  private org.jrdf.graph.Node toNode(PTripleElement element, Map<String,VariableNodeImpl> variableMap)
+      throws QueryException, URISyntaxException {
 
     // validate the element parameter
-    if (element == null) {
+    if (element == null) throw new IllegalArgumentException("Null \"element\" parameter");
 
-      throw new IllegalArgumentException("Null \"element\" parameter");
-    }
+    if (logger.isDebugEnabled()) logger.debug("Resolving " + element + "to a RDF node");
 
-    // 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) {
-
+      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) {
+      node = new URIReferenceImpl(toURI(((AResourceTripleElement)element).getResource()));
+      
+    } else if (element instanceof AVariableTripleElement) {
 
       // get the variable
-      String variableName =
-          ( (AVariable) ( (AVariableTripleElement) element).getVariable()).
-          getIdentifier().getText();
+      String variableName = ((AVariable)((AVariableTripleElement)element).getVariable()).getIdentifier().getText();
 
-      // log what we're doing
-      if (logger.isDebugEnabled()) {
+      if (logger.isDebugEnabled()) logger.debug("Resolved " + element + " to variable " + variableName);
 
-        logger.debug("Resolved " + element + " to variable " + variableName);
-      }
-
+      // use a map to keep the same variable objects if they can be reused
       if (variableMap.containsKey(variableName)) {
-
-        node = (VariableNodeImpl) variableMap.get(variableName);
+        node = (VariableNodeImpl)variableMap.get(variableName);
+      } else {
+        node = new VariableNodeImpl(variableName);
+        variableMap.put(variableName, (VariableNodeImpl)node);
       }
-      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
@@ -2122,71 +1208,42 @@
    */
   private void addAliasPair(String aliasPrefix, URI aliasTarget) {
 
-    // validate the aliasPrefix parameter
+    // validate the parameters
     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
+   * Log the TQL command to a specified file
    *
-   * @param command PARAMETER TO DO
+   * @param command The TQL command to be validated
    */
   private void logItql(String command) {
 
-    // Has this session been constructed for logging.
-    // the constructor initialise this if
+    // Short circuit if not logging.  The constructor initialises this if
     // system property itql.command.log is set
-    if (itqlLogFile == null) {
+    if (itqlLogFile == null) return;
 
-      return;
-    }
-
     try {
-      // has the log file been opened?
-      if (itqlLog == null) {
-        itqlLog = new PrintWriter(new FileWriter(itqlLogFile, true), true);
-      }
-
+      // open log if needed
+      if (itqlLog == null) itqlLog = new PrintWriter(new FileWriter(itqlLogFile, true), true);
       // append the command to the file
       itqlLog.println(command);
-    }
-    catch (Exception ex) {
+    } 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>
+   * Discard any unparsed tokens.
    */
-  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;
+  private void flush() {
+    lexer.leftoverTokenList.clear();
   }
 
 
@@ -2202,11 +1259,8 @@
       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;
-        }
+      for (ConstraintExpression expr: ((ConstraintOperation)e).getElements()) {
+        if (checkHavingPredicates(expr)) return false;
       }
       // all sub expressions returned true
       return true;
@@ -2216,63 +1270,13 @@
     }
   }
 
-
-  /**
-   * 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);
-    }
+  /** Local constants list of supported protocols. */
+  private static final Set<String> protocols = new HashSet<String>();
+  static {
+    protocols.add("rmi");
+    protocols.add("soap");
   }
 
-
   /**
    * Try to recognise a uri alias, and return the canonical form instead.
    *
@@ -2281,16 +1285,15 @@
    */
   private URI getCanonicalUriAlias(URI uri) {
     // only do this for remote protocols
-    if (!"rmi".equals(uri.getScheme()) && !"soap".equals(uri.getScheme())) {
-      return uri;
-    }
+    if (!protocols.contains(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();
+    if (host == null) return uri;
+
+    Set<String> hostnames = getHostnameAliases();
     // Check with a DNS server to see if this host is recognised
     InetAddress addr = null;
     try {
@@ -2330,9 +1333,10 @@
    *
    * @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;
+  @SuppressWarnings("unchecked")
+  private static Set<String> getHostnameAliases() {
+    Set<String> names = (Set<String>)getServerInfoProperty("HostnameAliases");
+    return (names == null) ? (Set<String>)java.util.Collections.EMPTY_SET : names;
   }
 
 
@@ -2351,7 +1355,7 @@
   /**
    * 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.
+   * ie. being run on a host which has no local database, such an an TQL 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.
@@ -2359,9 +1363,9 @@
   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);
+      Class<?> rsf = Class.forName("org.mulgara.server.ServerInfo");
+      java.lang.reflect.Method getter = rsf.getMethod("get" + property, (Class<?>[])null);
+      o = getter.invoke(null, (Object[])null);
     } catch (Exception e) { /* no op */ }
     return o;
   }
@@ -2369,7 +1373,7 @@
   private class Lexer2 extends Lexer {
   
     int commandCount = 0;
-    final LinkedList leftoverTokenList = new LinkedList();
+    final LinkedList<Token> leftoverTokenList = new LinkedList<Token>();
   
     public Lexer2() {
       super(null);




More information about the Mulgara-svn mailing list