/**
   * Checks to see if all of the values in the list are numeric or not.
   *
   * @param vals
   * @return
   */
  private boolean checkForNonNumeric(DataValue vals) {
    for (DataValue dv : vals.asList()) {

      if (dv.dataType() != DataType.LONG && dv.dataType() != DataType.DOUBLE) {
        return true;
      }
    }

    return false;
  }
  @Override
  public DataValue call(ScriptContext context, Map<String, DataValue> args)
      throws ScriptFunctionException {

    boolean containsNonNumeric;

    DataValue values = args.get("list");
    if (values.asList().size() == 0) {
      return DataValueFactory.longValue(0);
    }

    containsNonNumeric = checkForNonNumeric(values);

    List<DataValue> matching = new ArrayList<>();
    matching.addAll(values.asList());

    // Perform equal to checks
    DataValue equal = args.get(EQUAL_TO);
    if (equal.dataType() != DataType.NULL) {
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.equals(equal)) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    // Perform not checks
    DataValue not = args.get(NOT);
    if (not.dataType() != DataType.NULL) {
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.equals(not) == false) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    // Perform greater than checks.
    DataValue greater = args.get(GREATER_THAN);
    if (greater.dataType() != DataType.NULL) {
      if (containsNonNumeric) {
        throw new ScriptFunctionException(
            "Can not do comparison count if list contains non numeric values.");
      }
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.asDouble() > greater.asDouble()) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    // Perform less than checks
    DataValue less = args.get(LESS_THAN);
    if (less.dataType() != DataType.NULL) {
      if (containsNonNumeric) {
        throw new ScriptFunctionException(
            "Can not do comparison count if list contains non numeric values.");
      }
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.asDouble() < less.asDouble()) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    // Perform at least checks
    DataValue atLeast = args.get(AT_LEAST);
    if (atLeast.dataType() != DataType.NULL) {
      if (containsNonNumeric) {
        throw new ScriptFunctionException(
            "Can not do comparison count if list contains non numeric values.");
      }
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.asDouble() >= atLeast.asDouble()) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    // Perform at most checks
    DataValue atMost = args.get(AT_MOST);
    if (atMost.dataType() != DataType.NULL) {
      if (containsNonNumeric) {
        throw new ScriptFunctionException(
            "Can not do comparison count if list contains non numeric values.");
      }
      List<DataValue> lst = new ArrayList<>();
      for (DataValue dv : matching) {
        if (dv.asDouble() <= atMost.asDouble()) {
          lst.add(dv);
        }
      }

      matching = lst;
    }

    return DataValueFactory.longValue(matching.size());
  }