package edu.washington.escience.myria.expression;

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

/**
 * Returns a sequence of substrings of a given string, split on a regular expression.
 */
public class NgramExpression extends BinaryExpression {
  /***/
  private static final long serialVersionUID = 1L;

  /**
   * This is not really unused, it's used automagically by Jackson deserialization.
   */
  @SuppressWarnings("unused")
  private NgramExpression() {
    super();
  }

  /**
   * Takes the string to be split and the regex to split it on.
   *
   * @param left the left operand (index of string column).
   * @param right the right operand (regular expression string).
   */
  public NgramExpression(final ExpressionOperator left, final ExpressionOperator right) {
    super(left, right);
  }

  @Override
  public Type getOutputType(final ExpressionOperatorParameter parameters) {
    checkOperandTypes(Type.STRING_TYPE, Type.LONG_TYPE, parameters);
    return Type.STRING_TYPE;
  }

  @Override
  public String getJavaString(final ExpressionOperatorParameter parameters) {
    return new StringBuilder()
        .append("String val = (")
        .append(getLeft().getJavaString(parameters))
        .append(");\n")
        .append("int n = (int) (")
        .append(getRight().getJavaString(parameters))
        .append(");\n")
        .append("int numNgrams = val.length() - n + 1;\n")
        .append("String[] ngrams = new String[numNgrams];\n")
        .append("for (int i = 0; i < numNgrams; ++i) {\n")
        .append("ngrams[i] = val.substring(i, i + n));\n")
        .append("}\n")
        .append("return ngrams;\n")
        .toString();
  }

  @Override
  public String getJavaExpressionWithAppend(final ExpressionOperatorParameter parameters) {
    return new StringBuilder()
        .append("String val = (")
        .append(getLeft().getJavaString(parameters))
        .append(");\n")
        .append("int n = (int) (")
        .append(getRight().getJavaString(parameters))
        .append(");\n")
        .append("int numNgrams = val.length() - n + 1;\n")
        .append(Expression.COUNT)
        .append(".appendInt(numNgrams);\n")
        .append("for (int i = 0; i < numNgrams; ++i) {\n")
        .append(Expression.RESULT)
        .append(".appendString(val.substring(i, i + n));\n")
        .append("}\n")
        .toString();
  }

  @Override
  public boolean hasArrayOutputType() {
    return true;
  }
}

@@ -194,80 +194,79 @@
 ns a
- sequence of substrings of a given string, split on a regular expression
+ll n-character substrings in sequence (%22n-grams%22) from the input string
 .%0A *
@@ -589,48 +589,71 @@
 ing 
-to be split and the regex to split it on
+from which to compute n-grams and the length %60n%60 of each n-gram
 .%0A  
@@ -696,30 +696,19 @@
  (in
-dex of
+put
  string
- column).
+)
 %0A   
@@ -745,35 +745,33 @@
 nd (
-regular expression string).
+value of %60n%60 in %22n-gram%22)
 %0A   

fix javadoc