[Mulgara-svn] r1751 - in trunk/src/jar: query/java/org/mulgara/query query/java/org/mulgara/query/filter query/java/org/mulgara/query/filter/arithmetic query/java/org/mulgara/query/filter/value querylang querylang/java/org/mulgara/sparql querylang/java/org/mulgara/sparql/parser/cst querylang/javacc/org/mulgara/sparql/parser resolver/java/org/mulgara/resolver resolver-spi/java/org/mulgara/resolver/spi tuples/java/org/mulgara/store/tuples

pag at mulgara.org pag at mulgara.org
Fri Jul 3 17:34:50 UTC 2009


Author: pag
Date: 2009-07-03 10:34:49 -0700 (Fri, 03 Jul 2009)
New Revision: 1751

Added:
   trunk/src/jar/query/java/org/mulgara/query/ConstraintAssignment.java
   trunk/src/jar/tuples/java/org/mulgara/store/tuples/LetTuples.java
Modified:
   trunk/src/jar/query/java/org/mulgara/query/filter/AbstractFilterValue.java
   trunk/src/jar/query/java/org/mulgara/query/filter/Context.java
   trunk/src/jar/query/java/org/mulgara/query/filter/Filter.java
   trunk/src/jar/query/java/org/mulgara/query/filter/RDFTerm.java
   trunk/src/jar/query/java/org/mulgara/query/filter/TestContext.java
   trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/AbstractNumericOperation.java
   trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java
   trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/UnaryMinus.java
   trunk/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java
   trunk/src/jar/query/java/org/mulgara/query/filter/value/IRI.java
   trunk/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java
   trunk/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java
   trunk/src/jar/query/java/org/mulgara/query/filter/value/Var.java
   trunk/src/jar/querylang/build.xml
   trunk/src/jar/querylang/java/org/mulgara/sparql/PatternMapper.java
   trunk/src/jar/querylang/java/org/mulgara/sparql/parser/cst/BasicGraphPattern.java
   trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.java
   trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.jj
   trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserConstants.java
   trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserTokenManager.java
   trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TuplesContext.java
   trunk/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java
   trunk/src/jar/tuples/java/org/mulgara/store/tuples/TuplesOperations.java
Log:
Added variable assignment as a SPARQL extension. This touches the parser and CST, the mapper to the AST, the AST, and the query execution (including Tuples operations)

Added: trunk/src/jar/query/java/org/mulgara/query/ConstraintAssignment.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/ConstraintAssignment.java	                        (rev 0)
+++ trunk/src/jar/query/java/org/mulgara/query/ConstraintAssignment.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2008 Fedora Commons, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.query;
+
+// Java 2 standard packages
+import java.util.*;
+
+// Third party packages
+// import org.apache.log4j.Logger;
+
+// Local packages
+import org.mulgara.query.filter.RDFTerm;
+
+/**
+ * A constraint for assigning a value to a variable.
+ *
+ * @created July 2, 2009
+ *
+ * @author Paul Gearon
+ * @copyright &copy; 2009 <a href="http://www.fedora-commons.org/">Fedora Commons</a>
+ */
+public class ConstraintAssignment implements ConstraintExpression {
+
+  /** Serialization ID */
+  private static final long serialVersionUID = 6393521993437251578L;
+
+  // /** Logger. */
+  // private final static Logger logger = Logger.getLogger(ConstraintAssignment.class);
+
+  protected ConstraintExpression context;
+
+  protected Variable var;
+
+  protected RDFTerm expr;
+
+  Set<Variable> variables = null;
+
+  /**
+   * Constructor.
+   *
+   * @param context The constraint that provides context to set this variable in.
+   * @param var The variable to be assigned.
+   * @param expr The expression to assign to the variable.
+   */
+  public ConstraintAssignment(ConstraintExpression context, Variable var, RDFTerm expr) {
+
+    // Validate parameters
+    if (context == null) {
+      throw new IllegalArgumentException("null constraint context");
+    }
+    if (var == null) {
+      throw new IllegalArgumentException("null variable");
+    }
+
+    if (expr == null) {
+      throw new IllegalArgumentException("null expression for the variable");
+    }
+
+    this.context = context;
+    this.var = var;
+    this.expr = expr;
+  }
+
+
+  /**
+   * Get all constraints which are variables. This
+   * method now uses the fourth element of the triple.
+   *
+   * @return A set containing all variable constraints.
+   */
+  public Set<Variable> getVariables() {
+    if (variables == null) {
+      Set<Variable> v = new HashSet<Variable>(context.getVariables());
+      v.add(var);
+      variables = Collections.unmodifiableSet(v);
+    }
+    return variables;
+  }
+
+
+  /**
+   * Equality is by value.
+   *
+   * @param object The ConstraintIs object to compare to
+   * @return <code>true</code> if object is the same as this.
+   */
+  public boolean equals(Object object) {
+    if (object == null) return false;
+
+    if (object == this) return true;
+
+    // Check that the given object is the correct class
+    if (!object.getClass().equals(this.getClass())) return false;
+
+    // Check each element.
+    ConstraintAssignment tmpConstraint = (ConstraintAssignment)object;
+
+    if (!context.equals(tmpConstraint.context) || var.equals(tmpConstraint.var)) return false;
+
+    // fudge the value comparison
+    boolean exprEq = false;
+    Object v1 = null;
+    Object v2 = null;
+    try {
+      v1 = expr.getValue();
+      try {
+        v2 = tmpConstraint.expr.getValue();
+        exprEq = v1.equals(v2);
+      } catch (QueryException e2) { }
+    } catch (QueryException e) {
+      try {
+        v2 = tmpConstraint.expr.getValue();
+      } catch (QueryException e2) { exprEq = true; }
+    }
+
+    return exprEq;
+  }
+
+
+  /**
+   * Retrieve the variable part of this constraint.
+   * @return the variable being bound.
+   */
+  public ConstraintExpression getContextConstraint() {
+    return context;
+  }
+
+
+  /**
+   * Retrieve the variable part of this constraint.
+   * @return the variable being bound.
+   */
+  public Variable getVariable() {
+    return var;
+  }
+
+
+  /**
+   * Retrieve the value part of this constraint.
+   * @return the expression to bind the variable to.
+   */
+  public RDFTerm getExpression() {
+    return expr;
+  }
+
+
+  /**
+   * Calculate a semi-unique integer for this object
+   *
+   * @return a semi-unique integer for this object
+   */
+  public int hashCode() {
+    return context.hashCode() + var.hashCode() + expr.hashCode();
+  }
+
+
+  /**
+   * Creates a string representation of these constraints. A typical result
+   * might be <code>[$x &lt;mulgara:is&gt; 'bar' $0]</code>.
+   *
+   * @return String representation of this object
+   */
+  public String toString() {
+
+    StringBuffer buffer = new StringBuffer(" LET (");
+    buffer.append(var).append(" := ").append(expr).append(")");
+    return buffer.toString();
+  }
+}

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/AbstractFilterValue.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/AbstractFilterValue.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/AbstractFilterValue.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -11,6 +11,7 @@
  */
 package org.mulgara.query.filter;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.value.Bool;
 import org.mulgara.query.filter.value.ComparableExpression;
@@ -68,6 +69,13 @@
    */
   public Object getValue() throws QueryException { return resolve().getValue(); }
 
+  /**
+   * @see org.mulgara.query.filter.value.ValueLiteral#getValue()
+   * @return an object, for the result.  Never null.
+   * @throws QueryException if this function does not resolve to a literal
+   */
+  public Node getJRDFValue() throws QueryException {return resolve().getJRDFValue(); }
+
   /** @see org.mulgara.query.filter.value.ValueLiteral#test(org.mulgara.query.filter.Context) */
   public boolean test(Context context) throws QueryException {
     setCurrentContext(context);
@@ -95,6 +103,12 @@
   /** @see org.mulgara.query.filter.RDFTerm#isURI() */
   public boolean isURI() throws QueryException { return isIRI(); }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException {
+    for (RDFTerm o: operands) if (!o.isGrounded()) return false;
+    return true;
+  }
+
   /** @see org.mulgara.query.filter.RDFTerm#sameTerm(org.mulgara.query.filter.RDFTerm) */
   public boolean sameTerm(RDFTerm v) throws QueryException { return resolve().sameTerm(v); }
 

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/Context.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/Context.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/Context.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -57,4 +57,12 @@
    */
   public Node globalize(long gNode) throws QueryException;
   
+  /**
+   * Localize a data object into a gNode.
+   * @param o The object to localize.
+   * @return a gNode representing the node.
+   * @throws QueryException If a localize exception is encountered.
+   */
+  public long localize(Node node) throws QueryException;
+  
 }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/Filter.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/Filter.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/Filter.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -1,26 +1,33 @@
-/**
- * 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
+/*
+ * Copyright 2008 Fedora Commons, Inc.
  *
- * 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.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 package org.mulgara.query.filter;
 
+import org.jrdf.graph.Node;
+import org.mulgara.query.rdf.LiteralImpl;
+import org.mulgara.query.rdf.XSD;
 import org.mulgara.query.QueryException;
 
 
 /**
  * Filters the iteration of a Constraint.
+ * TODO: This is more properly called an Expression, since they can be used in non-filter roles.
  *
  * @created Mar 7, 2008
  * @author Paul Gearon
- * @copyright &copy; 2008 <a href="mailto:pgearon at users.sourceforge.net">Paul Gearon</a>
- * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ * @copyright &copy; 2008 <a href="http://www.fedora-commons.org/">Fedora Commons</a>
  */
 public interface Filter extends ContextOwner, RDFTerm {
 
@@ -42,10 +49,12 @@
     public boolean equals(RDFTerm v) throws QueryException { return v == this; }
     public ContextOwner getContextOwner() { return null; }
     public Object getValue() throws QueryException { return true; }
+    public Node getJRDFValue() throws QueryException { return new LiteralImpl("true", XSD.BOOLEAN_URI); }
     public boolean isBlank() throws QueryException { return false; }
     public boolean isIRI() throws QueryException { return false; }
     public boolean isLiteral() throws QueryException { return true; }
     public boolean isURI() throws QueryException { return false; }
+    public boolean isGrounded() throws QueryException { return true; }
     public boolean sameTerm(RDFTerm v) throws QueryException { return equals(v); }
     public void setContextOwner(ContextOwner owner) { }
     public void addContextListener(ContextOwner l) { }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/RDFTerm.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/RDFTerm.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/RDFTerm.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -13,6 +13,7 @@
 
 import java.io.Serializable;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 
 
@@ -34,6 +35,13 @@
   public Object getValue() throws QueryException;
 
   /**
+   * Returns the data represented by this expression as a JRDF node.
+   * @return The represented data.
+   * @throws QueryException Resolving the data for this value leads to an error.
+   */
+  public Node getJRDFValue() throws QueryException;
+
+  /**
    * A value based equality test.
    * @param v The object to compare to
    * @return <code>true</code> iff v has the same value as the current object.
@@ -69,5 +77,13 @@
    * @return <code>true</code> if the terms are the same
    */
   public boolean sameTerm(RDFTerm v) throws QueryException;
-  
+
+  /**
+   * Tests if this term is based on an expression that uses unbound variables
+   * or if it is grounded in a value.
+   * @return <code>true</code> iff the expression is based only on grounded terms,
+   *         or on variables which are themselves based on grounded terms.
+   */
+  public boolean isGrounded() throws QueryException;
+
 }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/TestContext.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/TestContext.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/TestContext.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -105,6 +105,13 @@
     return n != Null.NULL ? n : null;
   }
 
+  /** @see org.mulgara.query.filter.Context#localize(org.jrdf.graph.Node) */
+  public long localize(Node node) throws QueryException {
+    Long l = localizer.get(node);
+    if (l == null) throw new QueryException("Unable to localize id <" + node + ">");
+    return l.longValue();
+  }
+
   /** @see org.mulgara.query.filter.Context#isBound(int) */
   public boolean isBound(int columnNumber) throws QueryException {
     if (columnNumber >= columnNames.size()) throw new QueryException("Unexpected column: " + columnNumber);
@@ -152,4 +159,5 @@
     public boolean isLiteral() { return false; }
     public boolean isURIReference() { return false; }
   }
+
 }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/AbstractNumericOperation.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/AbstractNumericOperation.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/AbstractNumericOperation.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -3,6 +3,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.Context;
 import org.mulgara.query.filter.ContextOwner;
@@ -36,6 +37,11 @@
   /** @see org.mulgara.query.filter.value.ComparableExpression#getValue() */
   public Number getValue() throws QueryException { return getNumber(); }
 
+  /** @see org.mulgara.query.filter.RDFTerm#getJRDFValue() */
+  public Node getJRDFValue() throws QueryException {
+    return new NumericLiteral(getNumber()).getJRDFValue();
+  }
+
   /** @see org.mulgara.query.filter.RDFTerm#equals(RDFTerm) */
   public boolean equals(RDFTerm v) throws QueryException { return compare(getNumber(), v.getValue()) == 0; }
 

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -49,6 +49,11 @@
     rhs.setContextOwner(this);
   }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException {
+    return lhs.isGrounded() && rhs.isGrounded();
+  }
+
   // Not using generics in NumberOps as we can't know the types at this stage, but they are handy
   // for defining the classes correctly
   /**

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/UnaryMinus.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/UnaryMinus.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/arithmetic/UnaryMinus.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -43,6 +43,11 @@
     operand.setContextOwner(this);
   }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException {
+    return operand.isGrounded();
+  }
+
   // Not using generics in NumberOps as we can't know the types at this stage, but they are handy
   // for defining the classes correctly
   /**

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -12,6 +12,7 @@
 package org.mulgara.query.filter.value;
 
 import org.jrdf.graph.BlankNode;
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.Context;
 import org.mulgara.query.filter.ContextOwner;
@@ -48,6 +49,11 @@
   }
 
   /** {@inheritDoc} */
+  public Node getJRDFValue() throws QueryException {
+    return node;
+  }
+
+  /** {@inheritDoc} */
   public boolean equals(RDFTerm v) throws QueryException {
     return v.isBlank() && node.equals(v.getValue());
   }
@@ -69,6 +75,9 @@
   /** {@inheritDoc} */
   public boolean isURI() { return false; }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException { return true; }
+
   /** This value does not need a context */
   public ContextOwner getContextOwner() {  return null; }
 

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/value/IRI.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/value/IRI.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/value/IRI.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -13,10 +13,12 @@
 
 import java.net.URI;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.Context;
 import org.mulgara.query.filter.ContextOwner;
 import org.mulgara.query.filter.RDFTerm;
+import org.mulgara.query.rdf.URIReferenceImpl;
 
 
 /**
@@ -50,6 +52,11 @@
   }
 
   /** {@inheritDoc} */
+  public Node getJRDFValue() {
+    return new URIReferenceImpl(value);
+  }
+
+  /** {@inheritDoc} */
   public boolean equals(Object o) {
     try {
       return (o instanceof RDFTerm) ? equals((RDFTerm)o) : false;
@@ -76,6 +83,9 @@
   public boolean isLiteral() { return false; }
 
   /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException { return true; }
+
+  /** {@inheritDoc} */
   public boolean sameTerm(RDFTerm v) throws QueryException {
     return equals(v);
   }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -11,10 +11,13 @@
  */
 package org.mulgara.query.filter.value;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.Context;
 import org.mulgara.query.filter.ContextOwner;
 import org.mulgara.query.filter.RDFTerm;
+import org.mulgara.query.rdf.LiteralImpl;
+
 import static org.mulgara.query.rdf.XSD.STRING_URI;
 
 
@@ -79,11 +82,23 @@
     return STRING_TYPE;
   }
 
+  /**
+   * @see org.mulgara.query.filter.RDFTerm#getJRDFValue()
+   */
+  public Node getJRDFValue() throws QueryException {
+    return lang == EMPTY ? new LiteralImpl(getLexical()) : new LiteralImpl(getLexical(), lang.getLexical());
+  }
+
   /** @see org.mulgara.query.filter.value.ValueLiteral#isSimple() */
   public boolean isSimple() throws QueryException {
     return true;
   }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException {
+    return true;
+  }
+
   /**
    * @see org.mulgara.query.filter.value.ComparableExpression#test(Context)
    */
@@ -164,4 +179,5 @@
   private int compareLang(ValueLiteral sl) throws QueryException {
     return ((String)lang.getValue()).compareTo((String)sl.getLang().getValue());
   }
+
 }

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -17,9 +17,11 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.jrdf.graph.Node;
 import org.mulgara.query.QueryException;
 import org.mulgara.query.filter.Context;
 import org.mulgara.query.filter.ContextOwner;
+import org.mulgara.query.rdf.LiteralImpl;
 import org.mulgara.query.rdf.XSD;
 import org.mulgara.query.rdf.XSDAbbrev;
 
@@ -97,6 +99,11 @@
     return false;
   }
 
+  /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException {
+    return true;
+  }
+
   /**
    * Gets the language ID of this literal
    * @return The language ID for this literal
@@ -126,6 +133,13 @@
   }
 
   /**
+   * A JRDF Node that represents this literal
+   */
+  public Node getJRDFValue() throws QueryException {
+    return new LiteralImpl(lexical, type);
+  }
+
+  /**
    * No context needed as this is a literal value.
    * @see org.mulgara.query.filter.RDFTerm#setContextOwner(org.mulgara.query.filter.ContextOwner)
    */

Modified: trunk/src/jar/query/java/org/mulgara/query/filter/value/Var.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/filter/value/Var.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/query/java/org/mulgara/query/filter/value/Var.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -79,6 +79,11 @@
   }
 
   /** {@inheritDoc} */
+  public Node getJRDFValue() throws QueryException {
+    return resolve().getJRDFValue();
+  }
+
+  /** {@inheritDoc} */
   public Number getNumber() throws QueryException {
     Object result = getValue();
     if (result instanceof Number) return (Number)result;
@@ -110,6 +115,9 @@
   }
 
   /** {@inheritDoc} */
+  public boolean isGrounded() throws QueryException { return false; }
+
+  /** {@inheritDoc} */
   public boolean equals(RDFTerm v) throws QueryException {
     return resolve().equals(v);
   }

Modified: trunk/src/jar/querylang/build.xml
===================================================================
--- trunk/src/jar/querylang/build.xml	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/build.xml	2009-07-03 17:34:49 UTC (rev 1751)
@@ -147,6 +147,7 @@
       <zipfileset src="${lib.dir}/${jta.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${axis.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jline.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${jena.jar}" excludes="META-INF/**"/>
     </jar>
   </target>
 

Modified: trunk/src/jar/querylang/java/org/mulgara/sparql/PatternMapper.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/sparql/PatternMapper.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/java/org/mulgara/sparql/PatternMapper.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -40,7 +40,9 @@
 import org.mulgara.sparql.parser.cst.RDFLiteral;
 import org.mulgara.sparql.parser.cst.Triple;
 import org.mulgara.sparql.parser.cst.TripleList;
+import org.mulgara.sparql.parser.cst.VarAssign;
 import org.mulgara.parser.MulgaraParserException;
+import org.mulgara.query.ConstraintAssignment;
 import org.mulgara.query.ConstraintConjunction;
 import org.mulgara.query.ConstraintDisjunction;
 import org.mulgara.query.ConstraintElement;
@@ -231,6 +233,7 @@
     addToMap(new GraphPatternConjunctionToConstraint());
     addToMap(new GraphPatternDisjunctionToConstraint());
     addToMap(new GraphPatternOptionalToConstraint());
+    addToMap(new VarAssignToConstraint());
     addToMap(new TripleToConstraint());
     addToMap(new TripleListToConstraint());
   }
@@ -281,6 +284,17 @@
     }
   }
 
+  /** Map the assignment patterns to ConstraintAssignment. */
+  private static class VarAssignToConstraint extends PatternToConstraintMapper<VarAssign> {
+    public Class<VarAssign> getMapType() { return VarAssign.class; }
+    ConstraintExpression typedMap(VarAssign pattern, PatternMapper mapper) throws MulgaraParserException {
+      ConstraintExpression main = mapper.mapPattern(pattern.getMain());
+      org.mulgara.query.Variable v = new org.mulgara.query.Variable(pattern.getVar().getName());
+      FilterMapper filterMapper = new FilterMapper(pattern.getExpression());
+      return new ConstraintAssignment(main, v, filterMapper.getFilter());
+    }
+  }
+
   /** Map the triple patterns to ConstraintImpl. */
   private static class TripleToConstraint extends PatternToConstraintMapper<Triple> {
     public Class<Triple> getMapType() { return Triple.class; }

Modified: trunk/src/jar/querylang/java/org/mulgara/sparql/parser/cst/BasicGraphPattern.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/sparql/parser/cst/BasicGraphPattern.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/java/org/mulgara/sparql/parser/cst/BasicGraphPattern.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -75,7 +75,10 @@
    * @see org.mulgara.sparql.parser.cst.GroupGraphPattern#setFilter(org.mulgara.sparql.parser.cst.Expression)
    */
   public void setFilter(Expression f) {
-    filter = f;
+    if (filter == null) filter = f;
+    else {
+      filter = new AndExpression(filter, f);
+    }
   }
 
   /**

Modified: trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.java
===================================================================
--- trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -163,8 +163,8 @@
         }
       }
       break;
-    case 40:
-      jj_consume_token(40);
+    case 41:
+      jj_consume_token(41);
             queryStructure.setSelectAll();
       break;
     default:
@@ -238,8 +238,8 @@
         }
       }
       break;
-    case 40:
-      jj_consume_token(40);
+    case 41:
+      jj_consume_token(41);
             queryStructure.setSelectAll();
       break;
     default:
@@ -261,7 +261,7 @@
     }
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case WHERE:
-    case 43:
+    case 44:
       WhereClause();
       break;
     default:
@@ -419,9 +419,9 @@
       case REGEX:
       case BOUND:
       case SAME_TERM:
-      case 41:
       case 42:
-      case 46:
+      case 43:
+      case 47:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -440,14 +440,14 @@
   final public void OrderCondition() throws ParseException {
                           boolean asc = true; Expression e;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 41:
     case 42:
+    case 43:
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 41:
-        jj_consume_token(41);
-        break;
       case 42:
         jj_consume_token(42);
+        break;
+      case 43:
+        jj_consume_token(43);
                        asc = false;
         break;
       default:
@@ -468,7 +468,7 @@
     case REGEX:
     case BOUND:
     case SAME_TERM:
-    case 46:
+    case 47:
     case IRI_REF:
     case PNAME_NS:
     case PNAME_LN:
@@ -486,7 +486,7 @@
       case REGEX:
       case BOUND:
       case SAME_TERM:
-      case 46:
+      case 47:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -532,12 +532,12 @@
   GraphPatternConjunction c = null;
   Expression f;
           g = GroupGraphPattern.EMPTY;
-    jj_consume_token(43);
+    jj_consume_token(44);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case TRUE:
     case FALSE:
-    case 46:
-    case 51:
+    case 47:
+    case 53:
     case IRI_REF:
     case PNAME_NS:
     case PNAME_LN:
@@ -571,7 +571,8 @@
       case GRAPH:
       case OPTIONAL:
       case FILTER:
-      case 43:
+      case LET:
+      case 44:
         ;
         break;
       default:
@@ -581,7 +582,8 @@
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case GRAPH:
       case OPTIONAL:
-      case 43:
+      case LET:
+      case 44:
         g = GraphPatternNotTriples(g);
         break;
       case FILTER:
@@ -595,8 +597,8 @@
         throw new ParseException();
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 44:
-        jj_consume_token(44);
+      case 45:
+        jj_consume_token(45);
         break;
       default:
         jj_la1[28] = jj_gen;
@@ -605,8 +607,8 @@
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case TRUE:
       case FALSE:
-      case 46:
-      case 51:
+      case 47:
+      case 53:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -642,7 +644,7 @@
         ;
       }
     }
-    jj_consume_token(45);
+    jj_consume_token(46);
       {if (true) return g;}
     throw new Error("Missing return statement in function");
   }
@@ -652,13 +654,13 @@
                                            TripleList l; GraphPatternConjunction g = null;
     l = TriplesSameSubject();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 44:
-      jj_consume_token(44);
+    case 45:
+      jj_consume_token(45);
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case TRUE:
       case FALSE:
-      case 46:
-      case 51:
+      case 47:
+      case 53:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -704,18 +706,21 @@
     case OPTIONAL:
       g = OptionalGraphPattern(in);
       break;
-    case 43:
+    case 44:
       g = GroupOrUnionGraphPattern(in);
       break;
     case GRAPH:
       g = GraphGraphPattern(in);
       break;
+    case LET:
+      g = Assignment(in);
+      break;
     default:
       jj_la1[32] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
-      {if (true) return g;}
+        {if (true) return g;}
     throw new Error("Missing return statement in function");
   }
 
@@ -739,6 +744,20 @@
     throw new Error("Missing return statement in function");
   }
 
+/* SPARQL Extension */
+/* Assignment  ::=  'LET (' Var ':=' Expression ')' */
+  final public GroupGraphPattern Assignment(GroupGraphPattern in) throws ParseException {
+                                                       Variable v ; Expression expr ;
+    jj_consume_token(LET);
+    jj_consume_token(47);
+    v = Var();
+    jj_consume_token(48);
+    expr = Expression();
+    jj_consume_token(49);
+      {if (true) return new VarAssign(in, v, expr) ;}
+    throw new Error("Missing return statement in function");
+  }
+
 /* [25]    GroupOrUnionGraphPattern    ::=    GroupGraphPattern ( 'UNION' GroupGraphPattern )* */
   final public GroupGraphPattern GroupOrUnionGraphPattern(GroupGraphPattern in) throws ParseException {
                                                                      GroupGraphPattern g1, g2; GraphPatternDisjunction d = null;
@@ -777,7 +796,7 @@
   final public Expression Constraint() throws ParseException {
                             Expression e;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 46:
+    case 47:
       e = BrackettedExpression();
       break;
     case STR:
@@ -823,25 +842,25 @@
     case NIL:
       jj_consume_token(NIL);
       break;
-    case 46:
-      jj_consume_token(46);
+    case 47:
+      jj_consume_token(47);
       e = Expression();
                              list.add(e);
       label_11:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case 47:
+        case 50:
           ;
           break;
         default:
           jj_la1[35] = jj_gen;
           break label_11;
         }
-        jj_consume_token(47);
+        jj_consume_token(50);
         e = Expression();
                                                                    list.add(e);
       }
-      jj_consume_token(48);
+      jj_consume_token(49);
       break;
     default:
       jj_la1[36] = jj_gen;
@@ -855,12 +874,12 @@
 /* [30]    ConstructTemplate    ::=    '{' ConstructTriples? '}' */
   final public void ConstructTemplate() throws ParseException {
                              TripleList triples = null;
-    jj_consume_token(43);
+    jj_consume_token(44);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case TRUE:
     case FALSE:
-    case 46:
-    case 51:
+    case 47:
+    case 53:
     case IRI_REF:
     case PNAME_NS:
     case PNAME_LN:
@@ -888,7 +907,7 @@
       jj_la1[37] = jj_gen;
       ;
     }
-    jj_consume_token(45);
+    jj_consume_token(46);
       queryStructure.setConstructTemplate(triples);
   }
 
@@ -897,13 +916,13 @@
                                   TripleList triples, t;
     triples = TriplesSameSubject();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 44:
-      jj_consume_token(44);
+    case 45:
+      jj_consume_token(45);
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case TRUE:
       case FALSE:
-      case 46:
-      case 51:
+      case 47:
+      case 53:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -972,8 +991,8 @@
       pl = PropertyListNotEmpty();
                                               {if (true) return new TripleList(s, pl);}
       break;
-    case 46:
-    case 51:
+    case 47:
+    case 53:
       an = TriplesNode();
       pl = PropertyList();
                                          {if (true) return new TripleList(an, pl);}
@@ -995,16 +1014,16 @@
     label_12:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 49:
+      case 51:
         ;
         break;
       default:
         jj_la1[41] = jj_gen;
         break label_12;
       }
-      jj_consume_token(49);
+      jj_consume_token(51);
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 50:
+      case 52:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -1027,7 +1046,7 @@
   final public PropertyList PropertyList() throws ParseException {
                                 PropertyList pl = null;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 50:
+    case 52:
     case IRI_REF:
     case PNAME_NS:
     case PNAME_LN:
@@ -1052,14 +1071,14 @@
     label_13:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 47:
+      case 50:
         ;
         break;
       default:
         jj_la1[44] = jj_gen;
         break label_13;
       }
-      jj_consume_token(47);
+      jj_consume_token(50);
       Object();
                      l.add(n);
     }
@@ -1087,8 +1106,8 @@
       e = VarOrIRIref();
                       {if (true) return e;}
       break;
-    case 50:
-      jj_consume_token(50);
+    case 52:
+      jj_consume_token(52);
             {if (true) return IRIReference.RDF_TYPE;}
       break;
     default:
@@ -1104,10 +1123,10 @@
   final public AnnotatedNode TriplesNode() throws ParseException {
                                 AnnotatedNode n;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 46:
+    case 47:
       n = Collection();
       break;
-    case 51:
+    case 53:
       n = BlankNodePropertyList();
       break;
     default:
@@ -1122,9 +1141,9 @@
 /* [39]    BlankNodePropertyList    ::=    '[' PropertyListNotEmpty ']' */
   final public AnnotatedNode BlankNodePropertyList() throws ParseException {
                                           PropertyList pl;
-    jj_consume_token(51);
+    jj_consume_token(53);
     pl = PropertyListNotEmpty();
-    jj_consume_token(52);
+    jj_consume_token(54);
       {if (true) return new AnnotatedNode(queryStructure.newBlankNode(), pl);}
     throw new Error("Missing return statement in function");
   }
@@ -1133,7 +1152,7 @@
 /* Returns a *NODE* that is a collection.  The rest of the collection will be conjoined after. */
   final public AnnotatedNode Collection() throws ParseException {
                                Node n; GraphList l = queryStructure.newList();
-    jj_consume_token(46);
+    jj_consume_token(47);
     label_14:
     while (true) {
       n = GraphNode();
@@ -1141,8 +1160,8 @@
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case TRUE:
       case FALSE:
-      case 46:
-      case 51:
+      case 47:
+      case 53:
       case IRI_REF:
       case PNAME_NS:
       case PNAME_LN:
@@ -1171,7 +1190,7 @@
         break label_14;
       }
     }
-    jj_consume_token(48);
+    jj_consume_token(49);
       {if (true) return new AnnotatedNode(l);}
     throw new Error("Missing return statement in function");
   }
@@ -1205,8 +1224,8 @@
     case ANON:
       n = VarOrTerm();
       break;
-    case 46:
-    case 51:
+    case 47:
+    case 53:
       n = TriplesNode();
       break;
     default:
@@ -1361,14 +1380,14 @@
     label_15:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 53:
+      case 55:
         ;
         break;
       default:
         jj_la1[53] = jj_gen;
         break label_15;
       }
-      jj_consume_token(53);
+      jj_consume_token(55);
       ae = ConditionalAndExpression();
                                                                         e = new OrExpression(e, ae);
     }
@@ -1383,14 +1402,14 @@
     label_16:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 54:
+      case 56:
         ;
         break;
       default:
         jj_la1[54] = jj_gen;
         break label_16;
       }
-      jj_consume_token(54);
+      jj_consume_token(56);
       e2 = ValueLogical();
                                                 e = new AndExpression(e, e2);
     }
@@ -1411,40 +1430,40 @@
                                       Expression e, e2;
     e = NumericExpression();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 55:
-    case 56:
     case 57:
     case 58:
     case 59:
     case 60:
+    case 61:
+    case 62:
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 55:
-        jj_consume_token(55);
+      case 57:
+        jj_consume_token(57);
         e2 = NumericExpression();
                                    e = new Equals(e, e2);
         break;
-      case 56:
-        jj_consume_token(56);
+      case 58:
+        jj_consume_token(58);
         e2 = NumericExpression();
                                       e = new NotEquals(e, e2);
         break;
-      case 57:
-        jj_consume_token(57);
+      case 59:
+        jj_consume_token(59);
         e2 = NumericExpression();
                                      e = new LessThan(e, e2);
         break;
-      case 58:
-        jj_consume_token(58);
+      case 60:
+        jj_consume_token(60);
         e2 = NumericExpression();
                                      e = new GreaterThan(e, e2);
         break;
-      case 59:
-        jj_consume_token(59);
+      case 61:
+        jj_consume_token(61);
         e2 = NumericExpression();
                                       e = new LessThanEqual(e, e2);
         break;
-      case 60:
-        jj_consume_token(60);
+      case 62:
+        jj_consume_token(62);
         e2 = NumericExpression();
                                       e = new GreaterThanEqual(e, e2);
         break;
@@ -1477,8 +1496,8 @@
     label_17:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 61:
-      case 62:
+      case 63:
+      case 64:
       case INTEGER_POSITIVE:
       case DECIMAL_POSITIVE:
       case DOUBLE_POSITIVE:
@@ -1492,13 +1511,13 @@
         break label_17;
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 61:
-        jj_consume_token(61);
+      case 63:
+        jj_consume_token(63);
         e2 = MultiplicativeExpression();
                                           e = new Plus(e, e2);
         break;
-      case 62:
-        jj_consume_token(62);
+      case 64:
+        jj_consume_token(64);
         e2 = MultiplicativeExpression();
                                             e = new Minus(e, e2);
         break;
@@ -1531,8 +1550,8 @@
     label_18:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 40:
-      case 63:
+      case 41:
+      case 65:
         ;
         break;
       default:
@@ -1540,13 +1559,13 @@
         break label_18;
       }
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case 40:
-        jj_consume_token(40);
+      case 41:
+        jj_consume_token(41);
         e2 = UnaryExpression();
                                  e = new Multiply(e, e2);
         break;
-      case 63:
-        jj_consume_token(63);
+      case 65:
+        jj_consume_token(65);
         e2 = UnaryExpression();
                                    e = new Divide(e, e2);
         break;
@@ -1564,18 +1583,18 @@
   final public Expression UnaryExpression() throws ParseException {
                                  Expression e;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 64:
-      jj_consume_token(64);
+    case 66:
+      jj_consume_token(66);
       e = PrimaryExpression();
                                 {if (true) return new Not(e);}
       break;
-    case 61:
-      jj_consume_token(61);
+    case 63:
+      jj_consume_token(63);
       e = PrimaryExpression();
                                   {if (true) return new UnaryPlus(e);}
       break;
-    case 62:
-      jj_consume_token(62);
+    case 64:
+      jj_consume_token(64);
       e = PrimaryExpression();
                                   {if (true) return new UnaryMinus(e);}
       break;
@@ -1592,7 +1611,7 @@
     case TRUE:
     case SAME_TERM:
     case FALSE:
-    case 46:
+    case 47:
     case IRI_REF:
     case PNAME_NS:
     case PNAME_LN:
@@ -1626,7 +1645,7 @@
   final public Expression PrimaryExpression() throws ParseException {
                                    Expression e;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 46:
+    case 47:
       e = BrackettedExpression();
       break;
     case STR:
@@ -1684,9 +1703,9 @@
 /* [56]    BrackettedExpression    ::=    '(' Expression ')' */
   final public Expression BrackettedExpression() throws ParseException {
                                       Expression e;
-    jj_consume_token(46);
+    jj_consume_token(47);
     e = Expression();
-    jj_consume_token(48);
+    jj_consume_token(49);
                              {if (true) return e;}
     throw new Error("Missing return statement in function");
   }
@@ -1707,76 +1726,76 @@
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case STR:
       jj_consume_token(STR);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                    {if (true) return new BicStr(e);}
       break;
     case LANG:
       jj_consume_token(LANG);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                       {if (true) return new BicLang(e);}
       break;
     case LANGMATCHES:
       jj_consume_token(LANGMATCHES);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(47);
+      jj_consume_token(50);
       e2 = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                                                  {if (true) return new BicLangMatches(e, e2);}
       break;
     case DATATYPE:
       jj_consume_token(DATATYPE);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                           {if (true) return new BicDatatype(e);}
       break;
     case BOUND:
       jj_consume_token(BOUND);
-      jj_consume_token(46);
+      jj_consume_token(47);
       v = Var();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                 {if (true) return new BicBound(v);}
       break;
     case SAME_TERM:
       jj_consume_token(SAME_TERM);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(47);
+      jj_consume_token(50);
       e2 = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                                                {if (true) return new BicSameTerm(e, e2);}
       break;
     case IS_IRI:
       jj_consume_token(IS_IRI);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                         {if (true) return new BicIsIri(e);}
       break;
     case IS_URI:
       jj_consume_token(IS_URI);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                         {if (true) return new BicIsUri(e);}
       break;
     case IS_BLANK:
       jj_consume_token(IS_BLANK);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                           {if (true) return new BicIsBlank(e);}
       break;
     case IS_LITERAL:
       jj_consume_token(IS_LITERAL);
-      jj_consume_token(46);
+      jj_consume_token(47);
       e = Expression();
-      jj_consume_token(48);
+      jj_consume_token(49);
                                             {if (true) return new BicIsLiteral(e);}
       break;
     case REGEX:
@@ -1795,20 +1814,20 @@
   final public BuiltInCall RegexExpression() throws ParseException {
                                   Expression e1, e2, e3 = null;
     jj_consume_token(REGEX);
-    jj_consume_token(46);
+    jj_consume_token(47);
     e1 = Expression();
-    jj_consume_token(47);
+    jj_consume_token(50);
     e2 = Expression();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 47:
-      jj_consume_token(47);
+    case 50:
+      jj_consume_token(50);
       e3 = Expression();
       break;
     default:
       jj_la1[64] = jj_gen;
       ;
     }
-    jj_consume_token(48);
+    jj_consume_token(49);
       {if (true) return new BicRegEx(e1, e2, e3);}
     throw new Error("Missing return statement in function");
   }
@@ -1818,7 +1837,7 @@
                                   IRIReference ref; ArgList list;
     ref = IRIref();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 46:
+    case 47:
     case NIL:
       list = ArgList();
                                    {if (true) return new FunctionCall(ref, list);}
@@ -1837,15 +1856,15 @@
     s = String();
                    l = new RDFLiteral(s);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case 65:
+    case 67:
     case LANGTAG:
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
       case LANGTAG:
         t = jj_consume_token(LANGTAG);
                     l.setLanguage(t.image);
         break;
-      case 65:
-        jj_consume_token(65);
+      case 67:
+        jj_consume_token(67);
         ref = IRIref();
                             l.setDatatype(ref);
         break;
@@ -2090,10 +2109,10 @@
       jj_la1_0 = new int[] {0x40820100,0x200,0x10000,0x80000000,0x80000000,0x0,0x0,0x1000,0x1000,0x0,0x0,0x1000,0x2000000,0x1000,0x80000,0x2000000,0x400,0x1040000,0x1000000,0x40000,0x1040000,0x3860c000,0x0,0x3860c000,0x3860c000,0x0,0x102000,0x102000,0x0,0x0,0x0,0x0,0x102000,0x4000000,0x3860c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3860c000,0x3860c000,0x3860c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
    }
    private static void jj_la1_1() {
-      jj_la1_1 = new int[] {0x0,0x0,0x0,0x8,0x8,0x0,0x100,0x0,0x0,0x0,0x100,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4656,0x600,0x4056,0x4656,0x840a0,0x801,0x801,0x1000,0x840a0,0x840a0,0x1000,0x800,0x0,0x4056,0x8000,0x4000,0x840a0,0x840a0,0x1000,0x840a0,0x20000,0x40000,0x40000,0x8000,0x40000,0x84000,0x840a0,0x840a0,0xa0,0x0,0x0,0xa0,0x200000,0x400000,0x1f800000,0x1f800000,0x60000000,0x60000000,0x80000100,0x80000100,0x600040f6,0x40f6,0x56,0x8000,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0xa0,0x0,0x0,0x0,0x0,};
+      jj_la1_1 = new int[] {0x0,0x0,0x0,0x8,0x8,0x0,0x200,0x0,0x0,0x0,0x200,0x0,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8c56,0xc00,0x8056,0x8c56,0x2080a0,0x1101,0x1101,0x2000,0x2080a0,0x2080a0,0x2000,0x1100,0x0,0x8056,0x40000,0x8000,0x2080a0,0x2080a0,0x2000,0x2080a0,0x80000,0x100000,0x100000,0x40000,0x100000,0x208000,0x2080a0,0x2080a0,0xa0,0x0,0x0,0xa0,0x800000,0x1000000,0x7e000000,0x7e000000,0x80000000,0x80000000,0x200,0x200,0x800080f6,0x80f6,0x56,0x40000,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0xa0,0x0,0x0,0x0,0x0,};
    }
    private static void jj_la1_2() {
-      jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0xc0,0xc0,0x0,0x0,0xdc,0xdc,0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x0,0x0,0x0,0xdc,0x0,0xdc,0xdc,0x2bdff0fc,0x0,0x0,0x0,0x2bdff0fc,0x2bdff0fc,0x0,0x0,0x0,0x1c,0x0,0x8000000,0x2bdff0fc,0x2bdff0fc,0x0,0x2bdff0fc,0x0,0xdc,0xdc,0x0,0xdc,0x0,0x2bdff0fc,0x2bdff0fc,0x2bdff0fc,0xdc,0xc0,0x2bdff03c,0x0,0x0,0x0,0x0,0x1f8000,0x1f8000,0x0,0x0,0x3dff0dd,0x3dff0dc,0x0,0x0,0x8000000,0x102,0x102,0x1ff000,0x7000,0x38000,0x1c0000,0x0,0x3c00000,0x1c,0x18,0x20000020,};
+      jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x300,0x300,0x0,0x0,0x370,0x370,0x0,0x0,0x0,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x370,0x0,0x370,0x370,0xaf7fc3f0,0x0,0x0,0x0,0xaf7fc3f0,0xaf7fc3f0,0x0,0x0,0x0,0x70,0x0,0x20000000,0xaf7fc3f0,0xaf7fc3f0,0x0,0xaf7fc3f0,0x0,0x370,0x370,0x0,0x370,0x0,0xaf7fc3f0,0xaf7fc3f0,0xaf7fc3f0,0x370,0x300,0xaf7fc0f0,0x0,0x0,0x0,0x0,0x7e0001,0x7e0001,0x2,0x2,0xf7fc375,0xf7fc370,0x0,0x0,0x20000000,0x408,0x408,0x7fc000,0x1c000,0xe0000,0x700000,0x0,0xf000000,0x70,0x60,0x80000080,};
    }
    private static void jj_la1_3() {
       jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
@@ -2201,8 +2220,8 @@
 
   public ParseException generateParseException() {
     jj_expentries.removeAllElements();
-    boolean[] la1tokens = new boolean[100];
-    for (int i = 0; i < 100; i++) {
+    boolean[] la1tokens = new boolean[102];
+    for (int i = 0; i < 102; i++) {
       la1tokens[i] = false;
     }
     if (jj_kind >= 0) {
@@ -2227,7 +2246,7 @@
         }
       }
     }
-    for (int i = 0; i < 100; i++) {
+    for (int i = 0; i < 102; i++) {
       if (la1tokens[i]) {
         jj_expentry = new int[1];
         jj_expentry[0] = i;

Modified: trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.jj
===================================================================
--- trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.jj	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParser.jj	2009-07-03 17:34:49 UTC (rev 1751)
@@ -138,6 +138,7 @@
 |   < TRUE : "true" >
 |   < SAME_TERM : "sameTERM" >
 |   < FALSE : "false" >
+|   < LET : "let" >
 }
 
 
@@ -335,8 +336,12 @@
 /* [22]    GraphPatternNotTriples    ::=    OptionalGraphPattern | GroupOrUnionGraphPattern | GraphGraphPattern */
 GroupGraphPattern GraphPatternNotTriples(GroupGraphPattern in) : { GroupGraphPattern g; }
 {
-    ( g=OptionalGraphPattern(in) | g=GroupOrUnionGraphPattern(in) | g=GraphGraphPattern(in) )
-    { return g; }
+    (
+        g=OptionalGraphPattern(in)
+      | g=GroupOrUnionGraphPattern(in)
+      | g=GraphGraphPattern(in)
+      | g=Assignment(in)
+    ) { return g; }
 }
 
 /* [23]    OptionalGraphPattern    ::=    'OPTIONAL' GroupGraphPattern */
@@ -354,6 +359,16 @@
     }
 }
 
+/* SPARQL Extension */
+/* Assignment  ::=  'LET (' Var ':=' Expression ')' */
+GroupGraphPattern Assignment(GroupGraphPattern in) : { Variable v ; Expression expr ; }
+{
+    <LET> "(" v = Var() ":=" expr = Expression() ")"
+    { return new VarAssign(in, v, expr) ; }
+}
+
+
+
 /* [25]    GroupOrUnionGraphPattern    ::=    GroupGraphPattern ( 'UNION' GroupGraphPattern )* */
 GroupGraphPattern GroupOrUnionGraphPattern(GroupGraphPattern in) : { GroupGraphPattern g1, g2; GraphPatternDisjunction d = null; }
 {

Modified: trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserConstants.java
===================================================================
--- trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserConstants.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserConstants.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -37,40 +37,41 @@
   int TRUE = 37;
   int SAME_TERM = 38;
   int FALSE = 39;
-  int IRI_REF = 66;
-  int PNAME_NS = 67;
-  int PNAME_LN = 68;
-  int BLANK_NODE_LABEL = 69;
-  int VAR1 = 70;
-  int VAR2 = 71;
-  int LANGTAG = 72;
-  int Z_9 = 73;
-  int Z_9r = 74;
-  int Z_9o = 75;
-  int INTEGER = 76;
-  int DECIMAL = 77;
-  int DOUBLE = 78;
-  int INTEGER_POSITIVE = 79;
-  int DECIMAL_POSITIVE = 80;
-  int DOUBLE_POSITIVE = 81;
-  int INTEGER_NEGATIVE = 82;
-  int DECIMAL_NEGATIVE = 83;
-  int DOUBLE_NEGATIVE = 84;
-  int EXPONENT = 85;
-  int STRING_LITERAL1 = 86;
-  int STRING_LITERAL2 = 87;
-  int STRING_LITERAL_LONG1 = 88;
-  int STRING_LITERAL_LONG2 = 89;
-  int ECHAR = 90;
-  int NIL = 91;
-  int WS = 92;
-  int ANON = 93;
-  int PN_CHARS_BASE = 94;
-  int PN_CHARS_U = 95;
-  int VARNAME = 96;
-  int PN_CHARS = 97;
-  int PN_PREFIX = 98;
-  int PN_LOCAL = 99;
+  int LET = 40;
+  int IRI_REF = 68;
+  int PNAME_NS = 69;
+  int PNAME_LN = 70;
+  int BLANK_NODE_LABEL = 71;
+  int VAR1 = 72;
+  int VAR2 = 73;
+  int LANGTAG = 74;
+  int Z_9 = 75;
+  int Z_9r = 76;
+  int Z_9o = 77;
+  int INTEGER = 78;
+  int DECIMAL = 79;
+  int DOUBLE = 80;
+  int INTEGER_POSITIVE = 81;
+  int DECIMAL_POSITIVE = 82;
+  int DOUBLE_POSITIVE = 83;
+  int INTEGER_NEGATIVE = 84;
+  int DECIMAL_NEGATIVE = 85;
+  int DOUBLE_NEGATIVE = 86;
+  int EXPONENT = 87;
+  int STRING_LITERAL1 = 88;
+  int STRING_LITERAL2 = 89;
+  int STRING_LITERAL_LONG1 = 90;
+  int STRING_LITERAL_LONG2 = 91;
+  int ECHAR = 92;
+  int NIL = 93;
+  int WS = 94;
+  int ANON = 95;
+  int PN_CHARS_BASE = 96;
+  int PN_CHARS_U = 97;
+  int VARNAME = 98;
+  int PN_CHARS = 99;
+  int PN_PREFIX = 100;
+  int PN_LOCAL = 101;
 
   int DEFAULT = 0;
   int IN_COMMENT = 1;
@@ -116,6 +117,7 @@
     "\"true\"",
     "\"sameTERM\"",
     "\"false\"",
+    "\"let\"",
     "\"*\"",
     "\"ASC\"",
     "\"DESC\"",
@@ -123,8 +125,9 @@
     "\".\"",
     "\"}\"",
     "\"(\"",
+    "\":=\"",
+    "\")\"",
     "\",\"",
-    "\")\"",
     "\";\"",
     "\"a\"",
     "\"[\"",

Modified: trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserTokenManager.java
===================================================================
--- trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserTokenManager.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/querylang/javacc/org/mulgara/sparql/parser/SparqlParserTokenManager.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -39,57 +39,59 @@
          jjmatchedKind = 5;
          return jjMoveNfa_0(0, 0);
       case 33:
-         jjmatchedKind = 64;
-         return jjMoveStringLiteralDfa1_0(0x100000000000000L, 0x0L);
+         jjmatchedKind = 66;
+         return jjMoveStringLiteralDfa1_0(0x400000000000000L, 0x0L);
       case 35:
          jjmatchedKind = 6;
          return jjMoveNfa_0(0, 0);
       case 38:
-         return jjMoveStringLiteralDfa1_0(0x40000000000000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x100000000000000L, 0x0L);
       case 40:
-         jjmatchedKind = 46;
+         jjmatchedKind = 47;
          return jjMoveNfa_0(0, 0);
       case 41:
-         jjmatchedKind = 48;
+         jjmatchedKind = 49;
          return jjMoveNfa_0(0, 0);
       case 42:
-         jjmatchedKind = 40;
+         jjmatchedKind = 41;
          return jjMoveNfa_0(0, 0);
       case 43:
-         jjmatchedKind = 61;
+         jjmatchedKind = 63;
          return jjMoveNfa_0(0, 0);
       case 44:
-         jjmatchedKind = 47;
+         jjmatchedKind = 50;
          return jjMoveNfa_0(0, 0);
       case 45:
-         jjmatchedKind = 62;
+         jjmatchedKind = 64;
          return jjMoveNfa_0(0, 0);
       case 46:
-         jjmatchedKind = 44;
+         jjmatchedKind = 45;
          return jjMoveNfa_0(0, 0);
       case 47:
-         jjmatchedKind = 63;
+         jjmatchedKind = 65;
          return jjMoveNfa_0(0, 0);
+      case 58:
+         return jjMoveStringLiteralDfa1_0(0x1000000000000L, 0x0L);
       case 59:
-         jjmatchedKind = 49;
+         jjmatchedKind = 51;
          return jjMoveNfa_0(0, 0);
       case 60:
+         jjmatchedKind = 59;
+         return jjMoveStringLiteralDfa1_0(0x2000000000000000L, 0x0L);
+      case 61:
          jjmatchedKind = 57;
-         return jjMoveStringLiteralDfa1_0(0x800000000000000L, 0x0L);
-      case 61:
-         jjmatchedKind = 55;
          return jjMoveNfa_0(0, 0);
       case 62:
-         jjmatchedKind = 58;
-         return jjMoveStringLiteralDfa1_0(0x1000000000000000L, 0x0L);
+         jjmatchedKind = 60;
+         return jjMoveStringLiteralDfa1_0(0x4000000000000000L, 0x0L);
       case 65:
-         return jjMoveStringLiteralDfa1_0(0x20040000000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x40040000000L, 0x0L);
       case 66:
          return jjMoveStringLiteralDfa1_0(0x1000000a00L, 0x0L);
       case 67:
          return jjMoveStringLiteralDfa1_0(0x20000L, 0x0L);
       case 68:
-         return jjMoveStringLiteralDfa1_0(0x40280800000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x80280800000L, 0x0L);
       case 70:
          return jjMoveStringLiteralDfa1_0(0x8100001000L, 0x0L);
       case 71:
@@ -97,7 +99,7 @@
       case 73:
          return jjMoveStringLiteralDfa1_0(0x30408000L, 0x0L);
       case 76:
-         return jjMoveStringLiteralDfa1_0(0x8240000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x10008240000L, 0x0L);
       case 78:
          return jjMoveStringLiteralDfa1_0(0x80000L, 0x0L);
       case 79:
@@ -115,15 +117,15 @@
       case 87:
          return jjMoveStringLiteralDfa1_0(0x2000000L, 0x0L);
       case 91:
-         jjmatchedKind = 51;
+         jjmatchedKind = 53;
          return jjMoveNfa_0(0, 0);
       case 93:
-         jjmatchedKind = 52;
+         jjmatchedKind = 54;
          return jjMoveNfa_0(0, 0);
       case 94:
-         return jjMoveStringLiteralDfa1_0(0x0L, 0x2L);
+         return jjMoveStringLiteralDfa1_0(0x0L, 0x8L);
       case 97:
-         jjmatchedKind = 50;
+         jjmatchedKind = 52;
          return jjMoveStringLiteralDfa1_0(0x40000000L, 0x0L);
       case 98:
          return jjMoveStringLiteralDfa1_0(0x1000000a00L, 0x0L);
@@ -138,7 +140,7 @@
       case 105:
          return jjMoveStringLiteralDfa1_0(0x30408000L, 0x0L);
       case 108:
-         return jjMoveStringLiteralDfa1_0(0x8240000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x10008240000L, 0x0L);
       case 110:
          return jjMoveStringLiteralDfa1_0(0x80000L, 0x0L);
       case 111:
@@ -156,12 +158,12 @@
       case 119:
          return jjMoveStringLiteralDfa1_0(0x2000000L, 0x0L);
       case 123:
-         jjmatchedKind = 43;
+         jjmatchedKind = 44;
          return jjMoveNfa_0(0, 0);
       case 124:
-         return jjMoveStringLiteralDfa1_0(0x20000000000000L, 0x0L);
+         return jjMoveStringLiteralDfa1_0(0x80000000000000L, 0x0L);
       case 125:
-         jjmatchedKind = 45;
+         jjmatchedKind = 46;
          return jjMoveNfa_0(0, 0);
       default :
          return jjMoveNfa_0(0, 0);
@@ -176,33 +178,38 @@
    switch(curChar)
    {
       case 38:
-         if ((active0 & 0x40000000000000L) != 0L)
+         if ((active0 & 0x100000000000000L) != 0L)
          {
-            jjmatchedKind = 54;
+            jjmatchedKind = 56;
             jjmatchedPos = 1;
          }
          break;
       case 61:
-         if ((active0 & 0x100000000000000L) != 0L)
+         if ((active0 & 0x1000000000000L) != 0L)
          {
-            jjmatchedKind = 56;
+            jjmatchedKind = 48;
             jjmatchedPos = 1;
          }
-         else if ((active0 & 0x800000000000000L) != 0L)
+         else if ((active0 & 0x400000000000000L) != 0L)
          {
-            jjmatchedKind = 59;
+            jjmatchedKind = 58;
             jjmatchedPos = 1;
          }
-         else if ((active0 & 0x1000000000000000L) != 0L)
+         else if ((active0 & 0x2000000000000000L) != 0L)
          {
-            jjmatchedKind = 60;
+            jjmatchedKind = 61;
             jjmatchedPos = 1;
          }
+         else if ((active0 & 0x4000000000000000L) != 0L)
+         {
+            jjmatchedKind = 62;
+            jjmatchedPos = 1;
+         }
          break;
       case 65:
          return jjMoveStringLiteralDfa2_0(active0, 0xc208280200L, active1, 0L);
       case 69:
-         return jjMoveStringLiteralDfa2_0(active0, 0x40c00800100L, active1, 0L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x90c00800100L, active1, 0L);
       case 70:
          return jjMoveStringLiteralDfa2_0(active0, 0x1000000L, active1, 0L);
       case 72:
@@ -218,7 +225,7 @@
       case 82:
          return jjMoveStringLiteralDfa2_0(active0, 0x2000013400L, active1, 0L);
       case 83:
-         return jjMoveStringLiteralDfa2_0(active0, 0x20070408000L, active1, 0L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x40070408000L, active1, 0L);
       case 84:
          return jjMoveStringLiteralDfa2_0(active0, 0x4000L, active1, 0L);
       case 89:
@@ -229,16 +236,16 @@
          }
          break;
       case 94:
-         if ((active1 & 0x2L) != 0L)
+         if ((active1 & 0x8L) != 0L)
          {
-            jjmatchedKind = 65;
+            jjmatchedKind = 67;
             jjmatchedPos = 1;
          }
          break;
       case 97:
          return jjMoveStringLiteralDfa2_0(active0, 0xc208280200L, active1, 0L);
       case 101:
-         return jjMoveStringLiteralDfa2_0(active0, 0xc00800100L, active1, 0L);
+         return jjMoveStringLiteralDfa2_0(active0, 0x10c00800100L, active1, 0L);
       case 102:
          return jjMoveStringLiteralDfa2_0(active0, 0x1000000L, active1, 0L);
       case 104:
@@ -265,9 +272,9 @@
          }
          break;
       case 124:
-         if ((active0 & 0x20000000000000L) != 0L)
+         if ((active0 & 0x80000000000000L) != 0L)
          {
-            jjmatchedKind = 53;
+            jjmatchedKind = 55;
             jjmatchedPos = 1;
          }
          break;
@@ -291,9 +298,9 @@
       case 66:
          return jjMoveStringLiteralDfa3_0(active0, 0x10000000L);
       case 67:
-         if ((active0 & 0x20000000000L) != 0L)
+         if ((active0 & 0x40000000000L) != 0L)
          {
-            jjmatchedKind = 41;
+            jjmatchedKind = 42;
             jjmatchedPos = 2;
          }
          break;
@@ -330,8 +337,13 @@
          }
          break;
       case 83:
-         return jjMoveStringLiteralDfa3_0(active0, 0x40080800200L);
+         return jjMoveStringLiteralDfa3_0(active0, 0x80080800200L);
       case 84:
+         if ((active0 & 0x10000000000L) != 0L)
+         {
+            jjmatchedKind = 40;
+            jjmatchedPos = 2;
+         }
          return jjMoveStringLiteralDfa3_0(active0, 0x200100000L);
       case 85:
          return jjMoveStringLiteralDfa3_0(active0, 0x3000008000L);
@@ -374,6 +386,11 @@
       case 115:
          return jjMoveStringLiteralDfa3_0(active0, 0x80800200L);
       case 116:
+         if ((active0 & 0x10000000000L) != 0L)
+         {
+            jjmatchedKind = 40;
+            jjmatchedPos = 2;
+         }
          return jjMoveStringLiteralDfa3_0(active0, 0x200100000L);
       case 117:
          return jjMoveStringLiteralDfa3_0(active0, 0x3000008000L);
@@ -395,9 +412,9 @@
       case 65:
          return jjMoveStringLiteralDfa4_0(active0, 0x200000000L);
       case 67:
-         if ((active0 & 0x40000000000L) != 0L)
+         if ((active0 & 0x80000000000L) != 0L)
          {
-            jjmatchedKind = 42;
+            jjmatchedKind = 43;
             jjmatchedPos = 3;
          }
          return jjMoveStringLiteralDfa4_0(active0, 0x800000L);
@@ -1115,8 +1132,8 @@
                case 0:
                   if ((0x3ff000000000000L & l) != 0L)
                   {
-                     if (kind > 76)
-                        kind = 76;
+                     if (kind > 78)
+                        kind = 78;
                      jjCheckNAddStates(0, 6);
                   }
                   else if (curChar == 45)
@@ -1127,8 +1144,8 @@
                      jjCheckNAddTwoStates(88, 89);
                   else if (curChar == 58)
                   {
-                     if (kind > 67)
-                        kind = 67;
+                     if (kind > 69)
+                        kind = 69;
                      jjCheckNAdd(66);
                   }
                   else if (curChar == 40)
@@ -1145,8 +1162,8 @@
                      jjstateSet[jjnewStateCnt++] = 9;
                   if ((0x3ff000000000000L & l) != 0L)
                   {
-                     if (kind > 99)
-                        kind = 99;
+                     if (kind > 101)
+                        kind = 101;
                      jjCheckNAddTwoStates(57, 58);
                   }
                   else if (curChar == 34)
@@ -1159,8 +1176,8 @@
                      jjCheckNAddTwoStates(1, 2);
                   break;
                case 2:
-                  if (curChar == 62 && kind > 66)
-                     kind = 66;
+                  if (curChar == 62 && kind > 68)
+                     kind = 68;
                   break;
                case 3:
                   if (curChar == 58)
@@ -1169,8 +1186,8 @@
                case 4:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 69)
-                     kind = 69;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(5, 6);
                   break;
                case 5:
@@ -1178,8 +1195,8 @@
                      jjCheckNAddTwoStates(5, 6);
                   break;
                case 6:
-                  if ((0x3ff200000000000L & l) != 0L && kind > 69)
-                     kind = 69;
+                  if ((0x3ff200000000000L & l) != 0L && kind > 71)
+                     kind = 71;
                   break;
                case 8:
                   if (curChar == 63)
@@ -1189,8 +1206,8 @@
                case 10:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 70)
-                     kind = 70;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAdd(10);
                   break;
                case 11:
@@ -1201,8 +1218,8 @@
                case 13:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 71)
-                     kind = 71;
+                  if (kind > 73)
+                     kind = 73;
                   jjCheckNAdd(13);
                   break;
                case 16:
@@ -1212,8 +1229,8 @@
                case 17:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 72)
-                     kind = 72;
+                  if (kind > 74)
+                     kind = 74;
                   jjCheckNAddTwoStates(16, 17);
                   break;
                case 18:
@@ -1229,8 +1246,8 @@
                      jjCheckNAddStates(20, 22);
                   break;
                case 22:
-                  if (curChar == 39 && kind > 86)
-                     kind = 86;
+                  if (curChar == 39 && kind > 88)
+                     kind = 88;
                   break;
                case 23:
                   if (curChar == 34)
@@ -1245,8 +1262,8 @@
                      jjCheckNAddStates(17, 19);
                   break;
                case 27:
-                  if (curChar == 34 && kind > 87)
-                     kind = 87;
+                  if (curChar == 34 && kind > 89)
+                     kind = 89;
                   break;
                case 28:
                   if (curChar == 39)
@@ -1270,8 +1287,8 @@
                      jjAddStates(27, 28);
                   break;
                case 35:
-                  if (curChar == 39 && kind > 88)
-                     kind = 88;
+                  if (curChar == 39 && kind > 90)
+                     kind = 90;
                   break;
                case 36:
                   if (curChar == 39)
@@ -1307,8 +1324,8 @@
                      jjAddStates(33, 34);
                   break;
                case 46:
-                  if (curChar == 34 && kind > 89)
-                     kind = 89;
+                  if (curChar == 34 && kind > 91)
+                     kind = 91;
                   break;
                case 47:
                   if (curChar == 34)
@@ -1331,8 +1348,8 @@
                      jjCheckNAddTwoStates(51, 52);
                   break;
                case 52:
-                  if (curChar == 41 && kind > 91)
-                     kind = 91;
+                  if (curChar == 41 && kind > 93)
+                     kind = 93;
                   break;
                case 54:
                   if ((0x100002600L & l) != 0L)
@@ -1341,8 +1358,8 @@
                case 56:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 99)
-                     kind = 99;
+                  if (kind > 101)
+                     kind = 101;
                   jjCheckNAddTwoStates(57, 58);
                   break;
                case 57:
@@ -1350,8 +1367,8 @@
                      jjCheckNAddTwoStates(57, 58);
                   break;
                case 58:
-                  if ((0x3ff200000000000L & l) != 0L && kind > 99)
-                     kind = 99;
+                  if ((0x3ff200000000000L & l) != 0L && kind > 101)
+                     kind = 101;
                   break;
                case 60:
                   if ((0x3ff600000000000L & l) != 0L)
@@ -1362,8 +1379,8 @@
                      jjstateSet[jjnewStateCnt++] = 62;
                   break;
                case 62:
-                  if (curChar == 58 && kind > 67)
-                     kind = 67;
+                  if (curChar == 58 && kind > 69)
+                     kind = 69;
                   break;
                case 63:
                   if ((0x3ff600000000000L & l) != 0L)
@@ -1380,8 +1397,8 @@
                case 66:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 68)
-                     kind = 68;
+                  if (kind > 70)
+                     kind = 70;
                   jjCheckNAddTwoStates(67, 68);
                   break;
                case 67:
@@ -1389,36 +1406,36 @@
                      jjCheckNAddTwoStates(67, 68);
                   break;
                case 68:
-                  if ((0x3ff200000000000L & l) != 0L && kind > 68)
-                     kind = 68;
+                  if ((0x3ff200000000000L & l) != 0L && kind > 70)
+                     kind = 70;
                   break;
                case 69:
                   if ((0x3ff600000000000L & l) != 0L)
                      jjAddStates(41, 42);
                   break;
                case 70:
-                  if ((0x3ff200000000000L & l) != 0L && kind > 98)
-                     kind = 98;
+                  if ((0x3ff200000000000L & l) != 0L && kind > 100)
+                     kind = 100;
                   break;
                case 71:
                   if (curChar != 58)
                      break;
-                  if (kind > 67)
-                     kind = 67;
+                  if (kind > 69)
+                     kind = 69;
                   jjCheckNAdd(66);
                   break;
                case 72:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 76)
-                     kind = 76;
+                  if (kind > 78)
+                     kind = 78;
                   jjCheckNAddStates(0, 6);
                   break;
                case 73:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 76)
-                     kind = 76;
+                  if (kind > 78)
+                     kind = 78;
                   jjCheckNAdd(73);
                   break;
                case 74:
@@ -1428,15 +1445,15 @@
                case 75:
                   if (curChar != 46)
                      break;
-                  if (kind > 77)
-                     kind = 77;
+                  if (kind > 79)
+                     kind = 79;
                   jjCheckNAdd(76);
                   break;
                case 76:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 77)
-                     kind = 77;
+                  if (kind > 79)
+                     kind = 79;
                   jjCheckNAdd(76);
                   break;
                case 77:
@@ -1458,8 +1475,8 @@
                case 82:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 78)
-                     kind = 78;
+                  if (kind > 80)
+                     kind = 80;
                   jjCheckNAdd(82);
                   break;
                case 83:
@@ -1473,8 +1490,8 @@
                case 86:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 78)
-                     kind = 78;
+                  if (kind > 80)
+                     kind = 80;
                   jjCheckNAdd(86);
                   break;
                case 87:
@@ -1484,8 +1501,8 @@
                case 88:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 77)
-                     kind = 77;
+                  if (kind > 79)
+                     kind = 79;
                   jjCheckNAdd(88);
                   break;
                case 89:
@@ -1499,8 +1516,8 @@
                case 92:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 78)
-                     kind = 78;
+                  if (kind > 80)
+                     kind = 80;
                   jjCheckNAdd(92);
                   break;
                case 93:
@@ -1510,8 +1527,8 @@
                case 94:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 79)
-                     kind = 79;
+                  if (kind > 81)
+                     kind = 81;
                   jjCheckNAdd(94);
                   break;
                case 95:
@@ -1521,15 +1538,15 @@
                case 96:
                   if (curChar != 46)
                      break;
-                  if (kind > 80)
-                     kind = 80;
+                  if (kind > 82)
+                     kind = 82;
                   jjCheckNAdd(97);
                   break;
                case 97:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 80)
-                     kind = 80;
+                  if (kind > 82)
+                     kind = 82;
                   jjCheckNAdd(97);
                   break;
                case 98:
@@ -1539,8 +1556,8 @@
                case 99:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 80)
-                     kind = 80;
+                  if (kind > 82)
+                     kind = 82;
                   jjCheckNAdd(99);
                   break;
                case 100:
@@ -1558,8 +1575,8 @@
                case 104:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 81)
-                     kind = 81;
+                  if (kind > 83)
+                     kind = 83;
                   jjCheckNAdd(104);
                   break;
                case 105:
@@ -1585,8 +1602,8 @@
                case 111:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 81)
-                     kind = 81;
+                  if (kind > 83)
+                     kind = 83;
                   jjCheckNAdd(111);
                   break;
                case 112:
@@ -1600,8 +1617,8 @@
                case 115:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 81)
-                     kind = 81;
+                  if (kind > 83)
+                     kind = 83;
                   jjCheckNAdd(115);
                   break;
                case 116:
@@ -1611,8 +1628,8 @@
                case 117:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 82)
-                     kind = 82;
+                  if (kind > 84)
+                     kind = 84;
                   jjCheckNAdd(117);
                   break;
                case 118:
@@ -1622,15 +1639,15 @@
                case 119:
                   if (curChar != 46)
                      break;
-                  if (kind > 83)
-                     kind = 83;
+                  if (kind > 85)
+                     kind = 85;
                   jjCheckNAdd(120);
                   break;
                case 120:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 83)
-                     kind = 83;
+                  if (kind > 85)
+                     kind = 85;
                   jjCheckNAdd(120);
                   break;
                case 121:
@@ -1640,8 +1657,8 @@
                case 122:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 83)
-                     kind = 83;
+                  if (kind > 85)
+                     kind = 85;
                   jjCheckNAdd(122);
                   break;
                case 123:
@@ -1659,8 +1676,8 @@
                case 127:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 84)
-                     kind = 84;
+                  if (kind > 86)
+                     kind = 86;
                   jjCheckNAdd(127);
                   break;
                case 128:
@@ -1686,8 +1703,8 @@
                case 134:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 84)
-                     kind = 84;
+                  if (kind > 86)
+                     kind = 86;
                   jjCheckNAdd(134);
                   break;
                case 135:
@@ -1701,8 +1718,8 @@
                case 138:
                   if ((0x3ff000000000000L & l) == 0L)
                      break;
-                  if (kind > 84)
-                     kind = 84;
+                  if (kind > 86)
+                     kind = 86;
                   jjCheckNAdd(138);
                   break;
                default : break;
@@ -1719,8 +1736,8 @@
                case 0:
                   if ((0x7fffffe87fffffeL & l) != 0L)
                   {
-                     if (kind > 99)
-                        kind = 99;
+                     if (kind > 101)
+                        kind = 101;
                      jjCheckNAddTwoStates(57, 58);
                   }
                   else if (curChar == 91)
@@ -1729,8 +1746,8 @@
                      jjCheckNAdd(15);
                   if ((0x7fffffe07fffffeL & l) != 0L)
                   {
-                     if (kind > 98)
-                        kind = 98;
+                     if (kind > 100)
+                        kind = 100;
                      jjCheckNAddStates(51, 58);
                   }
                   else if (curChar == 95)
@@ -1743,8 +1760,8 @@
                case 4:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 69)
-                     kind = 69;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(5, 6);
                   break;
                case 5:
@@ -1752,8 +1769,8 @@
                      jjCheckNAddTwoStates(5, 6);
                   break;
                case 6:
-                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 69)
-                     kind = 69;
+                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 71)
+                     kind = 71;
                   break;
                case 7:
                   if (curChar == 95)
@@ -1763,16 +1780,16 @@
                case 10:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 70)
-                     kind = 70;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAdd(10);
                   break;
                case 12:
                case 13:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 71)
-                     kind = 71;
+                  if (kind > 73)
+                     kind = 73;
                   jjCheckNAdd(13);
                   break;
                case 14:
@@ -1782,15 +1799,15 @@
                case 15:
                   if ((0x7fffffe07fffffeL & l) == 0L)
                      break;
-                  if (kind > 72)
-                     kind = 72;
+                  if (kind > 74)
+                     kind = 74;
                   jjCheckNAddTwoStates(15, 16);
                   break;
                case 17:
                   if ((0x7fffffe07fffffeL & l) == 0L)
                      break;
-                  if (kind > 72)
-                     kind = 72;
+                  if (kind > 74)
+                     kind = 74;
                   jjCheckNAddTwoStates(16, 17);
                   break;
                case 19:
@@ -1846,14 +1863,14 @@
                      jjAddStates(35, 36);
                   break;
                case 55:
-                  if (curChar == 93 && kind > 93)
-                     kind = 93;
+                  if (curChar == 93 && kind > 95)
+                     kind = 95;
                   break;
                case 56:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 99)
-                     kind = 99;
+                  if (kind > 101)
+                     kind = 101;
                   jjCheckNAddTwoStates(57, 58);
                   break;
                case 57:
@@ -1861,14 +1878,14 @@
                      jjCheckNAddTwoStates(57, 58);
                   break;
                case 58:
-                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 99)
-                     kind = 99;
+                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 101)
+                     kind = 101;
                   break;
                case 59:
                   if ((0x7fffffe07fffffeL & l) == 0L)
                      break;
-                  if (kind > 98)
-                     kind = 98;
+                  if (kind > 100)
+                     kind = 100;
                   jjCheckNAddStates(51, 58);
                   break;
                case 60:
@@ -1890,8 +1907,8 @@
                case 66:
                   if ((0x7fffffe87fffffeL & l) == 0L)
                      break;
-                  if (kind > 68)
-                     kind = 68;
+                  if (kind > 70)
+                     kind = 70;
                   jjCheckNAddTwoStates(67, 68);
                   break;
                case 67:
@@ -1899,16 +1916,16 @@
                      jjCheckNAddTwoStates(67, 68);
                   break;
                case 68:
-                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 68)
-                     kind = 68;
+                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 70)
+                     kind = 70;
                   break;
                case 69:
                   if ((0x7fffffe87fffffeL & l) != 0L)
                      jjCheckNAddTwoStates(69, 70);
                   break;
                case 70:
-                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 98)
-                     kind = 98;
+                  if ((0x7fffffe87fffffeL & l) != 0L && kind > 100)
+                     kind = 100;
                   break;
                case 80:
                   if ((0x2000000020L & l) != 0L)
@@ -1964,14 +1981,14 @@
                case 0:
                   if (jjCanMove_1(hiByte, i1, i2, l1, l2))
                   {
-                     if (kind > 99)
-                        kind = 99;
+                     if (kind > 101)
+                        kind = 101;
                      jjCheckNAddTwoStates(57, 58);
                   }
                   if (jjCanMove_1(hiByte, i1, i2, l1, l2))
                   {
-                     if (kind > 98)
-                        kind = 98;
+                     if (kind > 100)
+                        kind = 100;
                      jjCheckNAddStates(51, 58);
                   }
                   break;
@@ -1982,8 +1999,8 @@
                case 4:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 69)
-                     kind = 69;
+                  if (kind > 71)
+                     kind = 71;
                   jjCheckNAddTwoStates(5, 6);
                   break;
                case 5:
@@ -1991,35 +2008,35 @@
                      jjCheckNAddTwoStates(5, 6);
                   break;
                case 6:
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 69)
-                     kind = 69;
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 71)
+                     kind = 71;
                   break;
                case 9:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 70)
-                     kind = 70;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAdd(10);
                   break;
                case 10:
                   if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 70)
-                     kind = 70;
+                  if (kind > 72)
+                     kind = 72;
                   jjCheckNAdd(10);
                   break;
                case 12:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 71)
-                     kind = 71;
+                  if (kind > 73)
+                     kind = 73;
                   jjCheckNAdd(13);
                   break;
                case 13:
                   if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 71)
-                     kind = 71;
+                  if (kind > 73)
+                     kind = 73;
                   jjCheckNAdd(13);
                   break;
                case 19:
@@ -2041,8 +2058,8 @@
                case 56:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 99)
-                     kind = 99;
+                  if (kind > 101)
+                     kind = 101;
                   jjCheckNAddTwoStates(57, 58);
                   break;
                case 57:
@@ -2050,14 +2067,14 @@
                      jjCheckNAddTwoStates(57, 58);
                   break;
                case 58:
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 99)
-                     kind = 99;
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 101)
+                     kind = 101;
                   break;
                case 59:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 98)
-                     kind = 98;
+                  if (kind > 100)
+                     kind = 100;
                   jjCheckNAddStates(51, 58);
                   break;
                case 60:
@@ -2079,8 +2096,8 @@
                case 66:
                   if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
                      break;
-                  if (kind > 68)
-                     kind = 68;
+                  if (kind > 70)
+                     kind = 70;
                   jjCheckNAddTwoStates(67, 68);
                   break;
                case 67:
@@ -2088,16 +2105,16 @@
                      jjCheckNAddTwoStates(67, 68);
                   break;
                case 68:
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 68)
-                     kind = 68;
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 70)
+                     kind = 70;
                   break;
                case 69:
                   if (jjCanMove_2(hiByte, i1, i2, l1, l2))
                      jjCheckNAddTwoStates(69, 70);
                   break;
                case 70:
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 98)
-                     kind = 98;
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2) && kind > 100)
+                     kind = 100;
                   break;
                default : break;
             }
@@ -2292,12 +2309,13 @@
 public static final String[] jjstrLiteralImages = {
 "", null, null, null, null, null, null, null, null, null, null, null, null, 
 null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
-null, null, null, null, null, null, null, null, null, null, null, null, null, "\52", 
-"\101\123\103", "\104\105\123\103", "\173", "\56", "\175", "\50", "\54", "\51", "\73", "\141", 
-"\133", "\135", "\174\174", "\46\46", "\75", "\41\75", "\74", "\76", "\74\75", 
-"\76\75", "\53", "\55", "\57", "\41", "\136\136", null, null, null, null, null, null, 
 null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
-null, null, null, null, null, null, null, null, null, null, null, null, null, null, };
+"\52", "\101\123\103", "\104\105\123\103", "\173", "\56", "\175", "\50", "\72\75", 
+"\51", "\54", "\73", "\141", "\133", "\135", "\174\174", "\46\46", "\75", "\41\75", 
+"\74", "\76", "\74\75", "\76\75", "\53", "\55", "\57", "\41", "\136\136", null, null, 
+null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
+null, null, null, null, null, null, null, null, null, null, null, null, null, null, 
+null, null, null, null, };
 public static final String[] lexStateNames = {
    "DEFAULT", 
    "IN_COMMENT", 
@@ -2307,9 +2325,10 @@
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+   -1, -1, 
 };
 static final long[] jjtoToken = {
-   0xffffffffffffff01L, 0xc2bdff1ffL, 
+   0xffffffffffffff01L, 0x30af7fc7ffL, 
 };
 static final long[] jjtoSkip = {
    0xbeL, 0x0L, 

Modified: trunk/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java
===================================================================
--- trunk/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/resolver/java/org/mulgara/resolver/DefaultConstraintHandlers.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -216,6 +216,13 @@
                                            ((LocalNode)context.localize(constraint.getValueNode())).getValue());
           }
         }),
+        new NVPair(ConstraintAssignment.class, new ConstraintResolutionHandler() {
+          public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception {
+            ConstraintAssignment assignment = (ConstraintAssignment)constraintExpr;
+            Tuples arg = ConstraintOperations.resolveConstraintExpression(context, modelExpr, assignment.getContextConstraint());
+            return TuplesOperations.assign(arg, assignment.getVariable(), assignment.getExpression(), context);
+          }
+        }),
         new NVPair(ConstraintImpl.class, new ConstraintResolutionHandler() {
           public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception {
             ConstraintImpl constraint = (ConstraintImpl)constraintExpr;

Modified: trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TuplesContext.java
===================================================================
--- trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TuplesContext.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/resolver-spi/java/org/mulgara/resolver/spi/TuplesContext.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -128,5 +128,20 @@
       throw new QueryException("Unable to globalize id <" + gNode + ">", te);
     }
   }
+
+
+  /**
+   * Localize a data object into a gNode.
+   * @param o The object to localize.
+   * @return a gNode representing the node.
+   * @throws QueryException If a localize exception is encountered.
+   */
+  public long localize(Node node) throws QueryException {
+    try {
+      return session.localize(node);
+    } catch (LocalizeException te) {
+      throw new QueryException("Unable to localize: " + node, te);
+    }
+  }
   
 }

Added: trunk/src/jar/tuples/java/org/mulgara/store/tuples/LetTuples.java
===================================================================
--- trunk/src/jar/tuples/java/org/mulgara/store/tuples/LetTuples.java	                        (rev 0)
+++ trunk/src/jar/tuples/java/org/mulgara/store/tuples/LetTuples.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2009 Fedora Commons, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.store.tuples;
+
+// Java 2 standard packages
+import java.util.*;
+
+// Third party packages
+import org.apache.log4j.*;
+
+// Locally written packages
+import org.jrdf.graph.Node;
+import org.mulgara.query.Constraint;
+import org.mulgara.query.QueryException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.Variable;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.ContextOwner;
+import org.mulgara.query.filter.RDFTerm;
+import org.mulgara.resolver.spi.QueryEvaluationContext;
+import org.mulgara.resolver.spi.TuplesContext;
+import org.mulgara.store.statement.StatementStore;
+import org.mulgara.store.tuples.AbstractTuples;
+
+/**
+ * Variable binding operation. This class wraps another Tuples, binding a variable based on what
+ * the context provided by that Tuples.
+ * 
+ * @created July 1, 2009
+ * @author Paul Gearon
+ * @copyright &copy; 2009 <a href="http://www.fedora-commons.org/">Fedora Commons</a>
+ */
+public class LetTuples extends AbstractTuples implements ContextOwner {
+
+  @SuppressWarnings("unused")
+  private static Logger logger = Logger.getLogger(LetTuples.class.getName());
+
+  /** The inner tuples to filter. */
+  protected Tuples innerTuples;
+
+  /** The expression to bind the variable to. */
+  protected RDFTerm expr;
+
+  /** The variable to be bound by the expression. */
+  protected Variable var;
+
+  /** The tuples context */
+  protected TuplesContext context;
+
+  /** A list of context owners that this owner provides the context for. */
+  private List<ContextOwner> contextListeners = new ArrayList<ContextOwner>();
+
+  /** A convenience for remembering the last column in this tuples. */
+  private int lastCol;
+
+  /**
+   * Configure a tuples for binding a variable.
+   *
+   * @param innerTuples The original tuples.
+   * @param var the variable to bind.
+   * @param expr The expression to bind the variable to.
+   * @param queryContext The context to evaluate the tuples in.
+   * @throws IllegalArgumentException If the <var>innerTuples</var> is null.
+   */
+  LetTuples(Tuples innerTuples, Variable var, RDFTerm expr, QueryEvaluationContext queryContext) throws IllegalArgumentException {
+    // store the operands
+    this.var = var;
+    this.expr = expr;
+    this.innerTuples = (Tuples)innerTuples.clone();
+    this.context = new TuplesContext(this.innerTuples, queryContext.getResolverSession());
+    expr.setContextOwner(this);
+
+    // duplicate the inner variables, and add the new variable to it
+    Variable[] innerVars = this.innerTuples.getVariables();
+    this.lastCol = innerVars.length;
+    Variable[] vars = new Variable[this.lastCol + 1];
+    for (int i = 0; i < innerVars.length; i++) {
+      if (var.equals(innerVars[i])) throw new IllegalArgumentException("Variable ?" + var + " is already bound");
+      vars[i] = innerVars[i];
+    }
+    vars[innerVars.length] = var;
+
+    setVariables(vars);
+  }
+
+
+  /** {@inheritDoc} */
+  public long getColumnValue(int column) throws TuplesException {
+    if (column < lastCol) return innerTuples.getColumnValue(column);
+    // re-root the expression to this Tuples
+    expr.setContextOwner(this);
+    try {
+      Node val = expr.getJRDFValue();
+      return context.localize(val);
+    } catch (QueryException e) {
+      return UNBOUND;
+    }
+  }
+
+  
+  /** {@inheritDoc} */
+  public long getRawColumnValue(int column) throws TuplesException {
+    if (column < lastCol) return innerTuples.getRawColumnValue(column);
+    // re-root the expression to this Tuples
+    expr.setContextOwner(this);
+    try {
+      Node val = expr.getJRDFValue();
+      return context.localize(val);
+    } catch (QueryException e) {
+      return UNBOUND;
+    }
+  }
+
+
+  /** {@inheritDoc} */
+  public long getRowUpperBound() throws TuplesException {
+    return innerTuples.getRowUpperBound();
+  }
+
+
+  /** {@inheritDoc} */
+  public boolean isColumnEverUnbound(int column) throws TuplesException {
+    return column == lastCol || innerTuples.isColumnEverUnbound(column);
+  }
+
+
+  /** {@inheritDoc} */
+  public Variable[] getVariables() {
+    return super.getVariables();
+  }
+
+
+  /** {@inheritDoc} */
+  public int getColumnIndex(Variable variable) throws TuplesException {
+    return variable.equals(var) ? lastCol : innerTuples.getColumnIndex(variable);
+  }
+
+
+  /** {@inheritDoc} */
+  public boolean isMaterialized() {
+    return innerTuples.isMaterialized();
+  }
+
+
+  /** {@inheritDoc} */
+  public boolean hasNoDuplicates() throws TuplesException {
+    return innerTuples.hasNoDuplicates();
+  }
+
+
+  /** {@inheritDoc} */
+  public RowComparator getComparator() {
+    return innerTuples.getComparator();
+  }
+
+
+  /** {@inheritDoc} */
+  public List<Tuples> getOperands() {
+    return Collections.unmodifiableList(Arrays.asList(new Tuples[] {innerTuples}));
+  }
+
+
+  /** {@inheritDoc} */
+  public boolean isUnconstrained() throws TuplesException {
+    return innerTuples.isUnconstrained();
+  }
+
+
+  /** {@inheritDoc} */
+  public void renameVariables(Constraint constraint) {
+    innerTuples.renameVariables(constraint);
+    for (int i = 0; i < StatementStore.VARIABLES.length; i++) {
+      if (var.equals(StatementStore.VARIABLES[i])) {
+        var = (Variable)constraint.getElement(i);
+        break;
+      }
+    }
+  }
+
+
+  /**
+   * {@inheritDoc}
+   * We are not going to extend this operation to localized values.
+   */
+  public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException {
+    innerTuples.beforeFirst(prefix, suffixTruncation);
+  }
+
+  
+  /**
+   * @return {@inheritDoc}
+   * @throws TuplesException {@inheritDoc}
+   */
+  public boolean next() throws TuplesException {
+    return innerTuples.next();
+  }
+
+
+  /** {@inheritDoc} */
+  public void close() throws TuplesException {
+    innerTuples.close();
+  }
+
+
+  /** @return {@inheritDoc} */
+  public Object clone() {
+    LetTuples cloned = (LetTuples)super.clone();
+
+    // Clone the mutable fields as well
+    cloned.innerTuples = (Tuples)innerTuples.clone();
+    cloned.context = new TuplesContext(cloned.innerTuples, context);
+    return cloned;
+  }
+
+
+  /**
+   * Tells a filter what the current context is.
+   * @see org.mulgara.query.filter.ContextOwner#getCurrentContext()
+   */
+  public Context getCurrentContext() {
+    return context;
+  }
+
+
+  /**
+   * Allows the context to be set manually. This is not expected.
+   * @see org.mulgara.query.filter.ContextOwner#setCurrentContext(org.mulgara.query.filter.Context)
+   */
+  public void setCurrentContext(Context context) {
+    if (!(context instanceof TuplesContext)) throw new IllegalArgumentException("FilteredTuples can only accept a TuplesContext.");
+    this.context = (TuplesContext)context;
+    for (ContextOwner l: contextListeners) l.setCurrentContext(context);
+  }
+
+
+  /**
+   * This provides a context, and does not need to refer to a parent.
+   * @see org.mulgara.query.filter.ContextOwner#getContextOwner()
+   */
+  public ContextOwner getContextOwner() {
+    throw new IllegalStateException("Should never be asking for the context owner of a Tuples");
+  }
+
+
+  /**
+   * The owner of the context for a Tuples is never needed, since it is always provided by the Tuples.
+   * @see org.mulgara.query.filter.ContextOwner#setContextOwner(org.mulgara.query.filter.ContextOwner)
+   */
+  public void setContextOwner(ContextOwner owner) {
+  }
+
+
+  /**
+   * Adds a context owner as a listener so that it will be updated with its context
+   * when this owner gets updated.
+   * @param l The context owner to register.
+   */
+  public void addContextListener(ContextOwner l) {
+    contextListeners.add(l);
+  }
+
+}

Modified: trunk/src/jar/tuples/java/org/mulgara/store/tuples/TuplesOperations.java
===================================================================
--- trunk/src/jar/tuples/java/org/mulgara/store/tuples/TuplesOperations.java	2009-07-03 17:33:12 UTC (rev 1750)
+++ trunk/src/jar/tuples/java/org/mulgara/store/tuples/TuplesOperations.java	2009-07-03 17:34:49 UTC (rev 1751)
@@ -38,6 +38,7 @@
 // Local packages
 import org.mulgara.query.*;
 import org.mulgara.query.filter.Filter;
+import org.mulgara.query.filter.RDFTerm;
 import org.mulgara.resolver.spi.*;
 import org.mulgara.util.StackTrace;
 
@@ -378,9 +379,7 @@
       if (optional.getRowCardinality() == Cursor.ZERO) {
         // need to return standard, projected out to the extra variables
         if (optional.getNumberOfVariables() == 0) {
-          logger.warn("Lost variables on empty optional");
-          // TODO: This may be a problem. Throw an exception? A fix may require variables
-          // to be attached to empty tuples
+          // This may be empty due to having zero rows (since the columns are truncated in this case)
           return (Tuples)standard.clone();
         }
       }
@@ -794,6 +793,21 @@
 
 
   /**
+   * Assign a variable to an expression, with variables coming from a provided tuples.
+   * @param tuples The Tuples to provide the variable context.
+   * @param var The variable to be bound.
+   * @param expr The expression to bind the variable to.
+   * @param context The context in which the expression is to be resolved. This can go beyond
+   *        what has already been determined for the tuples parameter.
+   * @return A new Tuples which expands the provided Tuples to include the new variable.
+   * @throws IllegalArgumentException If tuples is <code>null</code>
+   */
+  public static Tuples assign(Tuples tuples, Variable var, RDFTerm expr, QueryEvaluationContext context) {
+    return new LetTuples(tuples, var, expr, context);
+  }
+
+
+  /**
    * Sort into default order, based on the columns and local node numbers.
    * @param tuples the tuples to sort
    * @return A new Tuples with the bindings sorted.




More information about the Mulgara-svn mailing list