http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/OGCFilter.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/OGCFilter.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/OGCFilter.java
new file mode 100644
index 0000000..7bf622d
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/OGCFilter.java
@@ -0,0 +1,241 @@
+package ss.cloudbase.core.iterators.filter.ogc;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import ss.cloudbase.core.iterators.filter.ogc.operation.IOperation;
+
+import cloudbase.core.data.Key;
+import cloudbase.core.data.Value;
+import cloudbase.core.iterators.filter.Filter;
+import cloudbase.start.classloader.CloudbaseClassLoader;
+
+/**
+ * The OGCFilter class provides a basic implementation of the 
+ * <a href="http://www.opengeospatial.org/standards/filter";>OGC Filter 
Encoding specification</a>. 
+ * This allows for arbitrary queries to be passed via XML and executed in a 
distributed fashion across tablet servers. The following
+ * code sets up a basic FilteringIterator that uses this filter (note that 
this jar must be present in each
+ * of the tablet servers' classpaths to work):
+ * 
+ * <code>
+ * <pre>
+ * cloudbase.core.client.Scanner reader;
+ * // set up the reader ...
+ *  
+ * // we're going to parse a row formated like key:value|key:value|key:value 
and return all of the rows
+ * // where the key "city" starts with "new"
+ * String filter = 
"&lt;PropertyIsLike&gt;&lt;PropertyName&gt;city&lt;/PropertyName&gt;&lt;Literal&gt;new*&lt;/Literal&gt;&lt;/PropertyIsLike&gt;";
+ * 
+ * reader.setScanIterators(50, FilteringIterator.class.getName(), 
"myIterator");
+ * reader.setScanIteratorOption("myIterator", "0", OGCFilter.class.getName());
+ * reader.setScanIteratorOption("myIterator", "0." + 
OGCFilter.OPTION_PAIR_DELIMITER, "\\|");
+ * reader.setScanIteratorOption("myIterator", "0." + 
OGCFilter.OPTION_VALUE_DELIMITER, ":");
+ * reader.setScanIteratorOption("myIterator", "0." + OGCFilter.OPTION_FILTER, 
filter);
+ * <pre>
+ * </code>
+ *  
+ * @author William Wall
+ */
+public class OGCFilter implements Filter {
+       private static final Logger logger = Logger.getLogger(OGCFilter.class);
+       
+       /** The string that separates the key/value pairs in the row value. */
+       public static final String OPTION_PAIR_DELIMITER = "pairDelimiter";
+       
+       /** The string that separates the key and the value(s) within a pair in 
the row value. */
+       public static final String OPTION_VALUE_DELIMITER = "valueDelimiter";
+       
+       /** The OGC Filter Encoding XML as a string */
+       public static final String OPTION_FILTER = "filter";
+       
+       /** Specifies the column name for the column family. If this option is 
not included, the column family is not included in the row. */
+       public static final String OPTION_COLF_NAME = "colfName";
+       
+       /** Specifies the column name for the column qualifier. If this option 
is not included, the column qualifier is not included in the row. */
+       public static final String OPTION_COLQ_NAME = "colqName";
+       
+       /** Specifies the compare type for the filter. Defaults to "auto". **/
+       public static final String OPTION_COMPARE_TYPE = "compareType";
+       
+       public static final String TYPE_NUMERIC = "numeric";
+       
+       public static final String TYPE_STRING = "string";
+       
+       public static final String TYPE_AUTO = "auto";
+       
+       /** Contains the pair delimiter provided through the 
<code>OPTION_PAIR_DELIMITER</code> option. */
+       protected String pairDelimiter;
+       
+       /** Contains the value delimiter provided through the 
<code>OPTION_VALUE_DELIMITER</code> option. */
+       protected String valueDelimiter;
+       
+       /** Contains the column family column name provided through the 
<code>OPTION_COLF_NAME</code> option. */
+       protected String colfName;
+       
+       /** Contains the column qualifier column name provided through the 
<code>OPTION_COLQ_NAME</code> option. */
+       protected String colqName;
+       
+       /** The root operation of the query tree **/
+       protected IOperation root;
+       
+       /** The compare type for the query tree **/
+       protected String compareType;
+
+       /**
+        * Whether or not to accept this key/value entry. A map of row keys and 
values is parsed and then sent off to the process function to be evaluated.
+        * @param key The cloudbase entry key
+        * @param value The cloudbase entry value
+        * @return True if the entry should be included in the results, false 
otherwise
+        */
+       @Override
+       public boolean accept(Key key, Value value) {
+               if (root != null) {
+                       Map<String, String> row = getRow(key, value);
+                       if (root != null) {
+                               return root.execute(row);
+                       }
+               }
+               return false;
+       }
+       
+       public boolean accept(Map<String, String> record) {
+               if (root != null) {
+                       return root.execute(record);
+               }
+               return false;
+       }
+       
+       /**
+        * Parses the cloudbase value into a map of key/value pairs. If the 
<code>OPTION_COLF_NAME</code> 
+        * or <code>OPTION_COLQ_NAME</code> options were used, then they will 
also be added to the row map. 
+        * By default, pairs are delimited by the first unicode character 
("\u0000") and values by the last unicode
+        * character ("\uFFFD"). See the <code>OPTION_PAIR_DELIMITER</code> and 
<code>OPTION_VALUE_DELIMITER</code> 
+        * options to change these values.
+        * 
+        * @param cbKey The cloudbase entry key
+        * @param cbValue The cloudbase entry value
+        * @return A map that represents this row
+        */
+       protected Map<String, String> getRow(Key cbKey, Value cbValue) {
+               //TODO: This should really be replaced by 
CBValueFormatter.parse(value.toString()), but I'm hesitant to require
+               // more jars (common-data and google-collections) to be in the 
cloudbase/lib directory. Also, what do we do with
+               // a field with multiple values? Should we just assume that if 
any value in that field matches then the row
+               // matches? Or should they all have to match? 
+               
+               String value = cbValue.toString();
+               Map<String, String> row = new HashMap<String, String>();
+               
+               if (colfName != null) {
+                       row.put(colfName, cbKey.getColumnFamily().toString());
+               }
+               if (colqName != null) {
+                       row.put(colqName, 
cbKey.getColumnQualifier().toString());
+               }
+               
+               // Determine the start/end of the value.
+               int valueStartIndex = 0;
+               int valueEndIndex = value.length();
+               
+               int vLen = valueDelimiter.length();
+               int fLen = pairDelimiter.length();
+
+               // Parse each of the values from the row value.
+               while (valueStartIndex < valueEndIndex) {
+                       int vIndex = value.indexOf(valueDelimiter, 
valueStartIndex);
+       
+                       // If an "equals" sign was found, parse the key and 
value.
+                       if (vIndex != -1) {
+                               String key = value.substring(valueStartIndex, 
vIndex).trim();
+                               int v = value.indexOf(valueDelimiter, vIndex + 
vLen);
+                               if (v == -1) {
+                                       v = valueEndIndex;
+                               }
+                               int f = value.indexOf(pairDelimiter, vIndex + 
vLen);
+                               if (f == -1) {
+                                       f = valueEndIndex;
+                               }
+                               
+                               int fIndex = Math.min(f,v);
+                               String val = value.substring(vIndex + 1, 
fIndex).trim();
+                               valueStartIndex = f;
+                               valueStartIndex += fLen;
+                               row.put(key, val);
+                       }
+               }
+               
+               return row;
+       }
+
+       @Override
+       public void init(Map<String, String> options) {
+               pairDelimiter = options.get(OPTION_PAIR_DELIMITER);
+               if (pairDelimiter == null || pairDelimiter.length() == 0) {
+                       pairDelimiter = "\u0000";
+               }
+               
+               valueDelimiter = options.get(OPTION_VALUE_DELIMITER);
+               if (valueDelimiter == null || valueDelimiter.length() == 0) {
+                       valueDelimiter = "\uFFFD";
+               }
+               
+               compareType = options.get(OPTION_COMPARE_TYPE);
+               if (compareType == null || compareType.length() == 0) {
+                       compareType = TYPE_AUTO;
+               }
+               
+               colfName = options.get(OPTION_COLF_NAME);
+               colqName = options.get(OPTION_COLQ_NAME);
+               
+               try {
+                       DocumentBuilder builder = 
DocumentBuilderFactory.newInstance().newDocumentBuilder();
+                       InputSource is = new InputSource();
+                       is.setCharacterStream(new 
StringReader(options.get(OPTION_FILTER)));
+                       Document doc = builder.parse(is);
+                       Node filter = doc.getDocumentElement();
+                       if (filter.getNodeName().equalsIgnoreCase("filter")) {
+                               filter = filter.getFirstChild();
+                       }
+                       root = createOperationTree(filter);
+               } catch (IOException e) {
+                       logger.error(e,e);
+               } catch (SAXException e) {
+                       logger.error(e,e);
+               } catch (ParserConfigurationException e) {
+                       logger.error(e,e);
+               }
+       }
+       
+       /**
+        * Creates the operation tree from the filter XML
+        * @param node The filter XML node to parse
+        * @return The root IOperation
+        */
+       protected IOperation createOperationTree(Node node) {
+               try {
+                       // instantiate the operation and initialize it
+                       Class<? extends IOperation> clazz = 
CloudbaseClassLoader.loadClass(IOperation.class.getPackage().getName() + "." + 
node.getNodeName(), IOperation.class);
+                       IOperation op = clazz.newInstance();
+                       op.init(node, compareType);
+                       return op;
+               } catch (ClassNotFoundException e) {
+                       logger.warn("Operation not supported: " + 
node.getNodeName());
+               } catch (InstantiationException e) {
+                       logger.error(e,e);
+               } catch (IllegalAccessException e) {
+                       logger.error(e,e);
+               }
+               return null;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractComparisonOp.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractComparisonOp.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractComparisonOp.java
new file mode 100644
index 0000000..46b1cf9
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractComparisonOp.java
@@ -0,0 +1,80 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import ss.cloudbase.core.iterators.filter.ogc.OGCFilter;
+
+
+
+/**
+ * This class provides a simple init method for setting up most of the 
variables
+ * needed to do a comparison operation between two values.
+ * 
+ * @author William Wall
+ */
+public abstract class AbstractComparisonOp {
+       protected String name, literal, value;
+       protected boolean isNumeric = false;
+       protected double literalNum, valueNum;
+       protected String compareType;
+       
+       public void init(Node node, String compareType) {
+               this.compareType = compareType;
+               Node child;
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       child = children.item(i);
+                       if 
(child.getNodeName().equalsIgnoreCase("PropertyName")) {
+                               name = child.getTextContent();
+                       } else {
+                               literal = child.getTextContent();
+                       }
+               }
+               
+               if (compareType.equalsIgnoreCase(OGCFilter.TYPE_NUMERIC) || 
compareType.equalsIgnoreCase(OGCFilter.TYPE_AUTO)) {
+                       literalNum = parseNumeric(literal);
+                       isNumeric = !Double.isNaN(literalNum);
+               }
+       }
+       
+       public List<IOperation> getChildren() {
+               return null;
+       }
+       
+       protected boolean checkRowNumeric(String s) {
+               if (isNumeric) {
+                       valueNum = parseNumeric(s);
+                       return valueNum != Double.NaN;
+               }
+               return false;
+       }
+       
+       public String getValue(Map<String, String> row) {
+               String value = row.get(name);
+               
+               // nulls will be lexicographically equal to ""
+               if (value == null) {
+                       value = "";
+               }
+               return value;
+       }
+       
+       public static double parseNumeric(String s) {
+               // see if the string can be parsed as a double or an integer
+               double val = Double.NaN;
+               try {
+                       val = Double.parseDouble(s);
+               } catch (Exception e) {
+                       try {
+                               val = new Double(Integer.parseInt(s));
+                       } catch (Exception e2) {
+                               
+                       }
+               }
+               return val;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractLogicalOp.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractLogicalOp.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractLogicalOp.java
new file mode 100644
index 0000000..0400f61
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/AbstractLogicalOp.java
@@ -0,0 +1,40 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import cloudbase.start.classloader.CloudbaseClassLoader;
+
+public class AbstractLogicalOp {
+       private static final Logger logger = 
Logger.getLogger(AbstractLogicalOp.class);
+       
+       List<IOperation> children = new ArrayList<IOperation>();
+       
+       public void init(Node node, String compareType) {
+               Node child;
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       child = children.item(i); 
+                       try {
+                               Class<? extends IOperation> clazz = 
CloudbaseClassLoader.loadClass(IOperation.class.getPackage().getName() + "." + 
child.getNodeName(), IOperation.class);
+                               IOperation op = clazz.newInstance();
+                               op.init(child, compareType);
+                               this.children.add(op);
+                       } catch (ClassNotFoundException e) {
+                               logger.warn("Operation not supported: " + 
node.getNodeName());
+                       } catch (InstantiationException e) {
+                               logger.error(e,e);
+                       } catch (IllegalAccessException e) {
+                               logger.error(e,e);
+                       }
+               }
+       }
+       
+       public List<IOperation> getChildren() {
+               return children;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/And.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/And.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/And.java
new file mode 100644
index 0000000..b192b19
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/And.java
@@ -0,0 +1,29 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * Executes a logical AND on all the child operations.
+ * 
+ * <code>
+ * <pre>
+ * &lt;And&gt;
+ *     &lt;PropertyIsEqualTo&gt;...
+ *     &lt;PropertyIsLessThan&gt;...
+ * &lt;/And&gt;
+ * </pre>
+ * </code>
+ * 
+ * @author William Wall
+ */
+public class And extends AbstractLogicalOp implements IOperation {
+       @Override
+       public boolean execute(Map<String, String> row) {
+               boolean result = true;
+               for (int i = 0; i < children.size(); i++) {
+                       result = children.get(i).execute(row);
+                       if (!result) break;
+               }
+               return result;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/BBOX.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/BBOX.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/BBOX.java
new file mode 100644
index 0000000..8596338
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/BBOX.java
@@ -0,0 +1,125 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * Tests a row to see if it falls within the given shape. The shape should be
+ * defined in degrees. There is no need to send a property name since all the
+ * rows contain either lonself/latself or lon/lat fields.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;BBOX&gt;
+ *             &lt;gml:Envelope&gt;
+ *                     &lt!-- coordinates are in lon/lat order --&gt;
+ *                     &lt;gml:LowerCorner&gt;13.09 
31.5899&lt;/gml:LowerCorner&gt;
+ *                     &lt;gml:UpperCorner&gt;35.725 
42.8153&lt;/gml:UpperCorner&gt;
+ *             &lt;/gml:Envelope&gt;
+ *     &lt;/BBOX&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class BBOX implements IOperation {
+       private static final Logger logger = Logger.getLogger(BBOX.class);
+       
+       Shape shape;
+       
+       // longitude column names in order of priority
+       protected static final String[] LON_NAMES = {
+               "lonself",
+               "lon",
+               "long",
+               "longitude"
+       };
+       
+       // latitude column names in order of priority
+       protected static final String[] LAT_NAMES = {
+               "latself",
+               "lat",
+               "latitude"
+       };
+       
+       @Override
+       public boolean execute(Map<String, String> row) {
+               Point2D p = BBOX.getPoint(row);
+               
+               if (p != null && shape != null) {
+                       if (shape.contains(p)) {
+                               return true;
+                       } else {
+                               // attempt to normalize the point into the 
shape in the event that the shape
+                               // bounds are outside of -180 to 180
+                               Rectangle bounds = shape.getBounds();
+                               while (p.getX() < bounds.getMinX()) {
+                                       p.setLocation(p.getX() + 360, p.getY());
+                               }
+                               while (p.getX() > bounds.getMaxX()) {
+                                       p.setLocation(p.getX() - 360, p.getY());
+                               }
+                               
+                               return shape.contains(p);
+                       }
+               }
+               
+               return false;
+       }
+
+       @Override
+       public List<IOperation> getChildren() {
+               return null;
+       }
+
+       @Override
+       public void init(Node node, String compareType) {
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       shape = ShapeFactory.getShape(children.item(i));
+                       if (shape != null) {
+                               break;
+                       }
+               }
+               
+       }
+       
+       /**
+        * Gets a point that represents the location of this row. See 
+        * @param row
+        * @return The point object as (x - Longitude, y - Latitude)
+        */
+       protected static Point2D getPoint(Map<String, String> row) {
+               Point2D.Double p = new Point2D.Double();
+               p.x = getDegree(row, LON_NAMES);
+               p.y = getDegree(row, LAT_NAMES);
+               return p;
+       }
+       
+       protected static double getDegree(Map<String, String> row, String[] 
cols) {
+               double num = Double.NaN;
+               String value;
+               for (int i = 0; i < cols.length; i++) {
+                       if (row.containsKey(cols[i])) {
+                               value = row.get(cols[i]);
+                               if (value != null && !value.equals("-")) {
+                                       try {
+                                               num = Double.parseDouble(value);
+                                               break;
+                                       } catch (NumberFormatException e) {
+                                               logger.warn("Could not parse 
degree value from " + cols[i] + " = " + value);
+                                       }
+                               }
+                       }
+               }
+               
+               return num;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/IOperation.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/IOperation.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/IOperation.java
new file mode 100644
index 0000000..6ad8ebe
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/IOperation.java
@@ -0,0 +1,30 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Node;
+
+public interface IOperation {
+       
+       /**
+        * Sets up the operation from the filter XML node
+        * @param node The node
+        * @param compareType The compare type. Defaults to "auto", but you can 
force it to be "numeric" or "string".
+        */
+       public void init(Node node, String compareType);
+       
+       /**
+        * Executes the operation indicated by the given node in the query
+        * tree.
+        * @param row The key/value pairs for the current row
+        * @return The boolean evaluation of the operation
+        */
+       public boolean execute(Map<String, String> row);
+       
+       /**
+        * Returns the nodes children. This is only applicable to logical
+        * operations (AND, OR, NOT).
+        */
+       public List<IOperation> getChildren();
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Not.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Not.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Not.java
new file mode 100644
index 0000000..74826a8
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Not.java
@@ -0,0 +1,35 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * Executes a logical NOT on the child operations. If there is a single child, 
then 
+ * the operation is NOT. If more than one child exists, this operation 
defaults to
+ * NOR behavior. For NAND behavior, make a single AND child of NOT.
+ * 
+ * <code>
+ * <pre>
+ * &lt;Not&gt;
+ *     &lt;PropertyIsEqualTo&gt;...
+ * &lt;/Not&gt;
+ * </pre>
+ * </code>
+ * 
+ * @author William Wall
+ *
+ */
+public class Not extends AbstractLogicalOp implements IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               // For typical NOT behavior, a NOT group should have one child. 
If it has more than one child, it behaves
+               // like NOR. NAND/NOR behavior can be implemented by giving the 
Not group a child group of AND/OR.
+               boolean result = true;
+               for (int i = 0; i < children.size(); i++) {
+                       result = !children.get(i).execute(row);
+                       // in the case that there are multiple children, treat 
them as NOR
+                       if (!result) break;
+               }
+               return result;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Or.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Or.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Or.java
new file mode 100644
index 0000000..0a3dd6e
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/Or.java
@@ -0,0 +1,29 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * Executes a logical OR on the child operations.
+ * 
+ * <code>
+ * <pre>
+ * &lt;Or&gt;
+ *     &lt;PropertyIsEqualTo&gt;...
+ *     &lt;PropertyIsLessThan&gt;...
+ * &lt;/Or&gt;
+ * </pre>
+ * </code>
+ * 
+ * @author William Wall
+ */
+public class Or extends AbstractLogicalOp implements IOperation {
+       @Override
+       public boolean execute(Map<String, String> row) {
+               boolean result = false;
+               for (int i = 0; i < children.size(); i++) {
+                       result = children.get(i).execute(row);
+                       if (result) break;
+               }
+               return result;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsBetween.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsBetween.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsBetween.java
new file mode 100644
index 0000000..2c9d86c
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsBetween.java
@@ -0,0 +1,76 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import ss.cloudbase.core.iterators.filter.ogc.OGCFilter;
+
+
+/**
+ * An operation that determines if the row's value is between the given
+ * boundary values.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsBetween&gt;
+ *             &lt;PropertyName&gt;height&lt;/PropertyName&gt;
+ *             
&lt;LowerBoundary&gt;&lt;Literal&gt;180&lt;/Literal&gt;&lt;/LowerBoundary&gt;
+ *             
&lt;UpperBoundary&gt;&lt;Literal&gt;200&lt;/Literal&gt;&lt;/UpperBoundary&gt;
+ *     &lt;/PropertyIsBetween&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class PropertyIsBetween implements IOperation {
+       String name;
+       String lower, upper, value;
+       double lowerNum, upperNum, valueNum;
+       boolean isNumeric = false;
+       
+       @Override
+       public boolean execute(Map<String, String> row) {
+               if (isNumeric) {
+                       valueNum = 
AbstractComparisonOp.parseNumeric(row.get(name));
+                       if (valueNum != Double.NaN) {
+                               return lowerNum <= valueNum && valueNum <= 
upperNum;
+                       }
+               }
+               
+               value = row.get(name);
+               if (value == null) {
+                       value = "";
+               }
+               
+               return value.compareTo(lower) > -1 && value.compareTo(upper) < 
1;
+       }
+
+       @Override
+       public List<IOperation> getChildren() {
+               return null;
+       }
+
+       @Override
+       public void init(Node node, String compareType) {
+               Node child;
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       child = children.item(i);
+                       if 
(child.getNodeName().equalsIgnoreCase("PropertyName")) {
+                               name = child.getTextContent();
+                       } else if 
(child.getNodeName().equalsIgnoreCase("LowerBoundary")) {
+                               lower = child.getTextContent();
+                       } else if 
(child.getNodeName().equalsIgnoreCase("UpperBoundary")) {
+                               upper = child.getTextContent();
+                       }
+               }
+               
+               if (compareType.equalsIgnoreCase(OGCFilter.TYPE_NUMERIC) || 
compareType.equalsIgnoreCase(OGCFilter.TYPE_AUTO)) {
+                       upperNum = AbstractComparisonOp.parseNumeric(upper);
+                       lowerNum = AbstractComparisonOp.parseNumeric(lower);
+                       isNumeric = !Double.isNaN(upperNum) && 
!Double.isNaN(lowerNum);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsEqualTo.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsEqualTo.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsEqualTo.java
new file mode 100644
index 0000000..93fa3f5
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsEqualTo.java
@@ -0,0 +1,30 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation to see whether the values are equal or not.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsEqualTo&gt;
+ *             &lt;PropertyName&gt;user&lt;/PropertyIsEqualTo&gt;
+ *             &lt;Literal&gt;CmdrTaco&lt;/Literal&gt;
+ *  &lt;/PropertyIsEqualTo&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class PropertyIsEqualTo extends AbstractComparisonOp implements 
IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum == literalNum;
+               }
+               
+               return value.equals(literal);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThan.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThan.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThan.java
new file mode 100644
index 0000000..8eb9ec0
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThan.java
@@ -0,0 +1,29 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation to see if the row value is greater than the given value.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsGreaterThan&gt;
+ *             &lt;PropertyName&gt;height&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;200&lt;/Literal&gt;
+ *     &lt;/PropertyIsGreaterThan&gt;
+ * </pre>
+ * @author William Wall
+ */
+public class PropertyIsGreaterThan extends AbstractComparisonOp implements 
IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum > literalNum;
+               }
+               
+               return value.compareTo(literal) > 0;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThanOrEqualTo.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThanOrEqualTo.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThanOrEqualTo.java
new file mode 100644
index 0000000..17fb1dc
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsGreaterThanOrEqualTo.java
@@ -0,0 +1,29 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation to see if the row value is greater than or equal to the given 
value.
+ * 
+ * Example:
+ *     <pre>
+ *     &lt;PropertyIsGreaterThanOrEqualTo&gt;
+ *             &lt;PropertyName&gt;height&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;100&lt;/Literal&gt;
+ *     &lt;/PropertyIsGreaterThanOrEqualTo&gt;
+ *     </pre>
+ * @author William Wall
+ */
+public class PropertyIsGreaterThanOrEqualTo extends AbstractComparisonOp 
implements IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum >= literalNum;
+               }
+               
+               return value.compareTo(literal) > -1;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThan.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThan.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThan.java
new file mode 100644
index 0000000..f094c99
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThan.java
@@ -0,0 +1,31 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation to see if the row value is less than the given value.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsLessThan&gt;
+ *             &lt;PropertyName&gt;height&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;180&lt;/Literal&gt;
+ *     &lt;/PropertyIsLessThan&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class PropertyIsLessThan extends AbstractComparisonOp implements 
IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum < literalNum;
+               }
+               
+               return value.compareTo(literal) < 0;
+       }
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThanOrEqualTo.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThanOrEqualTo.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThanOrEqualTo.java
new file mode 100644
index 0000000..9b01aae
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLessThanOrEqualTo.java
@@ -0,0 +1,29 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation to see if the row value is less than or equal to the given 
value.
+ * 
+ * <pre>
+ *     &lt;PropertyIsLessThanOrEqualTo&gt;
+ *             &lt;PropertyName&gt;height&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;100&lt;/Literal&gt;
+ *     &lt;/PropertyIsLessThanOrEqualTo&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class PropertyIsLessThanOrEqualTo extends AbstractComparisonOp 
implements IOperation {
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum <= literalNum;
+               }
+               
+               return value.compareTo(literal) < 1;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLike.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLike.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLike.java
new file mode 100644
index 0000000..ad38951
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsLike.java
@@ -0,0 +1,144 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * An operation that determines if the row value is like the given value. This
+ * operation supports wildcards (*).
+ * 
+ * Example:
+ * 
+ * <pre>
+ *     &lt;PropertyIsLike&gt;
+ *             &lt;PropertyName&gt;city&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;new*&lt;/Literal&gt;
+ *     &lt;/PropertyIsLike&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ * 
+ */
+public class PropertyIsLike implements IOperation {
+       String pattern;
+       String name;
+
+       @Override
+       public boolean execute(Map<String, String> row) {
+               String value = row.get(name);
+               if (value == null) {
+                       value = "";
+               }
+
+               return value.matches(pattern);
+       }
+
+       @Override
+       public List<IOperation> getChildren() {
+               return null;
+       }
+
+       @Override
+       public void init(Node node, String compareType) {
+               Node child;
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       child = children.item(i);
+                       if 
(child.getNodeName().equalsIgnoreCase("PropertyName")) {
+                               name = child.getTextContent();
+                       } else {
+                               pattern = child.getTextContent();
+                       }
+               }
+
+               pattern = convertToRegex(node, pattern);
+       }
+
+       /**
+        * Converts the pattern, wild card, single and escape characters to the
+        * regular expression equivalents. Everything else in the pattern is 
treated
+        * as a regex literal.
+        * 
+        * @param node The PropertyIsLike node
+        * @param likePattern The initial like pattern 
+        * 
+        * @return the equivalent regular expression string.
+        */
+       public String convertToRegex(Node node, String likePattern) {
+               // Convert the pattern to a regular expression.
+               StringBuilder regex = new StringBuilder();
+               
+               NamedNodeMap attr = node.getAttributes();
+               
+               String wildCard = "*";
+               if (attr.getNamedItem("wildCard") != null) {
+                       wildCard = attr.getNamedItem("wildCard").toString();
+               }
+               
+               String escapeChar = "\\";
+               if (attr.getNamedItem("escapeChar") != null) {
+                        escapeChar = 
attr.getNamedItem("escapeChar").toString();
+               }
+               
+               String singleChar = ".";
+               if (attr.getNamedItem("singleChar") != null) {
+                       singleChar = attr.getNamedItem("singleChar").toString();
+               }
+               
+               int escapeCharIndex = likePattern.indexOf(escapeChar);
+
+               // These are required in WFS but we'll handle null values here.
+               int wildCardIndex = wildCard == null ? -1 : 
likePattern.indexOf(wildCard);
+               int singleCharIndex = singleChar == null ? -1 : 
likePattern.indexOf(singleChar);
+               for (int index = 0; index < likePattern.length(); index++) {
+                       char ch = likePattern.charAt(index);
+                       if (index == escapeCharIndex) {
+                               escapeCharIndex = 
likePattern.indexOf(escapeChar, escapeCharIndex + escapeChar.length());
+
+                               // If there are consecutive escape characters, 
skip to the
+                               // next one to save it in the regex.
+                               if (index + 1 == escapeCharIndex) {
+                                       escapeCharIndex = 
likePattern.indexOf(escapeChar, escapeCharIndex + escapeChar.length());
+                               } else if (index + 1 == wildCardIndex) {
+                                       wildCardIndex = 
likePattern.indexOf(wildCard, wildCardIndex + wildCard.length());
+                               } else if (index + 1 == singleCharIndex) {
+                                       singleCharIndex = 
likePattern.indexOf(singleChar, singleCharIndex + singleChar.length());
+                               } else {
+                                       // This is an undefined condition, just 
skip the escape
+                                       // character.
+                               }
+                       }
+
+                       // Insert the regular expression equivalent of a wild 
card.
+                       else if (index == wildCardIndex) {
+                               regex.append(".*");
+                               index += wildCard.length() - 1;
+                               wildCardIndex = likePattern.indexOf(wildCard, 
wildCardIndex + wildCard.length());
+                       }
+
+                       // Insert the regular expression equivalent of the 
single char.
+                       else if (index == singleCharIndex) {
+                               regex.append(".");
+                               index += singleChar.length() - 1;
+                               singleCharIndex = 
likePattern.indexOf(singleChar, singleCharIndex + singleChar.length());
+                       }
+
+                       // Handle certain characters in a special manner.
+                       else if (('[' == ch) || (']' == ch) || ('\\' == ch) || 
('^' == ch)) {
+                               regex.append('\\').append(ch);
+                       }
+
+                       // Force everything else to be literals.
+                       else {
+                               regex.append('[').append(ch).append(']');
+                       }
+               }
+               
+               // add case insensitive flag and start match at beginning of 
the string
+               return "(?i)^" + regex.toString();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNotEqualTo.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNotEqualTo.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNotEqualTo.java
new file mode 100644
index 0000000..b62e6c6
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNotEqualTo.java
@@ -0,0 +1,30 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.Map;
+
+/**
+ * An operation that determines if the row value is not equal to the given 
value.
+ * 
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsNotEqualTo&gt;
+ *             &lt;PropertyName&gt;weather&lt;/PropertyName&gt;
+ *             &lt;Literal&gt;rainy&lt;/Literal&gt;
+ *     &lt;/PropertyIsNotEqualTo&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ *
+ */
+public class PropertyIsNotEqualTo extends AbstractComparisonOp implements 
IOperation {
+       @Override
+       public boolean execute(Map<String, String> row) {
+               value = getValue(row);
+               
+               if (checkRowNumeric(value)) {
+                       return valueNum != literalNum;
+               }
+               
+               return !value.equals(literal);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNull.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNull.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNull.java
new file mode 100644
index 0000000..d5d67c2
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/PropertyIsNull.java
@@ -0,0 +1,38 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Node;
+
+/**
+ * An operation to determine if the row value is null. Nulls and empty strings 
will both match.
+ *
+ * Example:
+ * <pre>
+ *     &lt;PropertyIsNull&gt;
+ *             &lt;PropertyName&gt;socialSkills&lt;/PropertyName&gt;
+ *     &lt;/PropertyIsNull&gt;
+ * </pre>
+ * 
+ * @author William Wall
+ */
+public class PropertyIsNull implements IOperation {
+       String name;
+       
+       @Override
+       public boolean execute(Map<String, String> row) {
+               String value = row.get(name);
+               return value == null || value.length() == 0;
+       }
+
+       @Override
+       public List<IOperation> getChildren() {
+               return null;
+       }
+
+       @Override
+       public void init(Node node, String compareType) {
+               name = node.getTextContent();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/ShapeFactory.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/ShapeFactory.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/ShapeFactory.java
new file mode 100644
index 0000000..10fea78
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/operation/ShapeFactory.java
@@ -0,0 +1,133 @@
+package ss.cloudbase.core.iterators.filter.ogc.operation;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import ss.cloudbase.core.iterators.filter.ogc.util.GeoUtil;
+
+
+public class ShapeFactory {
+       private static final Logger logger = 
Logger.getLogger(ShapeFactory.class);
+       
+       public static Shape getShape(Node node) {
+               if (node.getNodeName().equalsIgnoreCase("gml:Envelope")) {
+                       return parseEnvelope(node);
+               } else if (node.getNodeName().equalsIgnoreCase("gml:Polygon")) {
+                       return parsePolygon(node);
+               } else if 
(node.getNodeName().equalsIgnoreCase("gml:CircleByCenterPoint")) {
+                       return parseCircle(node);
+               }
+               
+               logger.warn("No parser implemented for: " + 
node.getLocalName());
+               return null;
+       }
+       
+       protected static Shape parseEnvelope(Node node) {
+               Rectangle rect = null;
+               
+               Node child;
+               NodeList children = node.getChildNodes();
+               for (int i = 0; i < children.getLength(); i++) {
+                       child = children.item(i);
+                       String[] parts = child.getTextContent().split("\\s");
+                       
+                       if (parts.length == 2) {
+                               double lon = Double.parseDouble(parts[0]);
+                               double lat = Double.parseDouble(parts[1]);
+                               
+                               if (rect == null) {
+                                       rect = new Rectangle();
+                                       rect.setFrame(lon, lat, 0, 0);
+                               } else {
+                                       rect.add(lon, lat);
+                               }
+                       }
+               }
+
+               // If the rectangle width is greater than 180 degrees, the user 
most likely
+               // meant to use the inverse BBOX (where the east value is less 
than the west).
+               // This is for clients that wrap coordinates rather than use 
absolute coordinates.
+               if (rect.getWidth() > 180) {
+                       rect.setFrame(rect.getMaxX(), rect.getMaxY(), 360 - 
rect.getWidth(), rect.getHeight());
+               }
+               
+               return rect;
+       }
+       
+       protected static Shape parsePolygon(Node node) {
+               Path2D poly = null;
+               
+               String text = node.getTextContent();
+               String[] list = text.split("\\s");
+               
+               for (int i = 1; i < list.length; i += 2) {
+                       double lon = Double.parseDouble(list[i-1]);
+                       double lat = Double.parseDouble(list[i]);
+                       if (poly == null) {
+                               poly = new Path2D.Double();
+                               poly.moveTo(lon, lat);
+                       } else {
+                               poly.lineTo(lon, lat);
+                       }
+               }
+               
+               return poly;
+       }
+       
+       protected static Shape parseCircle(Node node) {
+               Ellipse2D circle = null;
+               
+               double radius = Double.NaN, lon = Double.NaN, lat = Double.NaN;
+               String units = null;
+               
+               Node child;
+               NodeList children = node.getChildNodes();
+               try {
+                       for (int i = 0; i < children.getLength(); i++) {
+                               child = children.item(i);
+                               if 
(child.getNodeName().equalsIgnoreCase("gml:radius")) {
+                                       radius = 
Double.parseDouble(child.getTextContent());
+                                       units = 
child.getAttributes().getNamedItem("uom").getTextContent();
+                               } else {
+                                       String[] list = 
child.getTextContent().split("\\s");
+                                       lon = Double.parseDouble(list[0]);
+                                       lat = Double.parseDouble(list[1]);
+                               }
+                       }
+                       
+                       radius = convertToKM(radius, units);
+                       Point2D center = new Point2D.Double(lon, lat);
+                       Point2D end = GeoUtil.calculateEndLocation(center, 
radius, lat > 0 ? 180: 0);
+                       
+                       radius = Math.abs(end.getY() - lat);
+                       circle = new Ellipse2D.Double();
+                       circle.setFrameFromCenter(center, new 
Point2D.Double(center.getX() + radius, center.getY() + radius));
+               } catch (NumberFormatException e) {
+                       
+               } catch (ArrayIndexOutOfBoundsException e) {
+                       
+               }
+               
+               return circle;
+       }
+       
+       private static double convertToKM(double radius, String units) {
+               if (units.equalsIgnoreCase("km")) {
+                       return radius;
+               } else if (units.equalsIgnoreCase("m")) {
+                       return radius / 1000;
+               } else if (units.equalsIgnoreCase("mi")) {
+                       return 0.621371192 * radius;
+               } else if (units.equalsIgnoreCase("ft")) {
+                       return radius / 3280.8399;
+               }
+               return radius;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/util/GeoUtil.java
----------------------------------------------------------------------
diff --git 
a/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/util/GeoUtil.java
 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/util/GeoUtil.java
new file mode 100644
index 0000000..95259fa
--- /dev/null
+++ 
b/partition/common-query/src/main/java/ss/cloudbase/core/iterators/filter/ogc/util/GeoUtil.java
@@ -0,0 +1,32 @@
+package ss.cloudbase.core.iterators.filter.ogc.util;
+
+import java.awt.geom.Point2D;
+
+public class GeoUtil {
+       /**
+        * Calculates an ending location from a point, distance, and bearing
+        * @param point The start point
+        * @param distance The distance from the start point in kilometers
+        * @param bearing The bearing (in degrees) where north is 0
+        * @return The resulting point
+        */
+       public static Point2D calculateEndLocation(Point2D point, double 
distance, double bearing) {
+               double r = 6371; // earth's mean radius in km
+
+               double lon1 = Math.toRadians(point.getX());     
+               double lat1 = Math.toRadians(point.getY());
+               bearing = Math.toRadians(bearing);
+       
+               double lat2 = Math.asin( Math.sin(lat1) * Math.cos(distance/r) 
+ Math.cos(lat1) * Math.sin(distance/r) * Math.cos(bearing) );
+               double lon2 = lon1 + Math.atan2(Math.sin(bearing) * 
Math.sin(distance/r) * Math.cos(lat1), Math.cos(distance/r) - Math.sin(lat1) * 
Math.sin(lat2));
+               
+               lon2 = (lon2+Math.PI)%(2*Math.PI) - Math.PI;  // normalise to 
-180...+180
+       
+               if (Double.isNaN(lat2) || Double.isNaN(lon2)) return null;
+       
+               lon2 = Math.toDegrees(lon2);
+               lat2 = Math.toDegrees(lat2);
+               
+               return new Point2D.Double(lon2, lat2);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/test/java/GVDateFilterTest.java
----------------------------------------------------------------------
diff --git a/partition/common-query/src/test/java/GVDateFilterTest.java 
b/partition/common-query/src/test/java/GVDateFilterTest.java
new file mode 100644
index 0000000..8ea5578
--- /dev/null
+++ b/partition/common-query/src/test/java/GVDateFilterTest.java
@@ -0,0 +1,156 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Map.Entry;
+
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+import ss.cloudbase.core.iterators.GMDenIntersectingIterator;
+import ss.cloudbase.core.iterators.filter.general.GVDateFilter;
+
+import cloudbase.core.client.Connector;
+import cloudbase.core.client.Scanner;
+import cloudbase.core.client.TableNotFoundException;
+import cloudbase.core.data.Key;
+import cloudbase.core.data.Range;
+import cloudbase.core.data.Value;
+import cloudbase.core.iterators.FilteringIterator;
+import cloudbase.core.security.Authorizations;
+
+/**
+ *
+ * @author rashah
+ */
+public class GVDateFilterTest
+{
+
+  private Connector cellLevelConn;
+  private Connector serializedConn;
+  private static final String TABLE = "partition";
+  private static final Authorizations AUTHS = new 
Authorizations("ALPHA,BETA,GAMMA".split(","));
+
+
+
+  protected Connector getSerializedConnector()
+  {
+    if (serializedConn == null)
+    {
+      serializedConn = SampleGVData.initConnector();
+      SampleGVData.writeDenSerialized(serializedConn, 
SampleGVData.sampleData());
+    }
+    return serializedConn;
+  }
+
+
+
+  protected Scanner getSerializedScanner()
+  {
+    Connector c = getSerializedConnector();
+    try
+    {
+      return c.createScanner(TABLE, AUTHS);
+    }
+    catch (TableNotFoundException e)
+    {
+      return null;
+    }
+  }
+
+  protected Scanner setUpGVDFFilter(Scanner s, String timesta)
+  {
+    try
+    {
+  
+      s.setScanIterators(50, FilteringIterator.class.getName(), "gvdf");
+      s.setScanIteratorOption("gvdf", "0", GVDateFilter.class.getName());
+      s.setScanIteratorOption("gvdf", "0." + GVDateFilter.OPTIONInTimestamp, 
timesta);
+
+    }
+    catch (IOException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return s;
+  }
+
+  protected String checkSerialized(Scanner s)
+  {
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (Entry<Key, Value> e : s)
+    {
+
+      if (!first)
+      {
+        sb.append(",");
+      }
+      else
+      {
+        first = false;
+      }
+
+      String colq = e.getKey().getColumnQualifier().toString();
+
+      sb.append(colq);
+    }
+    return sb.toString();
+  }
+
+
+  @Test
+  public void testNoResults()
+  {
+
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), 
"2008-03-03T20:44:28.633Z");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).equals(""));
+  }
+
+
+  @Test
+  public void testOneResult()
+  {
+
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), 
"2011-03-03T20:44:28.633Z");
+    s.setRange(new Range());
+
+    System.out.println(checkSerialized(s));
+
+    assertTrue(checkSerialized(s).equals("03"));
+  }
+
+  @Test
+  public void testTwoResults()
+  {
+
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), 
"2009-03-03T20:44:28.633Z");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).equals("04,01"));
+  }
+
+    @Test
+  public void testThreeResults()
+  {
+
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), 
"2010-03-01T20:44:28.633Z");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).equals("04,01,03"));
+  }
+
+  @Test
+  public void testDummyTest()
+  {
+    assertTrue(true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/test/java/GVFrequencyFilterTest.java
----------------------------------------------------------------------
diff --git a/partition/common-query/src/test/java/GVFrequencyFilterTest.java 
b/partition/common-query/src/test/java/GVFrequencyFilterTest.java
new file mode 100644
index 0000000..25c602a
--- /dev/null
+++ b/partition/common-query/src/test/java/GVFrequencyFilterTest.java
@@ -0,0 +1,144 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Map.Entry;
+
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+import ss.cloudbase.core.iterators.GMDenIntersectingIterator;
+import ss.cloudbase.core.iterators.filter.general.GVFrequencyFilter;
+
+import cloudbase.core.client.Connector;
+import cloudbase.core.client.Scanner;
+import cloudbase.core.client.TableNotFoundException;
+import cloudbase.core.data.Key;
+import cloudbase.core.data.Range;
+import cloudbase.core.data.Value;
+import cloudbase.core.iterators.FilteringIterator;
+import cloudbase.core.security.Authorizations;
+
+/**
+ *
+ * @author rashah
+ */
+public class GVFrequencyFilterTest
+{
+
+  private Connector cellLevelConn;
+  private Connector serializedConn;
+  private static final String TABLE = "partition";
+  private static final Authorizations AUTHS = new 
Authorizations("ALPHA,BETA,GAMMA".split(","));
+
+
+
+  protected Connector getSerializedConnector()
+  {
+    if (serializedConn == null)
+    {
+      serializedConn = SampleGVData.initConnector();
+      SampleGVData.writeDenSerialized(serializedConn, 
SampleGVData.sampleData());
+    }
+    return serializedConn;
+  }
+
+
+
+  protected Scanner getSerializedScanner()
+  {
+    Connector c = getSerializedConnector();
+    try
+    {
+      return c.createScanner(TABLE, AUTHS);
+    }
+    catch (TableNotFoundException e)
+    {
+      return null;
+    }
+  }
+
+  protected Scanner setUpGVDFFilter(Scanner s, String Frequency)
+  {
+    try
+    {
+      s.clearScanIterators();
+  
+      s.setScanIterators(50, FilteringIterator.class.getName(), "gvff");
+      s.setScanIteratorOption("gvff", "0", GVFrequencyFilter.class.getName());
+      s.setScanIteratorOption("gvff", "0." + 
GVFrequencyFilter.OPTIONFrequency, Frequency);
+
+    }
+    catch (IOException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return s;
+  }
+
+  protected String checkSerialized(Scanner s)
+  {
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (Entry<Key, Value> e : s)
+    {
+
+      if (!first)
+      {
+        sb.append(",");
+      }
+      else
+      {
+        first = false;
+      }
+
+      String colq = e.getKey().getColumnQualifier().toString();
+
+      //System.out.println(e.getKey()+"\t"+e.getValue());
+
+      sb.append(colq);
+    }
+    return sb.toString();
+  }
+
+  @Test
+  public void testNoMatch()
+  {
+
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), "2000000000");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).isEmpty());
+  }
+
+  @Test
+  public void testSingleMatch()
+  {
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), "1500000000");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).equals("01"));
+  }
+
+
+  @Test
+  public void testDoubleMatch()
+  {
+    Scanner s = setUpGVDFFilter(getSerializedScanner(), "1200000000");
+    s.setRange(new Range());
+
+    assertTrue(checkSerialized(s).equals("01,03"));
+  }
+
+  @Test
+  public void testDummyTest()
+  {
+    assertTrue(true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/test/java/IteratorTest.java
----------------------------------------------------------------------
diff --git a/partition/common-query/src/test/java/IteratorTest.java 
b/partition/common-query/src/test/java/IteratorTest.java
new file mode 100644
index 0000000..1b5cf14
--- /dev/null
+++ b/partition/common-query/src/test/java/IteratorTest.java
@@ -0,0 +1,554 @@
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+import ss.cloudbase.core.iterators.CellLevelFilteringIterator;
+import ss.cloudbase.core.iterators.CellLevelRecordIterator;
+import ss.cloudbase.core.iterators.ConversionIterator;
+import ss.cloudbase.core.iterators.GMDenIntersectingIterator;
+import ss.cloudbase.core.iterators.SortedMinIterator;
+import ss.cloudbase.core.iterators.SortedRangeIterator;
+import ss.cloudbase.core.iterators.UniqueIterator;
+import ss.cloudbase.core.iterators.filter.CBConverter;
+import cloudbase.core.client.Connector;
+import cloudbase.core.client.Scanner;
+import cloudbase.core.client.TableNotFoundException;
+import cloudbase.core.data.Key;
+import cloudbase.core.data.PartialKey;
+import cloudbase.core.data.Range;
+import cloudbase.core.data.Value;
+import cloudbase.core.security.Authorizations;
+
+public class IteratorTest {
+       private Connector cellLevelConn;
+       private Connector serializedConn;
+       
+       private static final String TABLE = "partition";
+       private static final Authorizations AUTHS = new 
Authorizations("ALPHA,BETA,GAMMA".split(","));
+       
+       public IteratorTest() {
+               
+       }
+       
+       protected Connector getCellLevelConnector() {
+               if (cellLevelConn == null) {
+                       cellLevelConn = SampleData.initConnector();
+                       SampleData.writeDenCellLevel(cellLevelConn, 
SampleData.sampleData());
+               }
+               return cellLevelConn;
+       }
+       
+       protected Connector getSerializedConnector() {
+               if (serializedConn == null) {
+                       serializedConn = SampleData.initConnector();
+                       SampleData.writeDenSerialized(serializedConn, 
SampleData.sampleData());
+                       SampleData.writeDenProvenance(serializedConn);
+                       SampleData.writeMinIndexes(serializedConn);
+               }
+               return serializedConn;
+       }
+       
+       protected Scanner getProvenanceScanner() {
+               Connector c = getSerializedConnector();
+               try {
+                       return c.createScanner("provenance", AUTHS);
+               } catch (TableNotFoundException e) {
+                       return null;
+               }
+       }
+       
+       protected Scanner getCellLevelScanner() {
+               Connector c = getCellLevelConnector();
+               try {
+                       return c.createScanner(TABLE, AUTHS);
+               } catch (TableNotFoundException e) {
+                       return null;
+               }
+       }
+       
+       protected Scanner getSerializedScanner() {
+               Connector c = getSerializedConnector();
+               try {
+                       return c.createScanner(TABLE, AUTHS);
+               } catch (TableNotFoundException e) {
+                       return null;
+               }
+       }
+       
+       protected Scanner setUpIntersectingIterator(Scanner s, Text[] terms, 
boolean multiDoc) {
+               try {
+                       s.setScanIterators(50, 
GMDenIntersectingIterator.class.getName(), "ii");
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.indexFamilyOptionName, "index");
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.docFamilyOptionName, "event");
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.OPTION_MULTI_DOC, "" + multiDoc);
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.columnFamiliesOptionName, 
GMDenIntersectingIterator.encodeColumns(terms));
+               return s;
+       }
+       
+       protected String checkSerialized(Scanner s) {
+               StringBuilder sb = new StringBuilder();
+               boolean first = true;
+               for (Entry<Key, Value> e: s) {
+                       if (!first) {
+                               sb.append(",");
+                       } else {
+                               first = false;
+                       }
+                       
+                       String colq = 
e.getKey().getColumnQualifier().toString();
+                       
+                       sb.append(colq);
+               }
+               return sb.toString();
+       }
+       
+       protected String checkCellLevel(Scanner s) {
+               StringBuilder sb = new StringBuilder();
+               boolean first = true;
+               for (Entry<Key, Value> e: s) {
+                       String colq = 
e.getKey().getColumnQualifier().toString();
+                       int i = colq.indexOf("\u0000");
+                       if (i > -1) {
+                               if (!first) {
+                                       sb.append(",");
+                               } else {
+                                       first = false;
+                               }
+                               sb.append(colq.substring(0, i));
+                               sb.append(".");
+                               sb.append(colq.substring(i + 1));
+                               sb.append("=");
+                               sb.append(e.getValue().toString());
+                       }
+               }
+               return sb.toString();
+       }
+       
+       @Test
+       public void testSerializedSingleDuplicate() {
+               Text[] terms = new Text[] {
+                       new Text("A"),
+                       new Text("A")
+               };
+               
+               String test = "01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testCellLevelSingleDuplicate() {
+               Text[] terms = new Text[] {
+                       new Text("A"),
+                       new Text("A")
+               };
+               String test = 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E";
+               Scanner s = setUpIntersectingIterator(getCellLevelScanner(), 
terms, true);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testSerializedTwoTerms() {
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               // all the evens will come first
+               String test = "02,01,03";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testCellLevelTwoTerms() {
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               
+               String test = 
"02.field0=B,02.field1=C,02.field2=D,02.field3=E,02.field4=F,"
+                       + 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E,"
+                       + 
"03.field0=C,03.field1=D,03.field2=E,03.field3=F,03.field4=G";
+               Scanner s = setUpIntersectingIterator(getCellLevelScanner(), 
terms, true);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testSerializedTwoTermsWithRange() {
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               
+               String test = "02";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range(new Key(new Text("0")), true, new Key(new 
Text("1")), false));
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testCellLevelTwoTermsWithRange() {
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               
+               String test = 
"02.field0=B,02.field1=C,02.field2=D,02.field3=E,02.field4=F";
+               Scanner s = setUpIntersectingIterator(getCellLevelScanner(), 
terms, true);
+               s.setRange(new Range(new Key(new Text("0")), true, new Key(new 
Text("1")), false));
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testSerializedSingleRange() {
+               Text[] terms = new Text[] {
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "A", true, "B", true)),
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "A", true, "B", true))
+               };
+               
+               String test = "02,01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testSerializedMultiRange() {
+               Text[] terms = new Text[] {
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "A", true, "B", true)),
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "B", true, "C", true))
+               };
+               
+               String test = "02,01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testSerializedTermAndRange() {
+               Text[] terms = new Text[] {
+                       new Text("B"),
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "A", true, "E", true))
+               };
+               
+               String test = "02,01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       protected Scanner setUpSortedRangeIterator(Scanner s, boolean multiDoc) 
{
+               try {
+                       s.setScanIterators(50, 
SortedRangeIterator.class.getName(), "ri");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_COLF, "index");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_DOC_COLF, "event");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_LOWER_BOUND, "A");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_UPPER_BOUND, "C");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_START_INCLUSIVE, "true");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_END_INCLUSIVE, "true");
+                       s.setScanIteratorOption("ri", 
SortedRangeIterator.OPTION_MULTI_DOC, "" + multiDoc);
+                       return s;
+               } catch (IOException e) {
+                       e.printStackTrace();
+                       return null;
+               }
+       }
+       
+       @Test
+       public void testSerializedSortedRangeIterator() {
+               Scanner s = setUpSortedRangeIterator(getSerializedScanner(), 
false);
+               String test = "02,01,03";
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testCellLevelSortedRangeIterator() {
+               Scanner s = setUpSortedRangeIterator(getCellLevelScanner(), 
true);
+               String test = 
"02.field0=B,02.field1=C,02.field2=D,02.field3=E,02.field4=F,"
+                       + 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E,"
+                       + 
"03.field0=C,03.field1=D,03.field2=E,03.field3=F,03.field4=G";
+               s.setRange(new Range());
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testUniqueIterator() {
+               Scanner s = getProvenanceScanner();
+               try {
+                       s.setScanIterators(50, UniqueIterator.class.getName(), 
"skipper");
+                       Key start = new Key(new Text("sid1"));
+                       s.setRange(new Range(start, 
start.followingKey(PartialKey.ROW)));
+                       
+                       int count = 0;
+                       for (Entry<Key, Value> e: s) {
+                               count++;
+                       }
+                       
+                       assertEquals(count, 3);
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+       }
+       
+       protected Scanner setUpConversionIterator(Scanner s) {
+               String[] conversions = new String[] {
+                       "field0 + 10",
+                       "field1 - 10",
+                       "field2 * 10",
+                       "field3 / 10",
+                       "field4 % 10"
+               };
+               
+               try {
+                       s.setScanIterators(50, 
ConversionIterator.class.getName(), "ci");
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               
+               s.setScanIteratorOption("ci", 
ConversionIterator.OPTION_CONVERSIONS, 
ConversionIterator.encodeConversions(conversions));
+               Key start = new Key(new Text("1"), new Text("event"), new 
Text("01"));
+               s.setRange(new Range(start, true, 
start.followingKey(PartialKey.ROW_COLFAM_COLQUAL), false));
+               
+               return s;
+       }
+       
+       @Test
+       public void testConversionIteratorSerialized() {
+               Scanner s = getSerializedScanner();
+               s = setUpConversionIterator(s);
+               
+               CBConverter c = new CBConverter();
+               
+               boolean test = true;
+               Map<String, Double> expected = new HashMap<String, Double>();
+               
+               expected.put("field0", 20.0);
+               expected.put("field1", 1.0);
+               expected.put("field2", 120.0);
+               expected.put("field3", 1.3);
+               expected.put("field4", 4.0);
+               
+               Map<String, String> record;
+               
+               for (Entry<Key, Value> e: s) {
+                       record = c.toMap(e.getKey(), e.getValue());
+                       
+                       for (Entry<String, String> pair: record.entrySet()) {
+                               test = test && 
expected.get(pair.getKey()).equals(new 
Double(Double.parseDouble(record.get(pair.getKey()))));
+                       }
+               }
+               
+               assertTrue(test);
+       }
+       
+       @Test
+       public void testConversionIteratorCellLevel() {
+               Scanner s = getCellLevelScanner();
+               s = setUpConversionIterator(s);
+               s.setScanIteratorOption("ci", 
ConversionIterator.OPTION_MULTI_DOC, "true");
+               
+               boolean test = true;
+               Map<String, Double> expected = new HashMap<String, Double>();
+               
+               expected.put("field0", 20.0);
+               expected.put("field1", 1.0);
+               expected.put("field2", 120.0);
+               expected.put("field3", 1.3);
+               expected.put("field4", 4.0);
+               
+               for (Entry<Key, Value> e: s) {
+                       String field = getField(e.getKey());
+                       if (field != null) {
+                               test = test && expected.get(field).equals(new 
Double(Double.parseDouble(e.getValue().toString())));
+                       }
+               }
+               
+               assertTrue(test);
+       }
+       
+       protected String getField(Key key) {
+               String colq = key.getColumnQualifier().toString();
+               int start = colq.indexOf("\u0000");
+               if (start == -1) {
+                       return null;
+               }
+               
+               int end = colq.indexOf("\u0000", start + 1);
+               if (end == -1) {
+                       end = colq.length();
+               }
+               
+               return colq.substring(start + 1, end);
+       }
+       
+       @Test
+       public void testCellLevelOGCFilter() {
+               Scanner s = getCellLevelScanner();
+               s.fetchColumnFamily(new Text("event"));
+               
+               try {
+                       s.setScanIterators(60, 
CellLevelFilteringIterator.class.getName(), "fi");
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               
+               s.setScanIteratorOption("fi", 
CellLevelFilteringIterator.OPTION_FILTER, 
"<PropertyIsBetween><PropertyName>field0</PropertyName>"
+                       + "<LowerBoundary><Literal>A</Literal></LowerBoundary>"
+                       + "<UpperBoundary><Literal>C</Literal></UpperBoundary>"
+                       + "</PropertyIsBetween>");
+               
+               String test = 
"02.field0=B,02.field1=C,02.field2=D,02.field3=E,02.field4=F,"
+                       + 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E,"
+                       + 
"03.field0=C,03.field1=D,03.field2=E,03.field3=F,03.field4=G";
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testMultiLevelIterator() {
+               Scanner s = getCellLevelScanner();
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               
+               s = setUpIntersectingIterator(s, terms, true);
+               
+               try {
+                       s.setScanIterators(60, 
CellLevelFilteringIterator.class.getName(), "fi");
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               
+               s.setScanIteratorOption("fi", 
CellLevelFilteringIterator.OPTION_FILTER, 
"<PropertyIsEqualTo><PropertyName>field0</PropertyName>"
+                       + "<Literal>A</Literal>"
+                       + "</PropertyIsEqualTo>");
+               
+               String test = 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E";
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testMultiLevelIterator2() {
+               Scanner s = getCellLevelScanner();
+               s = setUpSortedRangeIterator(s, true);
+               try {
+                       s.setScanIterators(60, 
CellLevelFilteringIterator.class.getName(), "fi");
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               s.setScanIteratorOption("fi", 
CellLevelFilteringIterator.OPTION_FILTER, 
"<PropertyIsEqualTo><PropertyName>field0</PropertyName>"
+                       + "<Literal>A</Literal>"
+                       + "</PropertyIsEqualTo>");
+               
+               String test = 
"01.field0=A,01.field1=B,01.field2=C,01.field3=D,01.field4=E";
+               assertTrue(test.equals(checkCellLevel(s)));
+       }
+       
+       @Test
+       public void testCellLevelRecordIterator() {
+               Scanner s = getCellLevelScanner();
+               s = setUpSortedRangeIterator(s, true);
+               try {
+                       s.setScanIterators(60, 
CellLevelRecordIterator.class.getName(), "recordItr");
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+               
+//             for (Entry<Key, Value> e: s) {
+//                     String v = e.getValue().toString();
+//                     v = v.replaceAll("\\u0000", ",");
+//                     v = v.replaceAll("\\uFFFD", "=");
+//                     System.out.println(e.getKey() + "\t" + v);
+//             }
+               String test = "02,01,03";
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testIntersectionWithoutDocLookup() {
+               Text[] terms = new Text[] {
+                       new Text("C"),
+                       new Text("D")
+               };
+               // all the evens will come first
+               String test = "\u000002,\u000001,\u000003";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.OPTION_DOC_LOOKUP, "false");
+               s.setRange(new Range());
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testSimpleNot() {
+               Text[] terms = new Text[] {
+                       new Text("B"),
+                       new Text("F")
+               };
+               
+               boolean[] nots = new boolean[] {
+                       false,
+                       true
+               };
+               
+               String test="01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.notFlagOptionName, 
GMDenIntersectingIterator.encodeBooleans(nots));
+               s.setRange(new Range());
+               
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testRangeNot() {
+               Text[] terms = new Text[] {
+                       new Text("B"),
+                       new 
Text(GMDenIntersectingIterator.getRangeTerm("index", "F", true, "H", true))
+               };
+               
+               boolean[] nots = new boolean[] {
+                       false,
+                       true
+               };
+               
+               String test = "01";
+               Scanner s = setUpIntersectingIterator(getSerializedScanner(), 
terms, false);
+               s.setScanIteratorOption("ii", 
GMDenIntersectingIterator.notFlagOptionName, 
GMDenIntersectingIterator.encodeBooleans(nots));
+               s.setRange(new Range());
+               
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+       
+       @Test
+       public void testMinIteratorOnLastKeys() {
+               Scanner s = getSerializedScanner();
+               try {
+                       s.setScanIterators(50, 
SortedMinIterator.class.getName(), "min");
+               } catch (IOException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               s.setScanIteratorOption("min", SortedMinIterator.OPTION_PREFIX, 
"z");
+               s.setRange(new Range());
+               
+               String test = "02,04,06,08,10,01,03,05,07,09";
+               assertTrue(test.equals(checkSerialized(s)));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/test/java/JTSFilterTest.java
----------------------------------------------------------------------
diff --git a/partition/common-query/src/test/java/JTSFilterTest.java 
b/partition/common-query/src/test/java/JTSFilterTest.java
new file mode 100644
index 0000000..8224f64
--- /dev/null
+++ b/partition/common-query/src/test/java/JTSFilterTest.java
@@ -0,0 +1,181 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Map.Entry;
+
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+import ss.cloudbase.core.iterators.GMDenIntersectingIterator;
+import ss.cloudbase.core.iterators.filter.jts.JTSFilter;
+
+import cloudbase.core.client.Connector;
+import cloudbase.core.client.Scanner;
+import cloudbase.core.client.TableNotFoundException;
+import cloudbase.core.data.Key;
+import cloudbase.core.data.Range;
+import cloudbase.core.data.Value;
+import cloudbase.core.iterators.FilteringIterator;
+import cloudbase.core.security.Authorizations;
+
+/**
+ *
+ * @author rashah
+ */
+public class JTSFilterTest
+{
+
+  private Connector cellLevelConn;
+  private Connector serializedConn;
+  private static final String TABLE = "partition";
+  private static final Authorizations AUTHS = new 
Authorizations("ALPHA,BETA,GAMMA".split(","));
+
+
+
+  protected Connector getSerializedConnector()
+  {
+    if (serializedConn == null)
+    {
+      serializedConn = SampleJTSData.initConnector();
+      SampleJTSData.writeDenSerialized(serializedConn, 
SampleJTSData.sampleData());
+    }
+    return serializedConn;
+  }
+
+
+
+  protected Scanner getSerializedScanner()
+  {
+    Connector c = getSerializedConnector();
+    try
+    {
+      return c.createScanner(TABLE, AUTHS);
+    }
+    catch (TableNotFoundException e)
+    {
+      return null;
+    }
+  }
+
+  protected Scanner setUpJTSFilter(Scanner s, String latitude, String 
longitude, boolean change_name)
+  {
+    try
+    {
+  
+      s.setScanIterators(50, FilteringIterator.class.getName(), "gvdf");
+      s.setScanIteratorOption("gvdf", "0", JTSFilter.class.getName());
+      s.setScanIteratorOption("gvdf", "0." + JTSFilter.OPTIONCenterPointLat, 
latitude);
+      s.setScanIteratorOption("gvdf", "0." + JTSFilter.OPTIONCenterPointLon, 
longitude);
+      if (change_name)
+          s.setScanIteratorOption("gvdf", "0." + 
JTSFilter.OPTIONGeometryKeyName, "beam-footprint");
+
+
+    }
+    catch (IOException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return s;
+  }
+
+  protected String checkSerialized(Scanner s)
+  {
+    StringBuilder sb = new StringBuilder();
+    boolean first = true;
+    for (Entry<Key, Value> e : s)
+    {
+
+      if (!first)
+      {
+        sb.append(",");
+      }
+      else
+      {
+        first = false;
+      }
+
+      String colq = e.getKey().getColumnQualifier().toString();
+
+      sb.append(colq);
+    }
+    return sb.toString();
+  }
+
+
+  @Test
+  public void testNoResults()
+  {
+    //London is in niether - 51°30'0.00"N   0° 7'0.00"W
+    String latitude = "51.5";
+    String longitude = "0.11";
+
+    Scanner s = setUpJTSFilter(getSerializedScanner(), latitude, longitude, 
false);
+    s.setRange(new Range());
+
+//    System.out.println("{" + checkSerialized(s) + "}");
+    assertTrue(checkSerialized(s).isEmpty());
+  }
+
+
+  @Test
+  public void testOneResultAmerica()
+  {
+    //This is North America
+    //Points  39°44'21.00"N 104°59'3.00"W (Denver) are in the footprint
+    String latitude = "33";
+    String longitude = "-93.0";
+
+    Scanner s = setUpJTSFilter(getSerializedScanner(), latitude, longitude, 
false);
+    s.setRange(new Range());
+
+    System.out.println("{" + checkSerialized(s) + "}");
+    assertTrue(checkSerialized(s).equals("02"));
+  }
+
+
+  @Test
+  public void testOneResultAustralia()
+  {
+    //This is Australia
+    //Points like 22S 135E are in the beam
+    String latitude = "-9";
+    String longitude = "100.0";
+
+    Scanner s = setUpJTSFilter(getSerializedScanner(), latitude, longitude, 
false);
+    s.setRange(new Range());
+
+    System.out.println("{" + checkSerialized(s) + "}");
+    assertTrue(checkSerialized(s).equals("01"));
+  }
+
+  @Test
+  public void testOneResultHawaii()
+  {
+    // -164 40 - somewhere near hawaii
+
+    //This is Australia
+    //Points like 22S 135E are in the beam
+    String latitude = "40";
+    String longitude = "-164.0";
+
+    Scanner s = setUpJTSFilter(getSerializedScanner(), latitude, longitude, 
true);
+    s.setRange(new Range());
+
+    System.out.println("{" + checkSerialized(s) + "}");
+    assertTrue(checkSerialized(s).equals("03"));
+  }
+
+
+  @Test
+  public void testDummyTest()
+  {
+    assertTrue(true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/92ddfa59/partition/common-query/src/test/java/OGCFilterTest.java
----------------------------------------------------------------------
diff --git a/partition/common-query/src/test/java/OGCFilterTest.java 
b/partition/common-query/src/test/java/OGCFilterTest.java
new file mode 100644
index 0000000..fd54945
--- /dev/null
+++ b/partition/common-query/src/test/java/OGCFilterTest.java
@@ -0,0 +1,163 @@
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hadoop.io.Text;
+import org.junit.Test;
+
+import cloudbase.core.data.Key;
+import cloudbase.core.data.Value;
+import ss.cloudbase.core.iterators.filter.ogc.OGCFilter;
+
+import static org.junit.Assert.*;
+
+public class OGCFilterTest {
+       private Key testKey = new Key(new Text("row"), new Text("colf"), new 
Text("colq"));
+       private Value testValue = new 
Value("uuid~event\uFFFDmy-event-hash-1\u0000date\uFFFD20100819\u0000time~dss\uFFFD212706.000\u0000frequency\uFFFD3.368248181443644E8\u0000latitude\uFFFD48.74571142707959\u0000longitude\uFFFD13.865561564126812\u0000altitude\uFFFD1047.0\u0000datetime\uFFFD2010-08-19T21:27:06.000Z\u0000test~key\uFFFD\u0000key\uFFFDa\uFFFDb".getBytes());
+
+       public OGCFilterTest() {
+
+       }
+
+       private OGCFilter getFilter(String filter) {
+               OGCFilter f = new OGCFilter();
+               Map<String, String> options = new HashMap<String, String>();
+               options.put(OGCFilter.OPTION_FILTER, filter);
+               f.init(options);
+               return f;
+       }
+
+       @Test
+       public void testBBOX() {
+               OGCFilter f = getFilter("<BBOX><gml:Envelope>"
+                       + "<gml:LowerCorner>13 48</gml:LowerCorner>"
+                       + "<gml:UpperCorner>14 49</gml:UpperCorner>"
+                       + "</gml:Envelope></BBOX>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testBetweenStr() {
+               OGCFilter f = 
getFilter("<PropertyIsBetween><PropertyName>datetime</PropertyName>"
+                       + 
"<LowerBoundary><Literal>2010-08-19</Literal></LowerBoundary>"
+                       + 
"<UpperBoundary><Literal>2010-08-20</Literal></UpperBoundary>"
+                       + "</PropertyIsBetween>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testBetweenNum() {
+               OGCFilter f = 
getFilter("<PropertyIsBetween><PropertyName>frequency</PropertyName>"
+                       + 
"<LowerBoundary><Literal>330000000</Literal></LowerBoundary>"
+                       + 
"<UpperBoundary><Literal>340000000</Literal></UpperBoundary>"
+                       + "</PropertyIsBetween>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testEqualStr() {
+               OGCFilter f = 
getFilter("<PropertyIsEqualTo><PropertyName>uuid~event</PropertyName><Literal>my-event-hash-1</Literal></PropertyIsEqualTo>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testEqualNum() {
+               OGCFilter f = 
getFilter("<PropertyIsEqualTo><PropertyName>altitude</PropertyName><Literal>1047</Literal></PropertyIsEqualTo>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testGreaterThanStr() {
+               OGCFilter f = 
getFilter("<PropertyIsGreaterThan><PropertyName>datetime</PropertyName><Literal>2010-08-15</Literal></PropertyIsGreaterThan>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testGreaterThanNum() {
+               OGCFilter f = 
getFilter("<PropertyIsGreaterThan><PropertyName>altitude</PropertyName><Literal>1000</Literal></PropertyIsGreaterThan>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testLessThanStr() {
+               OGCFilter f = 
getFilter("<PropertyIsLessThan><PropertyName>datetime</PropertyName><Literal>2010-08-20</Literal></PropertyIsLessThan>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testLessThanNum() {
+               OGCFilter f = 
getFilter("<PropertyIsLessThan><PropertyName>altitude</PropertyName><Literal>1200</Literal></PropertyIsLessThan>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testLike() {
+               OGCFilter f = 
getFilter("<PropertyIsLike><PropertyName>uuid~event</PropertyName><Literal>*event*</Literal></PropertyIsLike>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testNotEqualNum() {
+               OGCFilter f = 
getFilter("<PropertyIsNotEqualTo><PropertyName>altitude</PropertyName><Literal>1046</Literal></PropertyIsNotEqualTo>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testNull() {
+               OGCFilter f = 
getFilter("<PropertyIsNull><PropertyName>test~key</PropertyName></PropertyIsNull>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testNot() {
+               OGCFilter f = 
getFilter("<Not><PropertyIsEqualTo><PropertyName>altitude</PropertyName><Literal>1047</Literal></PropertyIsEqualTo></Not>");
+               assertFalse(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testAnd() {
+               OGCFilter f = getFilter("<And>"
+                       + 
"<PropertyIsEqualTo><PropertyName>altitude</PropertyName><Literal>1047</Literal></PropertyIsEqualTo>"
+                       + 
"<PropertyIsNull><PropertyName>test~key</PropertyName></PropertyIsNull>"
+                       + "</And>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testOr() {
+               OGCFilter f = getFilter("<Or>"
+                       + 
"<PropertyIsLike><PropertyName>uuid~event</PropertyName><Literal>*event*</Literal></PropertyIsLike>"
+                       + 
"<PropertyIsNull><PropertyName>uuid~event</PropertyName></PropertyIsNull>"
+                       + "</Or>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testNand() {
+               OGCFilter f = getFilter("<Not><And>"
+                       + 
"<PropertyIsNull><PropertyName>uuid~event</PropertyName></PropertyIsNull>"
+                       + 
"<PropertyIsNull><PropertyName>test~key</PropertyName></PropertyIsNull>"
+                       + "</And></Not>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testNor() {
+               OGCFilter f = getFilter("<Not>"
+                       + 
"<PropertyIsNull><PropertyName>uuid~event</PropertyName></PropertyIsNull>"
+                       + 
"<PropertyIsNull><PropertyName>altitude</PropertyName></PropertyIsNull>"
+                       + "</Not>");
+
+               assertTrue(f.accept(testKey, testValue));
+       }
+
+       @Test
+       public void testParse() {
+               OGCFilter f = 
getFilter("<PropertyIsEqualTo><PropertyName>key</PropertyName><Literal>a</Literal></PropertyIsEqualTo>");
+               assertTrue(f.accept(testKey, testValue));
+       }
+}

Reply via email to