You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by ts...@apache.org on 2013/01/22 03:35:07 UTC

[1/6] Basic reference interpreter implementation

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/NumericValue.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/NumericValue.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/NumericValue.java
new file mode 100644
index 0000000..f690c67
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/NumericValue.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.drill.common.exceptions.DrillRuntimeException;
+import org.apache.drill.exec.ref.eval.EvaluatorTypes.BasicEvaluator;
+import org.apache.drill.exec.ref.values.ScalarValues.DoubleScalar;
+import org.apache.drill.exec.ref.values.ScalarValues.FloatScalar;
+import org.apache.drill.exec.ref.values.ScalarValues.IntegerScalar;
+import org.apache.drill.exec.ref.values.ScalarValues.LongScalar;
+
+public abstract class NumericValue extends BaseDataValue implements ComparableValue, BasicEvaluator{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(NumericValue.class);
+  
+  
+  public static enum NumericType {
+    // order is important for conversion
+    INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL;
+  }
+  
+  public abstract NumericType getNumericType();
+
+  @Override
+  public int compareTo(DataValue dv2) {
+    NumericValue other = dv2.getAsNumeric();
+    NumericType mutual = getMutualType(this, other);
+    switch(mutual){
+    case BIG_DECIMAL:
+      return this.getAsBigDecimal().compareTo(other.getAsBigDecimal());
+    case BIG_INTEGER:
+      return this.getAsBigInteger().compareTo(other.getAsBigInteger());
+    case DOUBLE:
+      return Double.compare(this.getAsDouble(), other.getAsDouble());
+    case FLOAT:
+      return Float.compare(this.getAsFloat(), other.getAsFloat());
+    case INT:
+      return Integer.compare(this.getAsInt(), other.getAsInt());
+    case LONG:
+      return Long.compare(this.getAsInt(), other.getAsInt());
+    default:
+      throw new UnsupportedOperationException();
+    }
+  }
+  
+  public int getHashCode(double d){
+    Long l = Double.doubleToLongBits(d);
+    return (int)(l ^ (l >>> 32));
+  }
+  
+  @Override
+  public DataValue eval() {
+    return this;
+  }
+
+  private static NumericType getMutualType(NumericValue... values){
+    int ord = 0;
+    for(int i =0; i < values.length; i++){
+      ord = Math.max(ord, values[i].getNumericType().ordinal());
+    }
+    return NumericType.values()[ord]; 
+  }
+  
+
+  
+  @Override
+  public boolean equals(DataValue v) {
+    if(v == null) return false;
+    if(v.getDataType().isNumericType()){
+      return this.compareTo(v) == 0;
+    }else{
+      return false;
+    }
+  }
+
+  
+  public static NumericValue add(NumericValue... values){
+    NumericType mutual = getMutualType(values);
+    switch(mutual){
+    case BIG_DECIMAL:
+      throw new UnsupportedOperationException();
+//      BigDecimal bd = new BigDecimal(0);
+//      for(int i =0; i < values.length; i++){
+//        bd = bd.add(values[i].getAsBigDecimal());
+//      }
+//      return new BigDecimalScalar(bd);
+    case BIG_INTEGER:
+      throw new UnsupportedOperationException();
+//
+//      BigInteger bi = BigInteger.valueOf(0);
+//      for(int i =0; i < values.length; i++){
+//        bi = bi.add(values[i].getAsBigInteger());
+//      }
+//      return new BigIntegerScalar(bi);
+    case DOUBLE:
+      double d = 0d;
+      for(int i =0; i < values.length; i++){
+        d += values[i].getAsDouble();
+      }
+      return new DoubleScalar(d);
+    case FLOAT:
+      float f = 0f;
+      for(int i =0; i < values.length; i++){
+        f += values[i].getAsFloat();
+      }
+      return new FloatScalar(f);      
+    case INT:
+      int x = 0;
+      for(int i =0; i < values.length; i++){
+        x += values[i].getAsInt();
+      }
+      return new IntegerScalar(x);      
+    case LONG:
+      int l = 0;
+      for(int i =0; i < values.length; i++){
+        l += values[i].getAsLong();
+      }
+      return new LongScalar(l);      
+    default:
+      throw new UnsupportedOperationException();
+    }
+  }
+  
+  @Override
+  public boolean supportsCompare(DataValue dv2) {
+    return dv2.getDataType().isNumericType();
+  }
+
+  
+  
+  
+  @Override
+  public NumericValue getAsNumeric() {
+    return this;
+  }
+
+  public long getAsLong(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to a long.", this.getDataType().getName()));
+  }
+  public int getAsInt(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to an int.", this.getDataType().getName()));
+  }
+  public float getAsFloat(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to an float.", this.getDataType().getName()));
+  }
+  public double getAsDouble(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to a double.", this.getDataType().getName()));
+  }
+  public BigDecimal getAsBigDecimal(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to an big decimal.", this.getDataType().getName()));
+  }
+  public BigInteger getAsBigInteger(){
+    throw new DrillRuntimeException(String.format("A %s value can not be implicitly cast to a big integer.", this.getDataType().getName()));
+  }
+  
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ScalarValues.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ScalarValues.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ScalarValues.java
new file mode 100644
index 0000000..56e0b9d
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ScalarValues.java
@@ -0,0 +1,507 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+
+import org.apache.drill.common.expression.types.DataType;
+import org.apache.drill.exec.ref.eval.EvaluatorTypes.BasicEvaluator;
+import org.apache.drill.exec.ref.rops.DataWriter;
+import org.apache.hadoop.io.BytesWritable;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+
+
+public final class ScalarValues {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ScalarValues.class);
+  
+  private ScalarValues(){}
+  
+  public static class StringScalar extends BaseDataValue implements StringValue, ComparableValue, BasicEvaluator {
+    private CharSequence seq;
+
+    public StringScalar(CharSequence seq){
+      this.seq = seq;
+    }
+    
+    @Override
+    public int compareTo(DataValue o) {
+      CharSequence seq1 = seq;
+      CharSequence seq2 = o.getAsStringValue().getString();
+      final int len = Math.min(seq1.length(), seq2.length());
+      for(int i =0; i < len; i++){
+        char c1 = seq1.charAt(i);
+        char c2 = seq2.charAt(i);
+        if(c1 != c2){
+          return c1 - c2;
+        }
+      }
+      return seq1.length() - seq2.length();
+    }
+
+    @Override
+    public boolean supportsCompare(DataValue dv2) {
+      return dv2.getDataType() == DataType.NVARCHAR;
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeCharSequence(seq);
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.NVARCHAR;
+    }
+
+    @Override
+    public StringValue getAsStringValue() {
+      return this;
+    }
+
+    @Override
+    public CharSequence getString() {
+      return seq;
+    }
+    
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+    
+    public DataValue eval(){
+      return this;
+    }
+
+    @Override
+    public String toString() {
+      return "StringScalar [seq=" + seq + "]";
+    }
+
+    @Override
+    public boolean equals(DataValue v) {
+      if(v.getDataType() != this.getDataType()) return false;
+      return seq.equals(v.getAsStringValue().getString());
+    }
+
+    @Override
+    public int hashCode() {
+      return seq.hashCode();
+    }
+  }
+  
+ 
+  
+  public static class BooleanScalar extends BaseDataValue implements BooleanValue, BasicEvaluator{
+    private boolean b;
+    public BooleanScalar(boolean b){
+      this.b = b;
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeBoolean(b);
+    }
+    
+    @Override
+    public boolean getBoolean() {
+      return b;
+    }
+
+    @Override
+    public BooleanValue getAsBooleanValue() {
+      return this;
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.BOOLEAN;
+    }
+
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+
+    @Override
+    public DataValue eval() {
+      return this;
+    }
+
+    @Override
+    public String toString() {
+      return "BooleanScalar [b=" + b + "]";
+    }
+    
+    @Override
+    public boolean equals(DataValue v) {
+      if(v.getDataType() != this.getDataType()) return false;
+      return b == v.getAsBooleanValue().getBoolean();
+    }
+
+
+    @Override
+    public int hashCode() {
+      return b ? 1 : 0;
+    }
+  }
+  
+  public static class LongScalar extends NumericValue{
+    long l;
+    public LongScalar(long l) {
+      this.l = l;
+    }
+    
+    @Override
+    public long getAsLong() {
+      return l;
+    }
+
+    @Override
+    public float getAsFloat() {
+      return l;
+    }
+
+    @Override
+    public double getAsDouble() {
+      return l;
+    }
+
+    @Override
+    public BigInteger getAsBigInteger() {
+      return BigInteger.valueOf(l);
+    }
+
+    @Override
+    public BigDecimal getAsBigDecimal() {
+      return BigDecimal.valueOf(l);
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeSInt64(l);
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.INT64;
+    }
+
+    @Override
+    public NumericType getNumericType() {
+      return NumericType.LONG;
+    }
+    
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return "LongScalar [l=" + l + "]";
+    }
+    
+
+    @Override
+    public int hashCode() {
+      return getHashCode(l);
+    }
+
+  }
+  
+  public static class IntegerScalar extends NumericValue{
+    int i;
+    
+    public IntegerScalar(int i){
+      this.i = i;
+    }
+    
+    @Override
+    public BigInteger getAsBigInteger() {
+      return BigInteger.valueOf(i);
+    }
+
+    @Override
+    public BigDecimal getAsBigDecimal() {
+      return BigDecimal.valueOf(i);
+    }
+    
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeSInt32(i);
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.INT32;
+    }
+
+    @Override
+    public NumericType getNumericType() {
+      return NumericType.INT;
+    }
+
+    @Override
+    public long getAsLong() {
+      return i;
+    }
+
+    @Override
+    public int getAsInt() {
+      return i;
+    }
+
+    @Override
+    public float getAsFloat() {
+      return i;
+    }
+
+    @Override
+    public double getAsDouble() {
+      return i;
+    }
+    
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return "IntegerScalar [i=" + i + "]";
+    }
+
+    
+    @Override
+    public int hashCode() {
+      return getHashCode(i);
+    }
+    
+  }
+  
+
+  
+  public static class FloatScalar extends NumericValue{
+    float f;
+    public FloatScalar(float f){
+      this.f = f;
+    }
+
+    @Override
+    public BigDecimal getAsBigDecimal() {
+      return BigDecimal.valueOf(f);
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeSFloat32(f);
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.FLOAT32;
+    }
+
+    @Override
+    public NumericType getNumericType() {
+      return NumericType.FLOAT;
+    }
+
+    @Override
+    public double getAsDouble() {
+      return f;
+    }
+    
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return "FloatScalar [f=" + f + "]";
+    }
+
+    @Override
+    public int hashCode() {
+      return getHashCode(f);
+    }
+  }
+ 
+  
+  public static class DoubleScalar extends NumericValue{
+    private double d;
+    public DoubleScalar(double d){
+      this.d = d;
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.FLOAT64;
+    }
+
+    @Override
+    public NumericType getNumericType() {
+      return NumericType.DOUBLE;
+    }
+
+
+    @Override
+    public double getAsDouble() {
+      return d;
+    }
+
+
+    @Override
+    public BigDecimal getAsBigDecimal() {
+      return BigDecimal.valueOf(d);
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeSFloat64(d);
+    }
+    
+    @Override
+    public boolean isConstant() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return "DoubleScalar [d=" + d + "]";
+    }
+    
+    @Override
+    public int hashCode() {
+      return getHashCode(d);
+    }
+
+  }
+  
+  public static class BytesScalar extends BaseDataValue implements BytesValue{
+    private BytesWritable.Comparator comparator = new BytesWritable.Comparator();
+    private final static HashFunction HASH = Hashing.murmur3_32();
+
+    private byte[] bytes;
+    public BytesScalar(byte[] value){
+      this.bytes = value;
+    }
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeBytes(bytes);
+    }
+
+    @Override
+    public boolean supportsCompare(DataValue dv2) {
+      return dv2.getDataType() == DataType.BYTES;
+    }
+
+
+    @Override
+    public int compareTo(DataValue other) {
+      byte[] b1 = bytes;
+      byte[] b2 = other.getAsBytesValue().getAsArray();
+      return comparator.compare(b1, 0, bytes.length, b2, 0, bytes.length);
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.BYTES;
+    }
+
+    @Override
+    public byte[] getAsArray() {
+      return bytes;
+    }
+
+    @Override
+    public int getLength() {
+      return bytes.length;
+    }
+
+    @Override
+    public byte get(int pos) {
+      return bytes[pos];
+    }
+
+    @Override
+    public String toString() {
+      return "BytesScalar [bytes=" + Arrays.toString(bytes) + "]";
+    }
+
+    @Override
+    public boolean equals(DataValue v) {
+      if(v.getDataType() != this.getDataType()) return false;
+      BytesValue other = v.getAsBytesValue();
+      if(this.getLength() != other.getLength()) return false;
+      for(int i =0; i < this.getLength(); i++){
+        if(this.get(i) !=  other.get(i)) return false;
+      }
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return HASH.hashBytes(bytes).asInt();
+    }
+  }
+ 
+  
+  
+  static class NullValue extends BaseDataValue{
+
+    @Override
+    public void write(DataWriter writer) throws IOException {
+      writer.writeNullValue();
+    }
+
+    @Override
+    public DataType getDataType() {
+      return DataType.NULL;
+    }
+
+    @Override
+    public String toString() {
+      return "NullValue []";
+    }
+
+    @Override
+    public boolean equals(DataValue v) {
+      // identity since there should be only one.
+      return v == this;
+    }
+
+    @Override
+    public int hashCode() {
+      return 0;
+    }
+    
+    
+    
+    
+  }
+
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleArrayValue.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleArrayValue.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleArrayValue.java
new file mode 100644
index 0000000..d6adefb
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleArrayValue.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.apache.drill.common.expression.types.DataType;
+import org.apache.drill.exec.ref.rops.DataWriter;
+
+
+public class SimpleArrayValue extends BaseArrayValue{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SimpleArrayValue.class);
+
+  private static int padding = 5;
+  private DataValue[] items;
+  private int currentLast = -1;
+  
+  
+  public SimpleArrayValue(int size){
+    items  = new DataValue[size];
+  }
+  
+  public SimpleArrayValue(){
+    this(5);
+  }
+  
+  @Override
+  public void addToArray(int index, DataValue v) {
+    if( !(index < items.length)){
+      DataValue[] newItems = new DataValue[index + padding];
+      System.arraycopy(items, 0, newItems, 0, items.length);
+      this.items = newItems;
+    }
+    items[index] = v;
+    this.currentLast = Math.max(this.currentLast, index);
+  }
+
+  @Override
+  protected DataValue getByArrayIndex(int index) {
+    if(index < items.length){
+      DataValue ret = items[index];
+      if(ret == null) return NULL_VALUE;
+      return ret;
+    }else{
+      return NULL_VALUE;
+    }
+  }
+
+  @Override
+  protected int getNextIndex() {
+    return currentLast+1;
+  }
+
+  public int size(){
+    return currentLast+1;
+  }
+  
+  @Override
+  public void write(DataWriter w) throws IOException {
+    w.writeArrayStart(currentLast+1);
+    for(int i = 0; i <= currentLast; i++){
+      w.writeArrayElementStart();
+      DataValue v = items[i];
+      if(v == null){
+        w.writeNullValue();
+      }else{
+        v.write(w);
+      }
+      w.writeArrayElementEnd();
+    }
+    w.writeArrayEnd();
+  }
+
+  
+  @Override
+  public void append(BaseArrayValue container) {
+    int curLen = size();
+    int otherLen = container.size();
+    
+    // go backwards so the array gets resized first.
+    for(int i = otherLen -1; i > -1; i--){
+      DataValue v = container.getByArrayIndex(otherLen);
+      this.addToArray(i + curLen, v);
+    }
+    
+  }
+
+  @Override
+  public BaseArrayValue getAsArray() {
+    return this;
+  }
+
+  @Override
+  public BaseMapValue getAsMap() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String toString() {
+    return "SimpleArrayValue [items=" + Arrays.toString(items) + ", currentLast=" + currentLast + "]";
+  }
+
+  @Override
+  public boolean equals(DataValue v) {
+    if(v.getDataType() != DataType.MAP) return false;
+    BaseArrayValue other = v.getAsContainer().getAsArray();
+    if(this.size() != other.size()) return false;
+    for(int i =0; i < this.size(); i++){
+      DataValue v1 = this.getByArrayIndex(i);
+      DataValue v2 = other.getByArrayIndex(i);
+      if(!v1.equals(v2)) return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash((Object[]) items);
+  }
+  
+  
+  
+  
+  
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleMapValue.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleMapValue.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleMapValue.java
new file mode 100644
index 0000000..1c596e4
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/SimpleMapValue.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.drill.common.expression.types.DataType;
+import org.apache.drill.exec.ref.exceptions.RecordException;
+import org.apache.drill.exec.ref.rops.DataWriter;
+
+public class SimpleMapValue extends BaseMapValue{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SimpleMapValue.class);
+  
+  private HashMap<CharSequence, DataValue> map = new HashMap<CharSequence, DataValue>();
+
+  
+  @Override
+  public void setByName(CharSequence name, DataValue v) {
+    if( v== null) throw new RecordException(String.format("You attempted to write a null value with the map key of %s.", name), null);
+    map.put(name, v);
+  }
+
+  @Override
+  protected DataValue getByName(CharSequence name) {
+    return map.get(name);
+  }
+
+  @Override
+  public void write(DataWriter w) throws IOException {
+    w.writeMapStart();
+    
+    for(Map.Entry<CharSequence, DataValue> e : map.entrySet()){
+      DataValue v = e.getValue();
+      // skip null values.
+      if(v == null) continue;
+//      logger.debug("Writing key {}", e.getKey());
+      w.writeMapKey(e.getKey());
+      w.writeMapValueStart();
+      v.write(w);
+      w.writeMapValueEnd();
+    }
+    
+    w.writeMapEnd();
+  }
+
+  @Override
+  public Iterator<Entry<CharSequence, DataValue>> iterator() {
+    return map.entrySet().iterator();
+  }
+  
+  @Override
+  public BaseArrayValue getAsArray() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public BaseMapValue getAsMap() {
+    return this;
+  }
+
+  @Override
+  public boolean equals(DataValue v) {
+    if(v == null) return false;
+    if(v.getDataType() != DataType.MAP) return false;
+    BaseMapValue other = v.getAsContainer().getAsMap();
+    for(Entry<CharSequence, DataValue> e : this){
+      DataValue v2 = other.getByName(e.getKey());
+      if(!e.getValue().equals(v2)) return false;
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return map.hashCode();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/StringValue.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/StringValue.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/StringValue.java
new file mode 100644
index 0000000..a4b9c64
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/StringValue.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+public interface StringValue extends DataValue, ComparableValue{
+  public abstract CharSequence getString();
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueReader.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueReader.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueReader.java
new file mode 100644
index 0000000..9adcca0
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueReader.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import org.apache.drill.common.exceptions.DrillRuntimeException;
+import org.apache.drill.common.expression.types.DataType;
+
+public class ValueReader {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ValueReader.class);
+  
+  public static boolean getBoolean(DataValue v){
+    if(v.getDataType() == DataType.BOOLEAN){
+      return v.getAsBooleanValue().getBoolean();
+    }else{
+      throw new DrillRuntimeException(String.format("Unable to get boolean.  Type os a %s", v.getClass().getCanonicalName()));
+    }
+  }
+  
+  public static long getLong(DataValue v){
+    if(v.getDataType().isNumericType()){
+      return v.getAsNumeric().getAsLong();
+    }else{
+      throw new DrillRuntimeException(String.format("Unable to get value.  %s is not a numeric type.", v.getClass().getCanonicalName()));
+    }
+  }
+  public static double getDouble(DataValue v){
+    if(v.getDataType().isNumericType()){
+      return v.getAsNumeric().getAsDouble();
+    }else{
+      throw new DrillRuntimeException(String.format("Unable to get value.  %s is not a numeric type.", v.getClass().getCanonicalName()));
+    }
+  }
+  public static CharSequence getChars(DataValue v){
+    if(v.getDataType() == DataType.NVARCHAR){
+      return v.getAsStringValue().getString();
+    }else{
+      throw new DrillRuntimeException(String.format("Unable to get value.  %s is not a StringValue type.", v.getClass().getCanonicalName()));
+    }
+  }
+  
+  public static String getString(DataValue v){
+    return getChars(v).toString();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueUtils.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueUtils.java b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueUtils.java
new file mode 100644
index 0000000..ac51d3b
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/java/org/apache/drill/exec/ref/values/ValueUtils.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package org.apache.drill.exec.ref.values;
+
+import org.apache.drill.common.expression.PathSegment;
+import org.apache.drill.common.expression.ValueExpressions.CollisionBehavior;
+import org.apache.drill.common.expression.types.DataType;
+import org.apache.drill.exec.ref.exceptions.RecordException;
+
+public class ValueUtils {
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ValueUtils.class);
+  
+  public static DataValue getMergedDataValue(CollisionBehavior behavior, DataValue oldValue, DataValue newValue){
+//    logger.debug("Checking merged to see if merged value should be added.  Segment {}, oldValue: {}, new value: " + newValue, segment, oldValue);
+    if(oldValue == DataValue.NULL_VALUE) return newValue;
+    
+    switch(behavior){
+    case SKIP:
+      return oldValue;
+    case REPLACE: 
+      return newValue;
+    case FAIL:
+      throw new RecordException("Failure while doing query.  The destination specified already contains a value and no collision behavior was provdied.", null);
+    case OBJECTIFY:
+      SimpleMapValue n = new SimpleMapValue();
+      n.setByName("old", oldValue);
+      n.setByName("new",  newValue);
+      return n;
+    case ARRAYIFY:
+      SimpleArrayValue a = new SimpleArrayValue();
+      a.addToArray(0, oldValue);
+      a.addToArray(1, newValue);
+      return a;
+    case MERGE_OVERRIDE:
+      DataType oldT = oldValue.getDataType();
+      DataType newT = oldValue.getDataType();
+      if(oldT == DataType.MAP && newT == DataType.MAP){
+        oldValue.getAsContainer().getAsMap().merge(newValue.getAsContainer().getAsMap());
+        return oldValue;
+      }else if(oldT == DataType.ARRAY && newT == DataType.ARRAY){
+        logger.debug("Merging two arrays. {} and {}", oldValue, newValue);
+        oldValue.getAsContainer().getAsArray().append(newValue.getAsContainer().getAsArray());
+        return oldValue;
+      }else if(oldT == DataType.ARRAY || newT == DataType.ARRAY || oldT == DataType.MAP || newT == DataType.MAP){
+        throw new RecordException(String.format("Failure while doing query.  You requested a merge of values that were incompatibile.  Examples include merging an array and a map or merging a map/array with a scalar.  Merge Types were %s and %s.", oldT.getName(), newT.getName()), null);
+      }else{
+        // scalar type, just override the value.
+        return newValue;
+      }
+    default:
+      throw new UnsupportedOperationException();
+      
+    }
+  }
+  
+  public static DataValue getIntermediateValues(PathSegment missing, DataValue value){
+    if(missing == null) return value;
+
+    DataValue current = missing.isArray() ? new SimpleArrayValue() : new SimpleMapValue();
+    current.addValue(missing, value);
+    return current;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/main/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/main/resources/logback-test.xml b/sandbox/prototype/exec/ref/src/main/resources/logback-test.xml
new file mode 100644
index 0000000..9a53c12
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/main/resources/logback-test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<configuration>
+
+  <appender name="SOCKET" class="de.huxhorn.lilith.logback.appender.ClassicMultiplexSocketAppender">
+    <Compressing>true</Compressing> 
+    <ReconnectionDelay>10000</ReconnectionDelay>
+    <IncludeCallerData>true</IncludeCallerData>
+    <RemoteHosts>localhost</RemoteHosts>
+  </appender>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  
+  <logger name="org.apache.drill" additivity="false">
+    <level value="debug" />
+    <appender-ref ref="SOCKET" />
+    <appender-ref ref="STDOUT" />
+  </logger>
+
+  <root>
+    <level value="error" />
+    <appender-ref ref="SOCKET" />
+    <appender-ref ref="STDOUT" />
+  </root>
+
+        
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/test/resources/donuts.json
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/test/resources/donuts.json b/sandbox/prototype/exec/ref/src/test/resources/donuts.json
new file mode 100644
index 0000000..d9d69fe
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/test/resources/donuts.json
@@ -0,0 +1,129 @@
+
+	{
+		"id": "0001",
+		"type": "donut",
+		"name": "Cake",
+		"ppu": 0.55,
+		"sales": 35,
+
+		"batters":
+			{
+				"batter":
+					[
+						{ "id": "1001", "type": "Regular" },
+						{ "id": "1002", "type": "Chocolate" },
+						{ "id": "1003", "type": "Blueberry" },
+						{ "id": "1004", "type": "Devil's Food" }
+					]
+			},
+		"topping":
+			[
+				{ "id": "5001", "type": "None" },
+				{ "id": "5002", "type": "Glazed" },
+				{ "id": "5005", "type": "Sugar" },
+				{ "id": "5007", "type": "Powdered Sugar" },
+				{ "id": "5006", "type": "Chocolate with Sprinkles" },
+				{ "id": "5003", "type": "Chocolate" },
+				{ "id": "5004", "type": "Maple" }
+			]
+	}
+	{
+		"id": "0002",
+		"type": "donut",
+		"name": "Raised",
+		"ppu": 0.69,
+		"sales": 145,
+		"batters":
+			{
+				"batter":
+					[
+						{ "id": "1001", "type": "Regular" }
+					]
+			},
+		"topping":
+			[
+				{ "id": "5001", "type": "None" },
+				{ "id": "5002", "type": "Glazed" },
+				{ "id": "5005", "type": "Sugar" },
+				{ "id": "5003", "type": "Chocolate" },
+				{ "id": "5004", "type": "Maple" }
+			]
+	}
+	{
+		"id": "0003",
+		"type": "donut",
+		"name": "Old Fashioned",
+		"ppu": 0.55,
+		"sales": 300,
+		
+		"batters":
+			{
+				"batter":
+					[
+						{ "id": "1001", "type": "Regular" },
+						{ "id": "1002", "type": "Chocolate" }
+					]
+			},
+		"topping":
+			[
+				{ "id": "5001", "type": "None" },
+				{ "id": "5002", "type": "Glazed" },
+				{ "id": "5003", "type": "Chocolate" },
+				{ "id": "5004", "type": "Maple" }
+			]
+	}
+		{
+		"id": "0004",
+		"type": "donut",
+		"name": "Filled",
+		"ppu": 0.69,
+		"sales": 14,
+		
+		"batters":
+			{
+				"batter":
+					[
+						{ "id": "1001", "type": "Regular" },
+						{ "id": "1002", "type": "Chocolate" },
+						{ "id": "1003", "type": "Blueberry" },
+						{ "id": "1004", "type": "Devil's Food" }
+					]
+			},
+		"topping":
+			[
+				{ "id": "5001", "type": "None" },
+				{ "id": "5002", "type": "Glazed" },
+				{ "id": "5005", "type": "Sugar" },
+				{ "id": "5007", "type": "Powdered Sugar" },
+				{ "id": "5006", "type": "Chocolate with Sprinkles" },
+				{ "id": "5003", "type": "Chocolate" },
+				{ "id": "5004", "type": "Maple" }
+			],
+		"filling":
+			[
+				{ "id": "6001", "type": "None" },
+				{ "id": "6002", "type": "Raspberry" },
+				{ "id": "6003", "type": "Lemon" },
+				{ "id": "6004", "type": "Chocolate" },
+				{ "id": "6005", "type": "Kreme" }
+			]			
+	}
+		{
+		"id": "0005",
+		"type": "donut",
+		"name": "Apple Fritter",
+		"ppu": 1.00,
+		"sales": 700,
+		
+		"batters":
+			{
+				"batter":
+					[
+						{ "id": "1001", "type": "Regular" }
+					]
+			},
+		"topping":
+			[
+				{ "id": "5002", "type": "Glazed" }
+			]
+	}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/exec/ref/src/test/resources/simple_plan.json
----------------------------------------------------------------------
diff --git a/sandbox/prototype/exec/ref/src/test/resources/simple_plan.json b/sandbox/prototype/exec/ref/src/test/resources/simple_plan.json
new file mode 100644
index 0000000..f4f6b5b
--- /dev/null
+++ b/sandbox/prototype/exec/ref/src/test/resources/simple_plan.json
@@ -0,0 +1,76 @@
+{
+  head:{
+    type:"apache_drill_logical_plan",
+    version:"1",
+    generator:{
+      type:"manual",
+      info:"na"
+    }
+  },
+  sources:[
+    {
+      type:"json",
+      name:"local-logs",
+      files:[
+        "src/test/resources/donuts.json"
+      ]
+    }
+  ],
+  query:[
+    {
+      op:"sequence",
+      do:[
+	    {
+	      op: "scan",
+	      memo: "initial_scan",
+	      ref: "donuts",
+	      source: "local-logs",
+	      selection: {data: "activity"}
+	    },
+	    {
+	      op: "transform",
+	      transforms: [
+	        { ref: "donuts.quanity", expr: "donuts.sales"}
+	      ]
+	    },
+	    { 
+	      op: "filter",
+	      expr: "donuts.ppu < 1.00"
+	    },
+	    {
+	      op: "group",
+	      groupings: [
+	        { ref: "donuts.ppu", expr: "donuts.ppu" }
+	      ]
+	    },
+	    {
+	      op: "aggregate",
+	      type: "simple",
+	      keys: ["donuts.ppu"],
+	      aggregations: [
+	        { ref: "donuts.typeCount",  expr: "count(1)" },
+	        { ref: "donuts.quantity",  expr: "sum(donuts.sales)" },
+	        { ref: "donuts.sales",  expr: "sum(donuts.ppu * donuts.sales)" }
+	      ]
+	    },
+	    { 
+	      op: "order",
+	      orderings: [
+	        {order: "desc", expr: "donuts.ppu" }
+	      ]
+	    },	    
+	    {
+	      op: "project",
+	      projections: [
+	        { ref: "output", expr: "donuts" }
+	      ]
+	    },	    
+	    {
+	      op: "write",
+	      memo: "save file",
+	      file: "file:///opt/data/out.json"
+	    }     
+      ]
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/planner/src/main/java/org/apache/drill/App.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/planner/src/main/java/org/apache/drill/App.java b/sandbox/prototype/planner/src/main/java/org/apache/drill/App.java
deleted file mode 100644
index 201a69c..0000000
--- a/sandbox/prototype/planner/src/main/java/org/apache/drill/App.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.apache.drill;
-
-/**
- * Hello world!
- *
- */
-public class App 
-{
-    public static void main( String[] args )
-    {
-        System.out.println( "Hello World!" );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/planner/src/test/java/org/apache/drill/AppTest.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/planner/src/test/java/org/apache/drill/AppTest.java b/sandbox/prototype/planner/src/test/java/org/apache/drill/AppTest.java
deleted file mode 100644
index 5908f3e..0000000
--- a/sandbox/prototype/planner/src/test/java/org/apache/drill/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.drill;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest 
-    extends TestCase
-{
-    /**
-     * Create the test case
-     *
-     * @param testName name of the test case
-     */
-    public AppTest( String testName )
-    {
-        super( testName );
-    }
-
-    /**
-     * @return the suite of tests being tested
-     */
-    public static Test suite()
-    {
-        return new TestSuite( AppTest.class );
-    }
-
-    /**
-     * Rigourous Test :-)
-     */
-    public void testApp()
-    {
-        assertTrue( true );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/pom.xml
----------------------------------------------------------------------
diff --git a/sandbox/prototype/pom.xml b/sandbox/prototype/pom.xml
index 5ff9617..9d665f1 100644
--- a/sandbox/prototype/pom.xml
+++ b/sandbox/prototype/pom.xml
@@ -3,6 +3,12 @@
 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
+    <parent>
+      <groupId>org.apache</groupId>
+      <artifactId>apache</artifactId>
+      <version>9</version>
+    </parent>
+    
 	<groupId>org.apache.drill</groupId>
 	<artifactId>prototype-parent</artifactId>
 	<version>1.0-SNAPSHOT</version>

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/App.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/App.java b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/App.java
deleted file mode 100644
index 201a69c..0000000
--- a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/App.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.apache.drill;
-
-/**
- * Hello world!
- *
- */
-public class App 
-{
-    public static void main( String[] args )
-    {
-        System.out.println( "Hello World!" );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/238ca97d/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/AppTest.java
----------------------------------------------------------------------
diff --git a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/AppTest.java b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/AppTest.java
deleted file mode 100644
index 5908f3e..0000000
--- a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/AppTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.drill;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Unit test for simple App.
- */
-public class AppTest 
-    extends TestCase
-{
-    /**
-     * Create the test case
-     *
-     * @param testName name of the test case
-     */
-    public AppTest( String testName )
-    {
-        super( testName );
-    }
-
-    /**
-     * @return the suite of tests being tested
-     */
-    public static Test suite()
-    {
-        return new TestSuite( AppTest.class );
-    }
-
-    /**
-     * Rigourous Test :-)
-     */
-    public void testApp()
-    {
-        assertTrue( true );
-    }
-}