package edu.washington.escience.myria.expression;

import java.util.Objects;

import org.apache.commons.lang.StringEscapeUtils;
import org.joda.time.DateTime;

import com.fasterxml.jackson.annotation.JsonProperty;

import edu.washington.escience.myria.Type;
import edu.washington.escience.myria.expression.evaluate.ExpressionOperatorParameter;

/**
 * An expression that returns a constant value.
 */
public class ConstantExpression extends ZeroaryExpression {

  /***/
  private static final long serialVersionUID = 1L;

  /** The type of this object. */
  @JsonProperty
  private final Type valueType;

  /** The value of this object. */
  @JsonProperty
  private final String value;

  /**
   * This is not really unused, it's used automagically by Jackson deserialization.
   */
  @SuppressWarnings("unused")
  private ConstantExpression() {
    valueType = null;
    value = null;
  }

  /**
   * @param type the type of this object.
   * @param value the value of this constant.
   */
  public ConstantExpression(final Type type, final String value) {
    valueType = type;
    this.value = value;
  }

  /**
   * Construct integer constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final int value) {
    valueType = Type.INT_TYPE;
    this.value = String.valueOf(value);
  }

  /**
   * Construct long constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final long value) {
    valueType = Type.LONG_TYPE;
    this.value = String.valueOf(value);
  }

  /**
   * Construct float constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final float value) {
    valueType = Type.FLOAT_TYPE;
    this.value = String.valueOf(value) + "f";
  }

  /**
   * Construct double constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final double value) {
    valueType = Type.DOUBLE_TYPE;
    this.value = String.valueOf(value);
  }

  /**
   * Construct boolean constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final boolean value) {
    valueType = Type.BOOLEAN_TYPE;
    this.value = String.valueOf(value);
  }

  /**
   * Construct datetime constant.
   * 
   * @param value the value of this constant.
   */
  public ConstantExpression(final DateTime value) {
    valueType = Type.DATETIME_TYPE;
    this.value = String.valueOf(value);
  }

  @Override
  public Type getOutputType(final ExpressionOperatorParameter parameters) {
    return valueType;
  }

  @Override
  public String getJavaString(final ExpressionOperatorParameter parameters) {
    switch (valueType) {
      case BOOLEAN_TYPE:
      case DOUBLE_TYPE:
      case FLOAT_TYPE:
      case INT_TYPE:
      case LONG_TYPE:
        return value;
      case DATETIME_TYPE:
        throw new UnsupportedOperationException("using constant value of type DateTime");
      case STRING_TYPE:
        return '\"' + StringEscapeUtils.escapeJava(value) + '\"';
    }
    throw new UnsupportedOperationException("using constant value of type " + valueType);
  }

  @Override
  public int hashCode() {
    return Objects.hash(getClass().getCanonicalName(), valueType, value);
  }

  @Override
  public boolean equals(final Object other) {
    if (other == null || !(other instanceof ConstantExpression)) {
      return false;
    }
    ConstantExpression otherExp = (ConstantExpression) other;
    return Objects.equals(valueType, otherExp.valueType) && Objects.equals(value, otherExp.value);
  }

  /**
   * @return the value
   */
  public String getValue() {
    return value;
  }
}

@@ -124,39 +124,8 @@
 ils;
-%0Aimport org.joda.time.DateTime;
 %0A%0Aim
@@ -1215,36 +1215,29 @@
 alue) %7B%0A    
-valueType = 
+this(
 Type.INT_TYP
@@ -1237,34 +1237,17 @@
 INT_TYPE
-;%0A    this.value =
+,
  String.
@@ -1252,32 +1252,33 @@
 g.valueOf(value)
+)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -1410,36 +1410,29 @@
 alue) %7B%0A    
-valueType = 
+this(
 Type.LONG_TY
@@ -1433,34 +1433,17 @@
 ONG_TYPE
-;%0A    this.value =
+,
  String.
@@ -1448,32 +1448,33 @@
 g.valueOf(value)
+)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -1608,36 +1608,29 @@
 alue) %7B%0A    
-valueType = 
+this(
 Type.FLOAT_T
@@ -1632,34 +1632,17 @@
 OAT_TYPE
-;%0A    this.value =
+,
  String.
@@ -1662,11 +1662,12 @@
 ) + 
-%22f%22
+'f')
 ;%0A  
@@ -1815,36 +1815,29 @@
 alue) %7B%0A    
-valueType = 
+this(
 Type.DOUBLE_
@@ -1840,34 +1840,17 @@
 BLE_TYPE
-;%0A    this.value =
+,
  String.
@@ -1855,32 +1855,33 @@
 g.valueOf(value)
+)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -2019,36 +2019,29 @@
 alue) %7B%0A    
-valueType = 
+this(
 Type.BOOLEAN
@@ -2045,34 +2045,17 @@
 EAN_TYPE
-;%0A    this.value =
+,
  String.
@@ -2060,32 +2060,33 @@
 g.valueOf(value)
+)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -2101,16 +2101,14 @@
 uct 
-datetime
+string
  con
@@ -2206,24 +2206,22 @@
 n(final 
-DateTime
+String
  value) 
@@ -2230,72 +2230,31 @@
     
-valueType = Type.DATETIME_TYPE;%0A    this.value = String.valueOf(
+this(Type.STRING_TYPE, 
 valu

Remove datetime helper, String helper constructor, constructor delegation