[Mulgara-svn] r684 - in branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query: . filter filter/arithmetic filter/value

pag at mulgara.org pag at mulgara.org
Mon Mar 17 20:42:13 UTC 2008


Author: pag
Date: 2008-03-17 13:41:59 -0700 (Mon, 17 Mar 2008)
New Revision: 684

Added:
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/AbstractContextOwner.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/And.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryComparisonFilter.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryOperatorFilter.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryTestFilter.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BooleanLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BoundFn.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Context.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/ContextOwner.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Equals.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Filter.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThan.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThanEqualTo.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThan.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThanEqualTo.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Not.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/NotEquals.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Or.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/AddOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/DivideOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MinusOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MultiplyOperation.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparable.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparableLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Bool.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ComparableExpression.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/DateTime.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/IRI.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericExpression.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/RDFTerm.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ValueLiteral.java
   branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Var.java
Log:
Initial checkin of filter code. Currently compiling

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/AbstractContextOwner.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/AbstractContextOwner.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/AbstractContextOwner.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,40 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+
+/**
+ * Defines how to set and retrieve context
+ *
+ * @created Mar 14, 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>
+ */
+public abstract class AbstractContextOwner implements ContextOwner {
+
+  /** The more recent context */
+  private Context context = null;
+
+  /**
+   * Set the current context. This *must* be run at the start of every test else the underlying
+   * values will not resolve correctly.
+   * @param context The context for this test.
+   */
+  public void setCurrentContext(Context context) { this.context = context; }
+  
+  /**
+   * Get the current context. This is a callback that is used during a test.
+   * @return The context of the currently running test, or the most recent context if not in a test.
+   */
+  public Context getCurrentContext() { return context; }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/And.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/And.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/And.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,54 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+
+
+/**
+ * A product of filters.
+ *
+ * @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>
+ */
+public class And extends BinaryOperatorFilter {
+
+  /**
+   * Create a product of two other filters.
+   * @param lhs The first operands of the product
+   * @param rhs The first operands of the product
+   */
+  public And(Filter lhs, Filter rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * <code>false</code> and Exception is <code>false</code>.
+   * <code>true</code> and Exception is Exception.
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    boolean result = false;
+    try {
+      result = lhs.test(context);
+    } catch (QueryException e) {
+      // false on the RHS gives false
+      if (!rhs.test(context)) return false;
+      throw e;
+    }
+    return result && rhs.test(context);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryComparisonFilter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryComparisonFilter.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryComparisonFilter.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,44 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.filter.value.ComparableExpression;
+
+
+/**
+ * A comparison operation.
+ *
+ * @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>
+ */
+public abstract class BinaryComparisonFilter extends AbstractContextOwner implements Filter {
+
+  /** The first operand */
+  protected ComparableExpression lhs;
+
+  /** The second operand */
+  protected ComparableExpression rhs;
+
+  /**
+   * Creates a binary comparison, and registers this filter as the context owner
+   * @param lhs The left comparison expression
+   * @param rhs The right comparison expression
+   */
+  BinaryComparisonFilter(ComparableExpression lhs, ComparableExpression rhs) {
+    this.lhs = lhs;
+    this.rhs = rhs;
+    lhs.setContextOwner(this);
+    rhs.setContextOwner(this);
+  }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryOperatorFilter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryOperatorFilter.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryOperatorFilter.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,41 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+
+/**
+ * Represents a filter that takes other filters as parameters.
+ *
+ * @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>
+ */
+public abstract class BinaryOperatorFilter extends AbstractContextOwner implements Filter {
+
+  /** The first operand */
+  protected Filter lhs;
+
+  /** The second operand */
+  protected Filter rhs;
+
+  /**
+   * Creates a binary operation
+   * @param lhs The left filter expression
+   * @param rhs The right filter expression
+   */
+  BinaryOperatorFilter(Filter lhs, Filter rhs) {
+    this.lhs = lhs;
+    this.rhs = rhs;
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryTestFilter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryTestFilter.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BinaryTestFilter.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,45 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.filter.value.RDFTerm;
+
+
+/**
+ * A test operation for equality or inequality.
+ *
+ * @created Mar 14, 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>
+ */
+public abstract class BinaryTestFilter extends AbstractContextOwner implements Filter {
+
+  /** The first operand */
+  protected RDFTerm lhs;
+
+  /** The second operand */
+  protected RDFTerm rhs;
+
+  /**
+   * Creates a binary test, and registers this filter as the context owner
+   * @param lhs The left expression
+   * @param rhs The right expression
+   */
+  BinaryTestFilter(RDFTerm lhs, RDFTerm rhs) {
+    this.lhs = lhs;
+    this.rhs = rhs;
+    lhs.setContextOwner(this);
+    rhs.setContextOwner(this);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BooleanLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BooleanLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BooleanLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,58 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+
+/**
+ * A test that always returns a given boolean value.
+ *
+ * @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>
+ */
+public class BooleanLiteral implements Filter {
+
+  /** The internal value of this literal */
+  private boolean value;
+
+  /**
+   * Create a boolean value.
+   * @param value The value to create.
+   */
+  public BooleanLiteral(boolean value) {
+    this.value = value;
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) {
+    return value;
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#setCurrentContext(org.mulgara.query.filter.Context)
+   * Context is irrelevant for this class.
+   */
+  public void setCurrentContext(Context context) {
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#getCurrentContext()
+   * Context is irrelevant for this class.
+   */
+  public Context getCurrentContext() {
+    return null;
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BoundFn.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BoundFn.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/BoundFn.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,48 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.Var;
+
+
+/**
+ * Tests a variable to see if it is bound.
+ *
+ * @created Mar 16, 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>
+ */
+public class BoundFn extends AbstractContextOwner implements Filter {
+
+  /** The variable to test */
+  Var operand;
+
+  /**
+   * Create a function for testing a variable
+   * @param The variable to test
+   */
+  public BoundFn(Var operand) {
+    this.operand = operand;
+    operand.setContextOwner(this);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return operand.isBound();
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Context.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Context.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Context.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,59 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.store.tuples.Tuples;
+
+
+/**
+ * A context for processing filters and resolving variables. This is an immutable class.
+ *
+ * @created Mar 14, 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>
+ */
+public class Context {
+
+  /** The tuples containing variables and bindings. */
+  private Tuples tuples;
+
+  /** The session used for globalizing info. */
+  private ResolverSession session;
+
+  /**
+   * Creates a new context for processing a filter.
+   * @param tuples The variables and bindings to use in filtering. Not all variables need be bound.
+   * @param session The session used for globalizing the local data found in the filter.
+   */
+  public Context(Tuples tuples, ResolverSession session) {
+    this.tuples = tuples;
+    this.session = session;
+  }
+
+  
+  /**
+   * @return the tuples
+   */
+  public Tuples getTuples() {
+    return tuples;
+  }
+
+  
+  /**
+   * @return the session
+   */
+  public ResolverSession getSession() {
+    return session;
+  }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/ContextOwner.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/ContextOwner.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/ContextOwner.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,37 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+
+/**
+ * Defines how to set and retrieve context
+ *
+ * @created Mar 14, 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>
+ */
+public interface ContextOwner {
+
+  /**
+   * Set the current context. This *must* be run at the start of every test else the underlying
+   * values will not resolve correctly.
+   * @param context The context for this test.
+   */
+  public void setCurrentContext(Context context);
+  
+  /**
+   * Get the current context. This is a callback that is used during a test.
+   * @return The context of the currently running test, or the most recent context if not in a test.
+   */
+  public Context getCurrentContext();
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Equals.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Equals.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Equals.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,45 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.RDFTerm;
+
+
+/**
+ * The equality comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class Equals extends BinaryTestFilter {
+
+  /**
+   * Creates an equality test operation
+   * @param lhs The first term to compare
+   * @param rhs The second term to compare
+   */
+  Equals(RDFTerm lhs, RDFTerm rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.equals(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Filter.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Filter.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Filter.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,42 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+
+
+/**
+ * Filters the iteration of a Constraint.
+ *
+ * @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>
+ */
+public interface Filter extends ContextOwner {
+
+  /**
+   * Tests a binding according to the filter.
+   * @param context The context to resolve the filter in.
+   * @return <code>true</code> when the filter is matched.
+   * @throws QueryException The filter found an error during testing.
+   */
+  public boolean test(Context context) throws QueryException;
+
+  /** A filter that does no filtering. */
+  public static final Filter NULL = new Filter() {
+    public boolean test(Context context) { return true; }
+    public void setCurrentContext(Context context) { }
+    public Context getCurrentContext() { return null; }
+  };
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThan.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThan.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThan.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,40 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.ComparableExpression;
+
+
+/**
+ * The GreaterThan comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class GreaterThan extends BinaryComparisonFilter {
+
+  GreaterThan(ComparableExpression lhs, ComparableExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.greaterThan(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThanEqualTo.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThanEqualTo.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/GreaterThanEqualTo.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,40 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.ComparableExpression;
+
+
+/**
+ * The GreaterThanEqualTo comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class GreaterThanEqualTo extends BinaryComparisonFilter {
+
+  GreaterThanEqualTo(ComparableExpression lhs, ComparableExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.greaterThanEqualTo(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThan.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThan.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThan.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,40 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.ComparableExpression;
+
+
+/**
+ * The LessThan comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class LessThan extends BinaryComparisonFilter {
+
+  LessThan(ComparableExpression lhs, ComparableExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.lessThan(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThanEqualTo.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThanEqualTo.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/LessThanEqualTo.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,40 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.ComparableExpression;
+
+
+/**
+ * The LessThanEqualTo comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class LessThanEqualTo extends BinaryComparisonFilter {
+
+  LessThanEqualTo(ComparableExpression lhs, ComparableExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.lessThanEqualTo(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Not.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Not.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Not.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,46 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+
+
+/**
+ * An inversion of a test.
+ *
+ * @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>
+ */
+public class Not extends AbstractContextOwner implements Filter {
+
+  /** The filter to invert */
+  Filter operand;
+
+  /**
+   * Create an inversion of a filter
+   * @param filter The filter to invert
+   */
+  public Not(Filter operand) {
+    this.operand = operand;
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return !operand.test(context);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/NotEquals.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/NotEquals.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/NotEquals.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,46 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.value.RDFTerm;
+
+
+/**
+ * The LessThan comparison for Values.
+ *
+ * @created Mar 8, 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>
+ */
+public class NotEquals extends BinaryTestFilter {
+
+  /** The first operand */
+  protected RDFTerm lhs;
+
+  /** The second operand */
+  protected RDFTerm rhs;
+
+  NotEquals(RDFTerm lhs, RDFTerm rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return lhs.notEquals(rhs);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Or.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Or.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/Or.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,54 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter;
+
+import org.mulgara.query.QueryException;
+
+
+/**
+ * A sum of filters.
+ *
+ * @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>
+ */
+public class Or extends BinaryOperatorFilter {
+
+  /**
+   * Create a sum of two other filters.
+   * @param lhs The first operands of the sum
+   * @param rhs The first operands of the sum
+   */
+  public Or(Filter lhs, Filter rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * <code>true</code> or Exception is <code>true</code>.
+   * <code>false</code> or Exception is Exception.
+   * @see org.mulgara.query.filter.Filter#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    boolean result;
+    try {
+      result = lhs.test(context);
+    } catch (QueryException e) {
+      // true on the RHS gives true
+      if (!rhs.test(context)) return true;
+      throw e;
+    }
+    return result || rhs.test(context);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/AddOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/AddOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/AddOperation.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,43 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.arithmetic;
+
+import org.mulgara.query.filter.value.NumericExpression;
+
+
+/**
+ * Represents an add operation.
+ *
+ * @created Mar 14, 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>
+ */
+public class AddOperation extends BinaryOperation {
+
+  AddOperation(NumericExpression lhs, NumericExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * Use an operation set to perform an addition
+   * @param ops The operations to use for the current parameters
+   * @param left The first addend
+   * @param right The second addend
+   * @return The sum of left and right
+   */
+  @SuppressWarnings("unchecked")
+  Number doOperation(NumberOps ops, Number left, Number right) {
+    return ops.sum(left, right);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/BinaryOperation.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,591 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.arithmetic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.ContextOwner;
+import org.mulgara.query.filter.value.AbstractComparable;
+import org.mulgara.query.filter.value.NumericExpression;
+import org.mulgara.query.filter.value.RDFTerm;
+
+
+/**
+ * Represents a binary arithmetic operation.
+ *
+ * @created Mar 13, 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>
+ */
+public abstract class BinaryOperation extends AbstractComparable implements NumericExpression {
+
+  /** The first operand */
+  protected NumericExpression lhs;
+
+  /** The second operand */
+  protected NumericExpression rhs;
+
+  /** The owner of the context for resolving here */
+  private ContextOwner owner = null;
+
+  /**
+   * Creates an operation between two terms
+   * @param lhs The left side of the operation
+   * @param rhs The right side of the operation
+   */
+  BinaryOperation(NumericExpression lhs, NumericExpression rhs) {
+    this.lhs = lhs;
+    this.rhs = rhs;
+    lhs.setContextOwner(this);
+    rhs.setContextOwner(this);
+  }
+
+  /** @see org.mulgara.query.filter.value.ComparableExpression#getValue() */
+  public Object getValue() throws QueryException { return getNumber(); }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#equals() */
+  public boolean equals(RDFTerm v) throws QueryException { return getNumber().equals(v.getValue()); }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#isBlank() */
+  public boolean isBlank() throws QueryException { return false; }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#isIRI() */
+  public boolean isIRI() throws QueryException { return false; }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#isLiteral() */
+  public boolean isLiteral() throws QueryException { return false; }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#isURI() */
+  public boolean isURI() throws QueryException { return false; }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#notEquals() */
+  public boolean notEquals(RDFTerm v) throws QueryException { return !getNumber().equals(v.getValue()); }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#sameTerm() */
+  public boolean sameTerm(RDFTerm v) throws QueryException { return equals(v); }
+
+  /** @see org.mulgara.query.filter.Filter#test() */
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    return getNumber().doubleValue() != 0.0;
+  }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#setContextOwner(org.mulgara.query.filter.ContextOwner) */
+  public void setContextOwner(ContextOwner owner) {
+    this.owner = owner;
+  }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#getContextOwner() */
+  public ContextOwner getContextOwner() {
+    return owner;
+  }
+
+  // Not using generics in NumberOps as we can't know the types at this stage, but they are handy
+  // for defining the classes correctly
+  /**
+   * Calculate the result of this operation, returning it as a normal number.
+   * @throws QueryException The values of one of the operands could not be resolved.
+   * @see org.mulgara.query.filter.value.NumericExpression#getNumber()
+   */
+  @SuppressWarnings("unchecked")
+  public Number getNumber() throws QueryException {
+    Number left = lhs.getNumber();
+    Number right = rhs.getNumber();
+    NumberOps op = opMap.get(new ClassPair(left, right));
+    if (op == null) throw new AssertionError("Missing entry in operation map");
+    return op.product(left, right);
+  }
+
+  /**
+   * Perform the operation specific to the implementing class
+   * @param ops The operations to use for the current parameters
+   * @param left The first operand
+   * @param right The second operand
+   * @return The arithmetic result of applying the operation to the parameters
+   */
+  @SuppressWarnings("unchecked")
+  abstract Number doOperation(NumberOps ops, Number left, Number right);
+
+  /** The set of classes to be compared as floating point */
+  private static Set<Class<? extends Number>> floatUpcast = new HashSet<Class<? extends Number>>();
+  
+  /* Initialize the set of classes to be compared as floating point */
+  static {
+    floatUpcast.add(Double.class);
+    floatUpcast.add(Float.class);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.value.AbstractComparable#compare(java.lang.Object, java.lang.Object)
+   */
+  protected int compare(Object left, Object right) throws QueryException {
+    return compare((Number)left, right);
+  }
+
+  /**
+   * Compares 2 numbers of unknown type.  If they are both floating point, then use Double compare,
+   * otherwise use Long compare.
+   * @param left The first number in the comparison.
+   * @param right The second number. This cannot be assumed to be a number due to poorly formed queries.
+   * @return -1 if left<right, +1 if left>right, 0 if left==right
+   * @throws QueryException if right is a type other than {@link java.lang.Number}.
+   */
+  protected int compare(Number left, Object right) throws QueryException {
+    if (!(right instanceof Number)) throw new QueryException("Cannot compare a number to a: " + right.getClass().getSimpleName());
+    if (floatUpcast.contains(left.getClass()) || floatUpcast.contains(right.getClass())) {
+      return Double.valueOf(left.doubleValue()).compareTo(((Number)right).doubleValue());
+    }
+    return Long.valueOf(left.longValue()).compareTo(((Number)right).longValue());
+  }
+
+
+  /** Stores classes as an integrated pair for mapping pairs of Numbers to their appropriate functions */
+  static class ClassPair {
+    private Class<? extends Number> left;
+    private Class<? extends Number> right;
+
+    /**
+     * Create the pair using two classes
+     * @param left The left side of the pair
+     * @param right The right side of the pair
+     */
+    public ClassPair(Class<? extends Number> left, Class<? extends Number> right) {
+      this.left = left;
+      this.right = right;
+    }
+ 
+    /**
+     * Create the pair using two <em>instance</em> of classes
+     * @param left The left side instance for the pair
+     * @param right The right side instance for the pair
+     */
+    public ClassPair(Number left, Number right) {
+      this.left = left.getClass();
+      this.right = right.getClass();
+    }
+ 
+    /** @return The left side of the pair */
+    public Class<? extends Number> getLeft() { return left; }
+    /** @return The right side of the pair */
+    public Class<? extends Number> getRight() { return right; }
+ 
+    /** @return a hashcode determined by mising the hashcodes of the contributing classes */
+    public int hashCode() { return left.hashCode() ^ ~right.hashCode(); }
+    /** @return <code>true</code> iff o is a class pair containing equal elements */
+    public boolean equals(Object o) {
+      if (o == null || (!(o instanceof ClassPair))) return false;
+      return left.equals(((ClassPair)o).left) && right.equals(((ClassPair)o).right);
+    }
+  }
+
+  /** Defines a binary function that takes two numbers and returns a new one */
+  interface NumberOps<LT extends Number,RT extends Number> {
+    /**
+     * Get a ClassPair that represents this operation
+     * @return a new ClassPair for this operation type
+     */
+    public ClassPair getClassPair();
+    /**
+     * Perform a multiplication on arguments of the specified types.
+     * @param left The first multiplicands
+     * @param right The second multiplicands
+     * @return The product as a number of the type defined in this class.
+     */
+    public Number product(LT left, RT right);
+    /**
+     * Perform a sum on arguments of the specified types.
+     * @param left The first addend
+     * @param right The second addend
+     * @return The sum as a number of the type defined in this class.
+     */
+    public Number sum(LT left, RT right);
+    /**
+     * Perform a subtraction on arguments of the specified types.
+     * @param left The minuend
+     * @param right The subtrahend
+     * @return The difference as a number of the type defined in this class.
+     */
+    public Number subtract(LT left, RT right);
+    /**
+     * Perform a multiplication on arguments of the specified types.
+     * @param left The dividend
+     * @param right The divisor
+     * @return The quotient as a number of the type defined in this class.
+     */
+    public Number divide(LT left, RT right);
+  }
+
+  /** A map of types to the functions that multiply them with correct type promotions */
+  protected static Map<ClassPair,NumberOps<? extends Number,? extends Number>> opMap = new HashMap<ClassPair,NumberOps<? extends Number,? extends Number>>();
+
+  /** A utility to add a number function to the promotion map */
+  private static void addType(NumberOps<?,?> nf) { opMap.put(nf.getClassPair(), nf); }
+
+  // The following population of the operation map was generated with this ruby script:
+  /*
+   * types = [ "Double", "Float", "Long", "Integer", "Short", "Byte" ]
+   * puts "  static {"
+   * types.each do |l|
+   *   types.each do |r|
+   *     puts "    addType(new #{l[0].chr}#{r[0].chr}());"
+   *   end
+   * end
+   * puts "  }"
+   * puts
+   * types.each do |l|
+   *   types.each do |r|
+   *     puts "  private static class #{l[0].chr}#{r[0].chr} implements NumberOps<#{l},#{r}> {"
+   *     puts "    public ClassPair getClassPair() { return new ClassPair(#{l}.class, #{r}.class); }"
+   *     puts "    public Number product(#{l} left, #{r} right) { return left * right; }"
+   *     puts "    public Number sum(#{l} left, #{r} right) { return left + right; }"
+   *     puts "    public Number subtract(#{l} left, #{r} right) { return left - right; }"
+   *     puts "    public Number divide(#{l} left, #{r} right) { return left / right; }"
+   *     puts "  }"
+   *     puts
+   *   end
+   * end
+   */  
+
+  static {
+    addType(new DD());
+    addType(new DF());
+    addType(new DL());
+    addType(new DI());
+    addType(new DS());
+    addType(new DB());
+    addType(new FD());
+    addType(new FF());
+    addType(new FL());
+    addType(new FI());
+    addType(new FS());
+    addType(new FB());
+    addType(new LD());
+    addType(new LF());
+    addType(new LL());
+    addType(new LI());
+    addType(new LS());
+    addType(new LB());
+    addType(new ID());
+    addType(new IF());
+    addType(new IL());
+    addType(new II());
+    addType(new IS());
+    addType(new IB());
+    addType(new SD());
+    addType(new SF());
+    addType(new SL());
+    addType(new SI());
+    addType(new SS());
+    addType(new SB());
+    addType(new BD());
+    addType(new BF());
+    addType(new BL());
+    addType(new BI());
+    addType(new BS());
+    addType(new BB());
+  }
+
+  private static class DD implements NumberOps<Double,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Double.class); }
+    public Number product(Double left, Double right) { return left * right; }
+    public Number sum(Double left, Double right) { return left + right; }
+    public Number subtract(Double left, Double right) { return left - right; }
+    public Number divide(Double left, Double right) { return left / right; }
+  }
+
+  private static class DF implements NumberOps<Double,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Float.class); }
+    public Number product(Double left, Float right) { return left * right; }
+    public Number sum(Double left, Float right) { return left + right; }
+    public Number subtract(Double left, Float right) { return left - right; }
+    public Number divide(Double left, Float right) { return left / right; }
+  }
+
+  private static class DL implements NumberOps<Double,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Long.class); }
+    public Number product(Double left, Long right) { return left * right; }
+    public Number sum(Double left, Long right) { return left + right; }
+    public Number subtract(Double left, Long right) { return left - right; }
+    public Number divide(Double left, Long right) { return left / right; }
+  }
+
+  private static class DI implements NumberOps<Double,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Integer.class); }
+    public Number product(Double left, Integer right) { return left * right; }
+    public Number sum(Double left, Integer right) { return left + right; }
+    public Number subtract(Double left, Integer right) { return left - right; }
+    public Number divide(Double left, Integer right) { return left / right; }
+  }
+
+  private static class DS implements NumberOps<Double,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Short.class); }
+    public Number product(Double left, Short right) { return left * right; }
+    public Number sum(Double left, Short right) { return left + right; }
+    public Number subtract(Double left, Short right) { return left - right; }
+    public Number divide(Double left, Short right) { return left / right; }
+  }
+
+  private static class DB implements NumberOps<Double,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Double.class, Byte.class); }
+    public Number product(Double left, Byte right) { return left * right; }
+    public Number sum(Double left, Byte right) { return left + right; }
+    public Number subtract(Double left, Byte right) { return left - right; }
+    public Number divide(Double left, Byte right) { return left / right; }
+  }
+
+  private static class FD implements NumberOps<Float,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Double.class); }
+    public Number product(Float left, Double right) { return left * right; }
+    public Number sum(Float left, Double right) { return left + right; }
+    public Number subtract(Float left, Double right) { return left - right; }
+    public Number divide(Float left, Double right) { return left / right; }
+  }
+
+  private static class FF implements NumberOps<Float,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Float.class); }
+    public Number product(Float left, Float right) { return left * right; }
+    public Number sum(Float left, Float right) { return left + right; }
+    public Number subtract(Float left, Float right) { return left - right; }
+    public Number divide(Float left, Float right) { return left / right; }
+  }
+
+  private static class FL implements NumberOps<Float,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Long.class); }
+    public Number product(Float left, Long right) { return left * right; }
+    public Number sum(Float left, Long right) { return left + right; }
+    public Number subtract(Float left, Long right) { return left - right; }
+    public Number divide(Float left, Long right) { return left / right; }
+  }
+
+  private static class FI implements NumberOps<Float,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Integer.class); }
+    public Number product(Float left, Integer right) { return left * right; }
+    public Number sum(Float left, Integer right) { return left + right; }
+    public Number subtract(Float left, Integer right) { return left - right; }
+    public Number divide(Float left, Integer right) { return left / right; }
+  }
+
+  private static class FS implements NumberOps<Float,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Short.class); }
+    public Number product(Float left, Short right) { return left * right; }
+    public Number sum(Float left, Short right) { return left + right; }
+    public Number subtract(Float left, Short right) { return left - right; }
+    public Number divide(Float left, Short right) { return left / right; }
+  }
+
+  private static class FB implements NumberOps<Float,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Float.class, Byte.class); }
+    public Number product(Float left, Byte right) { return left * right; }
+    public Number sum(Float left, Byte right) { return left + right; }
+    public Number subtract(Float left, Byte right) { return left - right; }
+    public Number divide(Float left, Byte right) { return left / right; }
+  }
+
+  private static class LD implements NumberOps<Long,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Double.class); }
+    public Number product(Long left, Double right) { return left * right; }
+    public Number sum(Long left, Double right) { return left + right; }
+    public Number subtract(Long left, Double right) { return left - right; }
+    public Number divide(Long left, Double right) { return left / right; }
+  }
+
+  private static class LF implements NumberOps<Long,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Float.class); }
+    public Number product(Long left, Float right) { return left * right; }
+    public Number sum(Long left, Float right) { return left + right; }
+    public Number subtract(Long left, Float right) { return left - right; }
+    public Number divide(Long left, Float right) { return left / right; }
+  }
+
+  private static class LL implements NumberOps<Long,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Long.class); }
+    public Number product(Long left, Long right) { return left * right; }
+    public Number sum(Long left, Long right) { return left + right; }
+    public Number subtract(Long left, Long right) { return left - right; }
+    public Number divide(Long left, Long right) { return left / right; }
+  }
+
+  private static class LI implements NumberOps<Long,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Integer.class); }
+    public Number product(Long left, Integer right) { return left * right; }
+    public Number sum(Long left, Integer right) { return left + right; }
+    public Number subtract(Long left, Integer right) { return left - right; }
+    public Number divide(Long left, Integer right) { return left / right; }
+  }
+
+  private static class LS implements NumberOps<Long,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Short.class); }
+    public Number product(Long left, Short right) { return left * right; }
+    public Number sum(Long left, Short right) { return left + right; }
+    public Number subtract(Long left, Short right) { return left - right; }
+    public Number divide(Long left, Short right) { return left / right; }
+  }
+
+  private static class LB implements NumberOps<Long,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Long.class, Byte.class); }
+    public Number product(Long left, Byte right) { return left * right; }
+    public Number sum(Long left, Byte right) { return left + right; }
+    public Number subtract(Long left, Byte right) { return left - right; }
+    public Number divide(Long left, Byte right) { return left / right; }
+  }
+
+  private static class ID implements NumberOps<Integer,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Double.class); }
+    public Number product(Integer left, Double right) { return left * right; }
+    public Number sum(Integer left, Double right) { return left + right; }
+    public Number subtract(Integer left, Double right) { return left - right; }
+    public Number divide(Integer left, Double right) { return left / right; }
+  }
+
+  private static class IF implements NumberOps<Integer,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Float.class); }
+    public Number product(Integer left, Float right) { return left * right; }
+    public Number sum(Integer left, Float right) { return left + right; }
+    public Number subtract(Integer left, Float right) { return left - right; }
+    public Number divide(Integer left, Float right) { return left / right; }
+  }
+
+  private static class IL implements NumberOps<Integer,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Long.class); }
+    public Number product(Integer left, Long right) { return left * right; }
+    public Number sum(Integer left, Long right) { return left + right; }
+    public Number subtract(Integer left, Long right) { return left - right; }
+    public Number divide(Integer left, Long right) { return left / right; }
+  }
+
+  private static class II implements NumberOps<Integer,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Integer.class); }
+    public Number product(Integer left, Integer right) { return left * right; }
+    public Number sum(Integer left, Integer right) { return left + right; }
+    public Number subtract(Integer left, Integer right) { return left - right; }
+    public Number divide(Integer left, Integer right) { return left / right; }
+  }
+
+  private static class IS implements NumberOps<Integer,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Short.class); }
+    public Number product(Integer left, Short right) { return left * right; }
+    public Number sum(Integer left, Short right) { return left + right; }
+    public Number subtract(Integer left, Short right) { return left - right; }
+    public Number divide(Integer left, Short right) { return left / right; }
+  }
+
+  private static class IB implements NumberOps<Integer,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Integer.class, Byte.class); }
+    public Number product(Integer left, Byte right) { return left * right; }
+    public Number sum(Integer left, Byte right) { return left + right; }
+    public Number subtract(Integer left, Byte right) { return left - right; }
+    public Number divide(Integer left, Byte right) { return left / right; }
+  }
+
+  private static class SD implements NumberOps<Short,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Double.class); }
+    public Number product(Short left, Double right) { return left * right; }
+    public Number sum(Short left, Double right) { return left + right; }
+    public Number subtract(Short left, Double right) { return left - right; }
+    public Number divide(Short left, Double right) { return left / right; }
+  }
+
+  private static class SF implements NumberOps<Short,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Float.class); }
+    public Number product(Short left, Float right) { return left * right; }
+    public Number sum(Short left, Float right) { return left + right; }
+    public Number subtract(Short left, Float right) { return left - right; }
+    public Number divide(Short left, Float right) { return left / right; }
+  }
+
+  private static class SL implements NumberOps<Short,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Long.class); }
+    public Number product(Short left, Long right) { return left * right; }
+    public Number sum(Short left, Long right) { return left + right; }
+    public Number subtract(Short left, Long right) { return left - right; }
+    public Number divide(Short left, Long right) { return left / right; }
+  }
+
+  private static class SI implements NumberOps<Short,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Integer.class); }
+    public Number product(Short left, Integer right) { return left * right; }
+    public Number sum(Short left, Integer right) { return left + right; }
+    public Number subtract(Short left, Integer right) { return left - right; }
+    public Number divide(Short left, Integer right) { return left / right; }
+  }
+
+  private static class SS implements NumberOps<Short,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Short.class); }
+    public Number product(Short left, Short right) { return left * right; }
+    public Number sum(Short left, Short right) { return left + right; }
+    public Number subtract(Short left, Short right) { return left - right; }
+    public Number divide(Short left, Short right) { return left / right; }
+  }
+
+  private static class SB implements NumberOps<Short,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Short.class, Byte.class); }
+    public Number product(Short left, Byte right) { return left * right; }
+    public Number sum(Short left, Byte right) { return left + right; }
+    public Number subtract(Short left, Byte right) { return left - right; }
+    public Number divide(Short left, Byte right) { return left / right; }
+  }
+
+  private static class BD implements NumberOps<Byte,Double> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Double.class); }
+    public Number product(Byte left, Double right) { return left * right; }
+    public Number sum(Byte left, Double right) { return left + right; }
+    public Number subtract(Byte left, Double right) { return left - right; }
+    public Number divide(Byte left, Double right) { return left / right; }
+  }
+
+  private static class BF implements NumberOps<Byte,Float> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Float.class); }
+    public Number product(Byte left, Float right) { return left * right; }
+    public Number sum(Byte left, Float right) { return left + right; }
+    public Number subtract(Byte left, Float right) { return left - right; }
+    public Number divide(Byte left, Float right) { return left / right; }
+  }
+
+  private static class BL implements NumberOps<Byte,Long> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Long.class); }
+    public Number product(Byte left, Long right) { return left * right; }
+    public Number sum(Byte left, Long right) { return left + right; }
+    public Number subtract(Byte left, Long right) { return left - right; }
+    public Number divide(Byte left, Long right) { return left / right; }
+  }
+
+  private static class BI implements NumberOps<Byte,Integer> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Integer.class); }
+    public Number product(Byte left, Integer right) { return left * right; }
+    public Number sum(Byte left, Integer right) { return left + right; }
+    public Number subtract(Byte left, Integer right) { return left - right; }
+    public Number divide(Byte left, Integer right) { return left / right; }
+  }
+
+  private static class BS implements NumberOps<Byte,Short> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Short.class); }
+    public Number product(Byte left, Short right) { return left * right; }
+    public Number sum(Byte left, Short right) { return left + right; }
+    public Number subtract(Byte left, Short right) { return left - right; }
+    public Number divide(Byte left, Short right) { return left / right; }
+  }
+
+  private static class BB implements NumberOps<Byte,Byte> {
+    public ClassPair getClassPair() { return new ClassPair(Byte.class, Byte.class); }
+    public Number product(Byte left, Byte right) { return left * right; }
+    public Number sum(Byte left, Byte right) { return left + right; }
+    public Number subtract(Byte left, Byte right) { return left - right; }
+    public Number divide(Byte left, Byte right) { return left / right; }
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/DivideOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/DivideOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/DivideOperation.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,43 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.arithmetic;
+
+import org.mulgara.query.filter.value.NumericExpression;
+
+
+/**
+ * Represents a division operation.
+ *
+ * @created Mar 14, 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>
+ */
+public class DivideOperation extends BinaryOperation {
+
+  DivideOperation(NumericExpression lhs, NumericExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * Use an operation set to perform a division
+   * @param ops The operations to use for the current parameters
+   * @param left The dividend
+   * @param right The divisor
+   * @return The quotient of dividing right into left
+   */
+  @SuppressWarnings("unchecked")
+  Number doOperation(NumberOps ops, Number left, Number right) {
+    return ops.divide(left, right);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MinusOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MinusOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MinusOperation.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,43 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.arithmetic;
+
+import org.mulgara.query.filter.value.NumericExpression;
+
+
+/**
+ * Represents a subtraction operation.
+ *
+ * @created Mar 14, 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>
+ */
+public class MinusOperation extends BinaryOperation {
+
+  MinusOperation(NumericExpression lhs, NumericExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * Use an operation set to perform a subtraction
+   * @param ops The operations to use for the current parameters
+   * @param left The minuend
+   * @param right The subtrahend
+   * @return The difference between left and right
+   */
+  @SuppressWarnings("unchecked")
+  Number doOperation(NumberOps ops, Number left, Number right) {
+    return ops.subtract(left, right);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MultiplyOperation.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MultiplyOperation.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/arithmetic/MultiplyOperation.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,43 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.arithmetic;
+
+import org.mulgara.query.filter.value.NumericExpression;
+
+
+/**
+ * Represents a multiplication operation.
+ *
+ * @created Mar 13, 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>
+ */
+public class MultiplyOperation extends BinaryOperation {
+
+  MultiplyOperation(NumericExpression lhs, NumericExpression rhs) {
+    super(lhs, rhs);
+  }
+
+  /**
+   * Use an operation set to perform a multiplication
+   * @param ops The operations to use for the current parameters
+   * @param left The first operand
+   * @param right The second operand
+   * @return The product of left and right
+   */
+  @SuppressWarnings("unchecked")
+  Number doOperation(NumberOps ops, Number left, Number right) {
+    return ops.product(left, right);
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparable.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparable.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparable.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,37 @@
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.AbstractContextOwner;
+
+public abstract class AbstractComparable extends AbstractContextOwner implements ComparableExpression {
+
+  /** {@inheritDoc} */
+  public boolean lessThan(ComparableExpression v) throws QueryException {
+    return compare(getValue(), v.getValue()) < 0;
+  }
+
+  /** {@inheritDoc} */
+  public boolean greaterThan(ComparableExpression v) throws QueryException {
+    return compare(getValue(), v.getValue()) > 0;
+  }
+
+  /** {@inheritDoc} */
+  public boolean lessThanEqualTo(ComparableExpression v) throws QueryException {
+    return !greaterThan(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean greaterThanEqualTo(ComparableExpression v) throws QueryException {
+    return !lessThan(v);
+  }
+
+  /**
+   * Compares elements of the type handled by the implementing class.
+   * @param left The LHS of the comparison
+   * @param right The RHS of the comparison
+   * @return -1 if left<right, +1 if left>right, 0 if left==right
+   * @throws QueryException If getting the values for the comparison is invalid.
+   */
+  protected abstract int compare(Object left, Object right) throws QueryException;
+
+}
\ No newline at end of file

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparableLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparableLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/AbstractComparableLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,194 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.mulgara.query.QueryException;
+
+
+/**
+ * Basic common representation of literals.
+ *
+ * @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>
+ */
+public abstract class AbstractComparableLiteral extends AbstractComparable implements ValueLiteral {
+
+  /** The wrapped value */
+  Object value;
+
+  /**
+   * Creates a value
+   * @param value The value to use
+   */
+  public AbstractComparableLiteral(Object value) {
+    this.value = value;
+  }
+
+  /**
+   * Returns the wrapped data for this value.
+   * @return The wrapped data.
+   */
+  public Object getValue() {
+    return value;
+  }
+
+  /**
+   * {@inheritDoc}
+   * Override this if a tagged string.
+   */
+  public SimpleLiteral getLang() throws QueryException {
+    return SimpleLiteral.EMPTY;
+  }
+
+  /** {@inheritDoc} */
+  public boolean isBlank() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isIRI() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isURI() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isLiteral() { return true; }
+
+  /** {@inheritDoc} */
+  public boolean sameTerm(RDFTerm v) {
+    try {
+      return value.equals(v.getValue());
+    } catch (QueryException qe) {
+      return false;
+    }
+  }
+
+
+  /** {@inheritDoc} */
+  public boolean equals(RDFTerm v) throws QueryException {
+    return value.equals(v.getValue());
+  }
+  
+  /** {@inheritDoc} */
+  public boolean notEquals(RDFTerm v) throws QueryException {
+    return !value.equals(v.getValue());
+  }
+
+  /**
+   * Type-based switching to handle comparison of things that may not be directly comparable.
+   * @param left The first thing to compare
+   * @param right The second thing to compare
+   * @return -1 if left<right, +1 if left>right, and 0 if left=right
+   * @throws QueryException The data could not be compared.
+   */
+  protected int compare(Object left, Object right) throws QueryException {
+    DataCompare cmpFn = typeMap.get(left.getClass());
+    if (cmpFn == null) throw new QueryException("Cannot compare a " + left.getClass() + " to a " + right.getClass());
+    return cmpFn.compare(left, right);
+  }
+
+  /** Map of types to the functions used to compare those types */
+  protected static Map<Class<? extends Comparable<?>>,DataCompare> typeMap = new HashMap<Class<? extends Comparable<?>>,DataCompare>();
+
+  static {
+    typeMap.put(String.class, new StringCompare());
+    typeMap.put(Date.class, new DateCompare());
+    typeMap.put(Boolean.class, new BooleanCompare());
+    typeMap.put(Float.class, new FloatCompare());
+    typeMap.put(Double.class, new DoubleCompare());
+    typeMap.put(Long.class, new DecimalCompare());
+    typeMap.put(Integer.class, new DecimalCompare());
+    typeMap.put(Short.class, new DecimalCompare());
+    typeMap.put(Byte.class, new DecimalCompare());
+  }
+
+  /** Defines a function for comparing objects of arbitrary type */
+  protected interface DataCompare {
+    /**
+     * Comparison method used for any kind of type that might be compared.
+     * @param left The left hand side of the comparison. This must be of the correct type for the class.
+     * @param right The right hand side of the comparison. This should be tested for type compatibility with the left parameter
+     * @return -1 if left<right, 1 if left>right, and 0 if left==right
+     * @throws QueryException Due to an error in resolution of the values to be compared
+     */
+    int compare(Object left, Object right) throws QueryException;
+    /**
+     * Creates a new ComparableLiteral compatible with this comparison type, from given data
+     * @param data The data in the correct native {@link java.lang.Class} to be converted.
+     * @return A new literal containing the data.
+     */
+    ComparableExpression newLiteral(Object data);
+  }
+
+  /** Implements string comparisons */
+  private static class StringCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      if (!(right instanceof String)) throw new QueryException("Cannot compare a String to a: " + right.getClass());
+      return ((String)left).compareTo((String)right);
+    }
+    public ComparableExpression newLiteral(Object data) { return new SimpleLiteral((String)data); }
+  }
+
+  /** Implements string comparisons */
+  private static class DateCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      if (!(right instanceof Date)) throw new QueryException("Cannot compare a Date to a: " + right.getClass());
+      return ((Date)left).compareTo((Date)right);
+    }
+    public ComparableExpression newLiteral(Object data) { return new DateTime((Date)data); }
+  }
+
+  /** Implements boolean comparisons */
+  private static class BooleanCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      if (!(right instanceof Boolean)) throw new QueryException("Cannot compare a boolean to a: " + right.getClass());
+      return ((Boolean)left).compareTo((Boolean)right);
+    }
+    public ComparableExpression newLiteral(Object data) { return new Bool((Boolean)data); }
+  }
+
+  /** Implements floating point comparisons, or double comparisons if the rhs parameter is a double */
+  private static class FloatCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      Float fleft = (Float)left;
+      if (!(right instanceof Number)) throw new QueryException("Cannot compare a float to a: " + right.getClass());
+      // if right has more precision, then promote lfloat, and compare the other way around
+      if (right instanceof Double) return -((Double)right).compareTo(fleft.doubleValue());
+      return fleft.compareTo(((Number)right).floatValue());
+    }
+    public ComparableExpression newLiteral(Object data) { return new NumericLiteral((Float)data); }
+  }
+
+  /** Implements double precision floating point comparisons */
+  private static class DoubleCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      if (!(right instanceof Number)) throw new QueryException("Cannot compare a double to a: " + right.getClass());
+      return ((Double)left).compareTo(((Number)right).doubleValue());
+    }
+    public ComparableExpression newLiteral(Object data) { return new NumericLiteral((Double)data); }
+  }
+
+  /** Implements integer comparisons */
+  private static class DecimalCompare implements DataCompare {
+    public int compare(Object left, Object right) throws QueryException {
+      if (!(right instanceof Number)) throw new QueryException("Cannot compare a decimal number to a: " + right.getClass());
+      Long lleft = ((Number)left).longValue();
+      return lleft.compareTo(((Number)right).longValue());
+    }
+    public ComparableExpression newLiteral(Object data) { return new NumericLiteral((Number)data); }
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/BlankNodeValue.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,77 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.jrdf.graph.BlankNode;
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.ContextOwner;
+
+
+/**
+ * A blank node.
+ *
+ * @created Mar 12, 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>
+ */
+public class BlankNodeValue implements RDFTerm {
+
+  /** The wrapped blank node */
+  private final BlankNode node;
+
+  /**
+   * Creates the value to wrap the string
+   * @param s The string to wrap
+   */
+  public BlankNodeValue(BlankNode node) {
+    this.node = node;
+  }
+
+  /** {@inheritDoc} */
+  public BlankNode getValue() {
+    return node;
+  }
+
+  /** {@inheritDoc} */
+  public boolean equals(RDFTerm v) throws QueryException {
+    return v instanceof BlankNodeValue && node.equals(((BlankNodeValue)v).node);
+  }
+
+  /** {@inheritDoc} */
+  public boolean notEquals(RDFTerm v) throws QueryException {
+    return !(v instanceof BlankNodeValue) || !node.equals(((BlankNodeValue)v).node);
+  }
+
+  /** {@inheritDoc} */
+  public boolean sameTerm(RDFTerm v) {
+    return v instanceof BlankNodeValue && node.equals(((BlankNodeValue)v).node);
+  }
+
+  /** {@inheritDoc} */
+  public boolean isBlank() { return true; }
+
+  /** {@inheritDoc} */
+  public boolean isIRI() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isLiteral() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isURI() { return false; }
+
+  /** This value does not need a context */
+  public ContextOwner getContextOwner() {  return null; }
+
+  /** This value does not need a context */
+  public void setContextOwner(ContextOwner owner) { }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Bool.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Bool.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Bool.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,43 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.net.URI;
+
+import org.mulgara.query.QueryException;
+
+/**
+ * A boolean value.
+ *
+ * @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>
+ */
+public class Bool extends TypedLiteral {
+
+  /** xsd:boolean */
+  public static final URI TYPE = URI.create(XSD_NS + "boolean");
+
+  /**
+   * Creates the value to wrap the boolean
+   * @param n The boolean to wrap
+   */
+  public Bool(Boolean b) {
+    super(b, TYPE);
+  }
+
+  /** {@inheritDoc} */
+  public boolean test() throws QueryException {
+    return (Boolean)value;
+  }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ComparableExpression.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ComparableExpression.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ComparableExpression.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,70 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.Filter;
+
+
+/**
+ * Represents expressions that can appear in a comparison expression, used by filters
+ *
+ * @created Mar 10, 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>
+ */
+public interface ComparableExpression extends RDFTerm, Filter {
+
+  /**
+   * Returns the data represented by this expression.
+   * @return The represented data.
+   * @throws QueryException Resolving the data for this value leads to an error.
+   */
+  public Object getValue() throws QueryException;
+
+  /**
+   * A value based magnitude test.
+   * @param v The object to compare to
+   * @return <code>true</code> iff v has a greater value than the current object.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean lessThan(ComparableExpression v) throws QueryException;
+
+  /**
+   * A value based magnitude test.
+   * @param v The object to compare to
+   * @return <code>true</code> iff v has a lesser value than the current object.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean greaterThan(ComparableExpression v) throws QueryException;
+  
+  /**
+   * A value based magnitude test.
+   * @param v The object to compare to
+   * @return <code>false</code> iff v has a lesser value than the current object.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean lessThanEqualTo(ComparableExpression v) throws QueryException;
+  
+  /**
+   * A value based magnitude test.
+   * @param v The object to compare to
+   * @return <code>false</code> iff v has a greater value than the current object.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean greaterThanEqualTo(ComparableExpression v) throws QueryException;
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/DateTime.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/DateTime.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/DateTime.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,63 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.net.URI;
+import java.util.Date;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * A date value.
+ *
+ * @created Mar 8, 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>
+ */
+public class DateTime extends TypedLiteral {
+
+  /** xsd:dateTime */
+  public static final URI TYPE = URI.create(XSD_NS + "dateTime");
+
+  /** Singleton reference to the datatype factory for date parsers */
+  private static DatatypeFactory factory;
+  static {
+    try {
+      factory = DatatypeFactory.newInstance();
+    } catch (DatatypeConfigurationException e) {
+      throw new RuntimeException("Unable to initialize XML date parser");
+    }
+  }
+
+  /**
+   * Creates the date value
+   * @param value The date to wrap
+   */
+  public DateTime(java.util.Date value) {
+    super(value, TYPE);
+  }
+
+  /**
+   * Converts a lexical representation of an XSD date into a Date object.
+   * Note necessarily the most efficient way to handle this, but it has the
+   * advantage of simplicity and of using standard Java libraries.
+   * @param lexical The lexical form of the date.
+   * @return A {@link java.util.Date} for the represented date.
+   */
+  public static Date parseDate(String lexical) {
+    XMLGregorianCalendar cal = factory.newXMLGregorianCalendar(lexical);
+    return cal.toGregorianCalendar().getTime();
+  }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/IRI.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/IRI.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/IRI.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,80 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.net.URI;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.ContextOwner;
+
+
+/**
+ * <p>An IRI value.</p>
+ * <p>OK, so we're cheating.  This is a URI.</p>
+ *
+ * @created Mar 12, 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>
+ */
+public class IRI implements RDFTerm {
+
+  /** The URI held by this object */
+  private final URI value;
+
+  /**
+   * Creates the value to wrap the string
+   * @param s The string to wrap
+   */
+  public IRI(URI u) {
+    value = u;
+  }
+
+  /** {@inheritDoc} */
+  public URI getValue() {
+    return value;
+  }
+
+  /** {@inheritDoc} */
+  public boolean equals(RDFTerm v) throws QueryException {
+    return v.isIRI() && value.equals(((IRI)v).getValue());
+  }
+
+  /** {@inheritDoc} */
+  public boolean notEquals(RDFTerm v) throws QueryException {
+    return !v.isIRI() || !value.equals(((IRI)v).getValue());
+  }
+
+  /** {@inheritDoc} */
+  public boolean isBlank() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean isIRI() { return true; }
+
+  /** {@inheritDoc} */
+  public boolean isURI() { return true; }
+
+  /** {@inheritDoc} */
+  public boolean isLiteral() { return false; }
+
+  /** {@inheritDoc} */
+  public boolean sameTerm(RDFTerm v) {
+    return v instanceof IRI && value.equals(((IRI)v).getValue());
+  }
+
+  /** This value does not need a context */
+  public ContextOwner getContextOwner() {  return null; }
+
+  /** This value does not need a context */
+  public void setContextOwner(ContextOwner owner) { }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericExpression.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericExpression.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericExpression.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,31 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+
+/**
+ * A numeric expression.
+ *
+ * @created Mar 13, 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>
+ */
+public interface NumericExpression extends ComparableExpression {
+
+  /**
+   * Retrieves a numeric value for this expression.
+   * @return A value in one of the subtypes of {@link java.lang.Number}
+   */
+  Number getNumber() throws QueryException;
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/NumericLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,54 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A numeric value.  Expect that this will be extended into Double, Integer, Long, etc.
+ *
+ * @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>
+ */
+public class NumericLiteral extends TypedLiteral implements NumericExpression {
+
+  /**
+   * Creates the value to wrap the number
+   * @param n The number to wrap
+   */
+  public NumericLiteral(Number n) {
+    super(n, typeMap.get(n));
+  }
+
+  /**
+   * @see org.mulgara.query.filter.value.NumericExpression#getNumber()
+   */
+  public Number getNumber() {
+    return (Number)value;
+  }
+
+  /** A mapping of numeric types to their URIs */
+  private static final Map<Class<? extends Number>,URI> typeMap = new HashMap<Class<? extends Number>,URI>();
+  
+  static {
+    typeMap.put(Float.class, URI.create(XSD_NS + "float"));
+    typeMap.put(Double.class, URI.create(XSD_NS + "double"));
+    typeMap.put(Long.class, URI.create(XSD_NS + "long"));
+    typeMap.put(Integer.class, URI.create(XSD_NS + "int"));
+    typeMap.put(Short.class, URI.create(XSD_NS + "short"));
+    typeMap.put(Byte.class, URI.create(XSD_NS + "byte"));
+  }
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/RDFTerm.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/RDFTerm.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/RDFTerm.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,92 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.ContextOwner;
+
+
+/**
+ * Represents data that can appear in an expression, used by filters
+ *
+ * @created Mar 10, 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>
+ */
+public interface RDFTerm {
+
+  /**
+   * Returns the data represented by this expression.
+   * @return The represented data.
+   * @throws QueryException Resolving the data for this value leads to an error.
+   */
+  public Object getValue() 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.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean equals(RDFTerm v) throws QueryException;
+
+  /**
+   * A value based inequality test.
+   * @param v The object to compare to
+   * @return <code>false</code> iff v has the same value as the current object.
+   * @throws QueryException Resolving the data for this value leads to an error,
+   *                        or the types are incompatible.
+   */
+  public boolean notEquals(RDFTerm v) throws QueryException;
+
+  /**
+   * Tests if this object is a URI or IRI.
+   * @return <code>true</code> if this object is an IRI.
+   */
+  public boolean isIRI() throws QueryException;
+  
+  /** @see #isIRI() */
+  public boolean isURI() throws QueryException;
+
+  /**
+   * Tests if this value is a blank node
+   * @return <code>true</code> if this expression is a blank node
+   */
+  public boolean isBlank() throws QueryException;
+
+  /**
+   * Tests if this value is a literal
+   * @return <code>true</code> if this expression is a literal
+   */
+  public boolean isLiteral() throws QueryException;
+
+  /**
+   * Tests if this is the same term as another expression
+   * @param v The expression to test against
+   * @return <code>true</code> if the terms are the same
+   */
+  public boolean sameTerm(RDFTerm v) throws QueryException;
+  
+  /**
+   * Sets the object that contains the current context to work in.
+   * @param owner The object that owns this context.
+   */
+  public void setContextOwner(ContextOwner owner);
+  
+  /**
+   * Gets the object that contains the current context to work in.
+   * @return The object that owns this context.
+   */
+  public ContextOwner getContextOwner();
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/SimpleLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,78 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.ContextOwner;
+
+
+/**
+ * A string value.
+ *
+ * @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>
+ */
+public class SimpleLiteral extends AbstractComparableLiteral {
+
+  /** An empty simple literal */
+  public static final SimpleLiteral EMPTY = new SimpleLiteral("");
+
+  private SimpleLiteral lang = EMPTY;
+
+  /**
+   * Creates the value to wrap the string
+   * @param s The string to wrap
+   */
+  public SimpleLiteral(String s) {
+    super(s);
+  }
+
+  /**
+   * Creates the value to wrap the string
+   * @param s The string to wrap
+   */
+  public SimpleLiteral(String s, String l) {
+    super(s);
+    lang = new SimpleLiteral(l);
+  }
+
+  /**
+   * @see org.mulgara.query.filter.value.AbstractComparableLiteral#getLang()
+   */
+  public SimpleLiteral getLang() {
+    return lang;
+  }
+
+  /**
+   * @see org.mulgara.query.filter.value.AbstractComparableLiteral#getLang()
+   */
+  public String getLexical() {
+    return value == null ? (String)EMPTY.value : (String)value;
+  }
+
+  /**
+   * @see org.mulgara.query.filter.value.ComparableExpression#test()
+   */
+  public boolean test(Context context) throws QueryException {
+    return value != null && ((String)value).length() != 0;
+  }
+
+  /** This value does not need a context */
+  public ContextOwner getContextOwner() {  return null; }
+
+  /** This value does not need a context */
+  public void setContextOwner(ContextOwner owner) { }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/TypedLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,322 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.ContextOwner;
+
+
+/**
+ * A literal with a URI type and a value.
+ *
+ * @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>
+ */
+public class TypedLiteral extends AbstractComparableLiteral {
+
+  /** The type URI for this literal */
+  private URI type;
+  
+  /** The lexical representation for this literal */
+  private String lexical;
+
+  /** The namespace for all XSD types */
+  static final String XSD_NS = "http://www.w3.org/2001/XMLSchema#";
+
+  /**
+   * Creates the value to wrap the string
+   * @param value The data to wrap
+   * @param type The type of the literal
+   */
+  public TypedLiteral(Object value, URI type) {
+    super(value);
+    lexical = value.toString();  // lexical == value if value instanceof String
+    this.type = type;
+  }
+
+  /**
+   * A factory for typed literals.
+   * @param value The literal data in its lexical form. This means it's a String, and can even be invalid
+   * @param type The type of the literal. May be null.
+   * @param lang The language code of the literal. May be null.
+   */
+  public static ComparableExpression newTypedLiteral(String value, URI type, String lang) {
+    if (type != null) {
+      // get the info registered for this type URI
+      TypeInfo info = infoMap.get(type);
+      if (info != null) {
+        try {
+          return newTypedLiteral(info.toData(value));
+        } catch (QueryException e) {  // should not happen
+          throw new AssertionError("Internal type maps are inconsistent for: " + info.getClass().getSimpleName());
+        }
+      }
+      // no type info for the given URI, just pass through as a general typed literal
+      return new TypedLiteral(value, type);
+    }
+    // no type info provided, so it's a simple string
+    if (lang == null || lang.length() == 0) return new SimpleLiteral(value);
+    return new SimpleLiteral(value, lang);
+  }
+
+  /**
+   * A factory for typed literals from raw Java types. This is most likely to come
+   * from literal numbers parsed by a SPARQL parser.
+   * @param value The data as an object. May be a String, or some kind of {@link java.lang.Number}
+   */
+  public static ComparableExpression newTypedLiteral(Object value) throws QueryException {
+    DataCompare dc = typeMap.get(value.getClass());
+    if (dc == null) throw new QueryException("Unrecognized data type: " + value.getClass().getSimpleName());
+    return dc.newLiteral(value);
+  }
+
+  /**
+   * Gets the type of this literal
+   * @return The URI for this literals type
+   */
+  public IRI getType() {
+    return new IRI(type);
+  }
+
+  /**
+   * Gets the language ID of this literal
+   * @return The language ID for this literal
+   */
+  public SimpleLiteral getLang() {
+    return SimpleLiteral.EMPTY;
+  }
+  
+  /** {@inheritDoc} */
+  public String getLexical() {
+    return lexical;
+  }
+
+  /**
+   * No context needed as this is a literal value.
+   * @see org.mulgara.query.filter.value.RDFTerm#getContextOwner()
+   */
+  public ContextOwner getContextOwner() {
+    return null;
+  }
+
+  /**
+   * No context needed as this is a literal value.
+   * @see org.mulgara.query.filter.value.RDFTerm#setContextOwner(org.mulgara.query.filter.ContextOwner)
+   */
+  public void setContextOwner(ContextOwner owner) { }
+
+  /** {@inheritDoc} */
+  public boolean test(Context context) throws QueryException {
+    if (type == null) return ((String)value).length() != 0;
+    TypeInfo test = infoMap.get(type);
+    return test != null && test.ebv((String)value);
+  }
+
+  /** A map of XSD datatypes onto the tests for their types */
+  private static Map<URI,TypeInfo> infoMap = new HashMap<URI,TypeInfo>();
+
+  private static final URI xsd(String s) { return URI.create(XSD_NS + s); }
+
+  /** This interface tests if datatype matches the data to give an EBV of <code>true</code> */
+  public interface TypeInfo {
+    /** Returns an EBV of <code>true</code> iff the data matches the type sufficiently */
+    public boolean ebv(String data) throws QueryException;
+    /** Returns data parsed out of the string literal */
+    public Object toData(String representation);
+    /** Returns the URI for this type */
+    public URI getTypeURI();
+    /** All the registered types */
+    static final List<TypeInfo> types = new ArrayList<TypeInfo>();
+  }
+
+  /** Simple extension to TypeInfo to store the type URI for all implementing classes  */
+  private static abstract class AbstractXSD implements TypeInfo  {
+    private final URI typeURI;
+    AbstractXSD(String fragment) { typeURI = xsd(fragment); }
+    public URI getTypeURI() { return typeURI; }
+  }
+
+  /**
+   * Helper method for static initialization
+   * @param info The info to add to the infoMap
+   */
+  private static void addDefaultTypeInfo(TypeInfo info) {
+    infoMap.put(info.getTypeURI(), info);
+  }
+
+  // initialize the types
+  static {
+    addDefaultTypeInfo(new XSDString());
+    addDefaultTypeInfo(new XSDBoolean());
+    addDefaultTypeInfo(new XSDDouble());
+    addDefaultTypeInfo(new XSDFloat());
+    addDefaultTypeInfo(new XSDLong());
+    addDefaultTypeInfo(new XSDInteger());
+    addDefaultTypeInfo(new XSDShort());
+    addDefaultTypeInfo(new XSDByte());
+    addDefaultTypeInfo(new XSDDate());
+    infoMap.put(xsd("decimal"), new XSDLong());
+    infoMap.put(xsd("integer"), new XSDLong());
+    infoMap.put(xsd("nonPositiveInteger"), new XSDLong());
+    infoMap.put(xsd("negativeInteger"), new XSDLong());
+    infoMap.put(xsd("nonNegativeInteger"), new XSDLong());
+    infoMap.put(xsd("positiveInteger"), new XSDInteger());
+    infoMap.put(xsd("unsignedLong"), new XSDLong());
+    infoMap.put(xsd("unsignedInt"), new XSDLong());
+    infoMap.put(xsd("unsignedShort"), new XSDInteger());
+    infoMap.put(xsd("unsignedByte"), new XSDShort());
+  }
+
+  //////////////////////////////////////////////////////////////////
+  // Implementing classes
+  //////////////////////////////////////////////////////////////////
+
+  private static class XSDString extends AbstractXSD {
+    XSDString() { super("string"); }
+    public boolean ebv(String data) { return data != null && data.length() != 0; }
+    public Object toData(String r) { return r; }
+  }
+
+  private static class XSDBoolean extends AbstractXSD {
+    XSDBoolean() { super("boolean"); }
+    public boolean ebv(String data) { return Boolean.parseBoolean(data); }
+    public Object toData(String r) { return Boolean.parseBoolean(r); }
+  }
+  
+  private static class XSDDouble extends AbstractXSD {
+    XSDDouble() { super("double"); }
+    public boolean ebv(String data) {
+      try {
+        if (data == null) return false;
+        Double d = Double.parseDouble(data);
+        return 0 != Double.parseDouble(data) && !d.isNaN();
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Double.parseDouble(r);
+      } catch (NumberFormatException nfe) {
+        return Double.valueOf(0.0);
+      }
+    }
+  }
+  
+  private static class XSDFloat extends AbstractXSD {
+    XSDFloat() { super("float"); }
+    public boolean ebv(String data) {
+      try {
+        if (data == null) return false;
+        Float f = Float.parseFloat(data);
+        return 0 != f && !f.isNaN();
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Float.parseFloat(r);
+      } catch (NumberFormatException nfe) {
+        return Float.valueOf(0);
+      }
+    }
+  }
+
+  private static class XSDLong extends AbstractXSD {
+    XSDLong() { super("long"); }
+    public boolean ebv(String data) {
+      try {
+        return data != null && 0 != Long.parseLong(data);
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Long.parseLong(r);
+      } catch (NumberFormatException nfe) {
+        return Long.valueOf(0);
+      }
+    }
+  }
+
+  private static class XSDInteger extends AbstractXSD {
+    XSDInteger() { super("int"); }
+    public boolean ebv(String data) {
+      try {
+        return data != null && 0 != Integer.parseInt(data);
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Integer.parseInt(r);
+      } catch (NumberFormatException nfe) {
+        return Integer.valueOf(0);
+      }
+    }
+  }
+
+  private static class XSDShort extends AbstractXSD {
+    XSDShort() { super("short"); }
+    public boolean ebv(String data) {
+      try {
+        return data != null && 0 != Short.parseShort(data);
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Short.parseShort(r);
+      } catch (NumberFormatException nfe) {
+        return Short.valueOf((short)0);
+      }
+    }
+  }
+
+  private static class XSDByte extends AbstractXSD {
+    XSDByte() { super("byte"); }
+    public boolean ebv(String data) {
+      try {
+        return data != null && 0 != Byte.parseByte(data);
+      } catch (NumberFormatException nfe) {
+        return false;
+      }
+    }
+    public Object toData(String r) {
+      try {
+        return Long.parseLong(r);
+      } catch (NumberFormatException nfe) {
+        return Byte.valueOf((byte)0);
+      }
+    }
+  }
+
+  private static class XSDDate extends AbstractXSD {
+    XSDDate() { super("dateTime"); }
+    public boolean ebv(String data) throws QueryException { throw new QueryException("Unable to convert a date to a boolean"); }
+    public Object toData(String r) { return DateTime.parseDate(r); }
+  }
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ValueLiteral.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ValueLiteral.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/ValueLiteral.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,60 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.mulgara.query.QueryException;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.Filter;
+
+
+/**
+ * Represents expressions that can appear in a comparison expression, used by filters
+ *
+ * @created Mar 10, 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>
+ */
+public interface ValueLiteral extends RDFTerm, Filter {
+
+  /**
+   * Returns the data represented by this expression.
+   * @return The represented data.
+   * @throws QueryException Resolving the data for this value leads to an error.
+   */
+  public Object getValue() throws QueryException;
+
+  /**
+   * Returns the string that represents the value.  This is identical to the value for
+   * simple literals and xsd:string, and should parse to the value for most other types.
+   * However, it will also store incompatible values, in case of bad literal definitions
+   * such as 'abc'^^<xsd:integer>
+   * @return The represented data.
+   * @throws QueryException Resolving the data for this value leads to an error.
+   */
+  public String getLexical() throws QueryException;
+
+  /**
+   * Gets the language code for this literal, if it exists.
+   * @return a language code, or an empty string if none is present
+   */
+  public SimpleLiteral getLang() throws QueryException;
+  
+  /**
+   * Calculates the Effective Boolean Value (EBV) of this literal.
+   * @param context The context to determine this value in. Ignored because this is a literal.
+   * @return <code>true</code> when the EBV conditions are met.
+   * @throws QueryException There was an error during resolving the literal.
+   */
+  public boolean test(Context context) throws QueryException;
+
+}

Added: branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Var.java
===================================================================
--- branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Var.java	                        (rev 0)
+++ branches/mgr-61-sparql/src/jar/query/java/org/mulgara/query/filter/value/Var.java	2008-03-17 20:41:59 UTC (rev 684)
@@ -0,0 +1,269 @@
+/**
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+package org.mulgara.query.filter.value;
+
+import org.apache.log4j.Logger;
+import org.jrdf.graph.BlankNode;
+import org.jrdf.graph.Literal;
+import org.jrdf.graph.Node;
+import org.jrdf.graph.URIReference;
+import org.mulgara.query.QueryException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.Variable;
+import org.mulgara.query.filter.AbstractContextOwner;
+import org.mulgara.query.filter.Context;
+import org.mulgara.query.filter.ContextOwner;
+import org.mulgara.resolver.spi.GlobalizeException;
+import org.mulgara.store.tuples.Tuples;
+
+
+/**
+ * Marks the use of a variable.
+ * This class needs a reference to the calling resolved Tuples to extract the variable
+ * bindings for the current row.
+ *
+ * @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>
+ */
+public class Var extends AbstractContextOwner implements ComparableExpression, ValueLiteral, NumericExpression {
+
+  /** Logger */
+  private static Logger logger = Logger.getLogger(Var.class.getName());
+
+  /** The name of this variable */
+  private String name;
+
+  /** An invalid index to indicate that a variable is not bound */
+  private static final int NOT_BOUND = -1;
+
+  /** An invalid index to indicate that a variable is not initialized */
+  private static final int NOT_INITIALIZED = -2;
+
+  /** The index of this variable in the context */
+  private int varIndex = NOT_INITIALIZED;
+
+  /** The owner of the current context */
+  private ContextOwner contextOwner = null;
+
+  /**
+   * Instantiate a variable.
+   * @param n The boolean to wrap
+   */
+  Var(String name) {
+    this.name = name;
+  }
+
+  /**
+   * Tests if this variable is bound.
+   * @return <code>true</code> if the variable is unknown, or known and not bound.
+   */
+  public boolean isBound() throws QueryException {
+    try {
+      // this will set varIndex if it is not set yet
+      Context context = getLocalContext();
+      return varIndex != NOT_BOUND && context.getTuples().getColumnValue(varIndex) != Tuples.UNBOUND;
+    } catch (TuplesException te) {
+      throw new QueryException("Unable to test if variable is bound.", te);
+    }
+  }
+
+  /** {@inheritDoc} */
+  public Object getValue() throws QueryException {
+    return resolve().getValue();
+  }
+
+  /** {@inheritDoc} */
+  public Number getNumber() throws QueryException {
+    Object result = getValue();
+    if (result instanceof Number) return (Number)result;
+    throw new QueryException("Variable '" + name + "' did not resolve to a number. Got: " + result);
+  }
+
+  /**
+   * {@inheritDoc}
+   * Uses {@link #resolveComparable()} for throwing the QueryException if this variable
+   * does not resolve to a literal, and hence does not have a lexical form.
+   */
+  public String getLexical() throws QueryException {
+    ComparableExpression e = resolveComparable();
+    if (e.isLiteral()) return ((ValueLiteral)e).getLexical();
+    // fall back to getting a string out of a complex expression
+    return e.getValue().toString();
+  }
+
+  /** {@inheritDoc} */
+  public boolean equals(RDFTerm v) throws QueryException {
+    return resolveComparable().equals(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean notEquals(RDFTerm v) throws QueryException {
+    return resolveComparable().notEquals(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean greaterThan(ComparableExpression v) throws QueryException {
+    return resolveComparable().greaterThan(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean greaterThanEqualTo(ComparableExpression v) throws QueryException {
+    return resolveComparable().greaterThanEqualTo(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean lessThan(ComparableExpression v) throws QueryException {
+    return resolveComparable().lessThan(v);
+  }
+
+  /** {@inheritDoc} */
+  public boolean lessThanEqualTo(ComparableExpression v) throws QueryException {
+    return resolveComparable().lessThanEqualTo(v);
+  }
+
+  /**
+   * Resolve this variable in its current context
+   * @return An expression value wrapping the data bound to this point
+   * @throws QueryException Indicates an error getting data out of the context, or globalizing.
+   */
+  public ComparableExpression resolveComparable() throws QueryException {
+    RDFTerm v = resolve();
+    if (!(v instanceof ComparableExpression)) throw new QueryException("Cannot compare against a " + v.getClass().getSimpleName());
+    return (ComparableExpression)v;
+  }
+
+  /** {@inheritDoc} */
+  public boolean isBlank() throws QueryException {
+    return resolve().isBlank();
+  }
+
+  /** {@inheritDoc} */
+  public boolean isIRI() throws QueryException {
+    return resolve().isIRI();
+  }
+
+  /** {@inheritDoc} */
+  public boolean isLiteral() throws QueryException {
+    return resolve().isLiteral();
+  }
+
+  /** {@inheritDoc} */
+  public boolean isURI() throws QueryException {
+    return resolve().isURI();
+  }
+
+  /** {@inheritDoc} */
+  public boolean sameTerm(RDFTerm v) throws QueryException {
+    return resolve().sameTerm(v);
+  }
+
+  /**
+   * {@inheritDoc}
+   * @throws QueryException If there was an error resolving the variable, or the variable does not
+   *         resolve to a literal.
+   */
+  public SimpleLiteral getLang() throws QueryException {
+    RDFTerm term = resolve();
+    if (!term.isLiteral()) throw new QueryException("Cannot get a language tag on a non-literal: " + term.getClass().getSimpleName());
+    return ((ValueLiteral)term).getLang();
+  }
+
+  public boolean test(Context context) throws QueryException {
+    setCurrentContext(context);
+    RDFTerm term = resolve();
+    if (!term.isLiteral()) throw new QueryException("Cannot get an effective boolean value for a non-literal: " + term.getClass().getSimpleName());
+    return ((ComparableExpression)term).test(context);
+  }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#getContextOwner() */
+  public ContextOwner getContextOwner() {
+    return contextOwner;
+  }
+
+  /** @see org.mulgara.query.filter.value.RDFTerm#setContextOwner(org.mulgara.query.filter.ContextOwner) */
+  public void setContextOwner(ContextOwner owner) {
+    this.contextOwner = owner;
+  }
+
+  /**
+   * Resolve this variable in its current context
+   * @return An expression value wrapping the data bound to this point
+   * @throws QueryException Indicates an error getting data out of the context, or globalizing.
+   */
+  public RDFTerm resolve() throws QueryException {
+    long gNode;
+    try {
+      gNode = getLocalContext().getTuples().getColumnValue(varIndex);
+    } catch (TuplesException te) {
+      throw new QueryException("Unable to resolve variable " + name, te);
+    }
+
+    Node node;
+    try {
+      node = getContextOwner().getCurrentContext().getSession().globalize(gNode);
+    } catch (GlobalizeException te) {
+      throw new QueryException("Unable to globalize variable " + name + " from id <" + gNode + ">", te);
+    }
+
+    return convertToExpr(node);
+  }
+
+  /**
+   * Converts a node to an appropriate ExpressionValue
+   * @param node The node to convert
+   * @return A new ExpressionValue
+   */
+  private RDFTerm convertToExpr(Node node) throws QueryException {
+    if (node instanceof BlankNode) return new BlankNodeValue((BlankNode)node);
+    
+    if (node instanceof URIReference) return new IRI(((URIReference)node).getURI());
+    
+    if (!(node instanceof Literal)) throw new QueryException("Unknown type for: " + node);
+
+    Literal l = (Literal)node;
+    return TypedLiteral.newTypedLiteral(l.getLexicalForm(), l.getDatatypeURI(), l.getLanguage());
+  }
+
+  /**
+   * Return the current context, using a test context over that provided by the context owner if possible
+   * Updates the value of varIndex.
+   * @return The current context to use.
+   */
+  private Context getLocalContext() throws TuplesException {
+    Context localContext = getCurrentContext();
+    if (localContext == null) {
+      localContext = getContextOwner().getCurrentContext();
+    } else {
+      if (localContext != getContextOwner().getCurrentContext()) logger.warn("Unexpected different local context");
+    }
+    return setVarIndex(localContext);
+  }
+
+  /**
+   * Sets the varIndex if (and only if) it has not been set before.
+   * @param context The context to use to get the variable index.
+   * @return The context used, so it can be reused for the next operation.
+   */
+  private Context setVarIndex(Context context) {
+    if (varIndex == NOT_INITIALIZED) {
+      try {
+        varIndex = context.getTuples().getColumnIndex(new Variable(name));
+      } catch (TuplesException e) {
+        varIndex = NOT_BOUND;
+      }
+    }
+    return context;
+  }
+
+}




More information about the Mulgara-svn mailing list