private List<Query> buildGroupIntervalQuery(DataSetGroup group) {
    if (group == null || !group.isSelect()) return null;

    List<Query> result = new LinkedList<Query>();
    String sourceId = group.getColumnGroup().getSourceId();
    ColumnType columnType = metadata.getColumnType(sourceId);
    ElasticSearchDataSetDef def = (ElasticSearchDataSetDef) metadata.getDefinition();

    List<Interval> intervals = group.getSelectedIntervalList();
    for (Interval interval : intervals) {
      Query _result = null;
      boolean isLabelCol = ColumnType.LABEL.equals(columnType);
      boolean isNumericCol = ColumnType.NUMBER.equals(columnType);
      boolean isDateCol = ColumnType.DATE.equals(columnType);
      boolean isTextCol = ColumnType.TEXT.equals(columnType);

      if (isTextCol) {
        throw new IllegalArgumentException(
            "Not supported type ["
                + columnType.name()
                + "] for column with id ["
                + sourceId
                + "] using grouping.");
      }

      if (isLabelCol) {
        String filterValue = valueTypeMapper.formatLabel(def, sourceId, interval.getName());
        _result = new Query(sourceId, Query.Type.TERM);
        _result.setParam(Query.Parameter.VALUE.name(), filterValue);
      } else if (isNumericCol || isDateCol) {
        Object maxValue = interval.getMaxValue();
        Object minValue = interval.getMinValue();
        Object value0 =
            isNumericCol
                ? valueTypeMapper.formatNumeric(def, sourceId, (Double) minValue)
                : valueTypeMapper.formatDate(def, sourceId, (Date) minValue);
        Object value1 =
            isNumericCol
                ? valueTypeMapper.formatNumeric(def, sourceId, (Double) maxValue)
                : valueTypeMapper.formatDate(def, sourceId, (Date) maxValue);
        _result = new Query(sourceId, Query.Type.RANGE);
        _result.setParam(Query.Parameter.GT.name(), value0);
        _result.setParam(Query.Parameter.LT.name(), value1);
      }

      result.add(_result);
    }

    return result;
  }
  private String formatValue(ElasticSearchDataSetDef definition, String columnId, Object value) {
    ColumnType columnType = metadata.getColumnType(columnId);
    boolean isLabelCol = ColumnType.LABEL.equals(columnType);
    boolean isNumericCol = ColumnType.NUMBER.equals(columnType);
    boolean isDateCol = ColumnType.DATE.equals(columnType);
    boolean isTextCol = ColumnType.TEXT.equals(columnType);
    if (isTextCol) {
      return valueTypeMapper.formatText(definition, columnId, (String) value);
    } else if (isLabelCol) {
      return valueTypeMapper.formatLabel(definition, columnId, (String) value);
    } else if (isDateCol) {
      return valueTypeMapper.formatDate(definition, columnId, (Date) value);
    } else if (isNumericCol) {
      return valueTypeMapper.formatNumeric(definition, columnId, (Double) value);
    }

    throw new IllegalArgumentException(
        "Not supported type [" + columnType.name() + "] for column id [" + columnId + "].");
  }
  protected Query buildColumnCoreFunctionFilter(
      CoreFunctionFilter filter, DataSetMetadata metadata) {
    String columnId = filter.getColumnId();
    ColumnType columnType = metadata.getColumnType(columnId);
    ElasticSearchDataSetDef def = (ElasticSearchDataSetDef) metadata.getDefinition();

    Query result = null;

    CoreFunctionType type = filter.getType();
    List params = filter.getParameters();

    if (CoreFunctionType.IS_NULL.equals(type)) {

      result = new Query(Query.Type.NOT);
      Query existResult = new Query(columnId, Query.Type.EXISTS);
      result.setParam(Query.Parameter.FILTER.name(), existResult);

    } else if (CoreFunctionType.NOT_NULL.equals(type)) {

      result = new Query(columnId, Query.Type.EXISTS);

    } else if (CoreFunctionType.EQUALS_TO.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));

      if (ColumnType.LABEL.equals(columnType)) {
        result = new Query(columnId, Query.Type.TERM);
      } else {
        result = new Query(columnId, Query.Type.MATCH);
      }
      result.setParam(Query.Parameter.VALUE.name(), value);

    } else if (CoreFunctionType.LIKE_TO.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));

      if (value != null) {

        if (ColumnType.NUMBER.equals(columnType) || ColumnType.DATE.equals(columnType)) {
          throw new RuntimeException(
              "The operator LIKE can be applied only for LABEL or TEXT column types. The column ["
                  + columnId
                  + "] is type ["
                  + columnType.name()
                  + "}.");
        }

        // TEXT or LABEL columns.
        String indexType = def.getPattern(columnId);
        if (indexType == null || indexType.trim().length() == 0) {
          // Default ELS index type for String fields is ANALYZED.
          indexType = FieldMappingResponse.IndexType.ANALYZED.name();
        }

        // Replace Dashbuilder wildcard characters by the ones used in ELS wildcard query.
        boolean caseSensitive = params.size() < 2 || Boolean.parseBoolean(params.get(1).toString());
        boolean isFieldAnalyzed =
            FieldMappingResponse.IndexType.ANALYZED.name().equalsIgnoreCase(indexType);

        // Case un-sensitive is not supported for not_analyzed string fields.
        if (!isFieldAnalyzed && !caseSensitive) {
          throw new RuntimeException(
              "Case unsensitive is not supported for not_analyzed string fields. Field: ["
                  + columnId
                  + "].");
        }

        String pattern = utils.transformPattern(value.toString());
        boolean isLowerCaseExpandedTerms = isFieldAnalyzed && (!caseSensitive);
        result = new Query(columnId, Query.Type.QUERY_STRING);
        result.setParam(Query.Parameter.DEFAULT_FIELD.name(), columnId);
        result.setParam(Query.Parameter.DEFAULT_OPERATOR.name(), "AND");
        result.setParam(Query.Parameter.QUERY.name(), pattern);
        result.setParam(Query.Parameter.LOWERCASE_EXPANDED_TERMS.name(), isLowerCaseExpandedTerms);
      }

    } else if (CoreFunctionType.NOT_EQUALS_TO.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));

      if (ColumnType.LABEL.equals(columnType)) {
        Query resultMatch = new Query(columnId, Query.Type.TERM);
        resultMatch.setParam(Query.Parameter.VALUE.name(), value);
        result = new Query(columnId, Query.Type.NOT);
        result.setParam(Query.Parameter.FILTER.name(), resultMatch);
      } else {
        Query resultMatch = new Query(columnId, Query.Type.MATCH);
        resultMatch.setParam(Query.Parameter.VALUE.name(), value);
        result = new Query(columnId, Query.Type.BOOL);
        result.setParam(Query.Parameter.MUST_NOT.name(), asList(resultMatch));
      }

    } else if (CoreFunctionType.LOWER_THAN.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));
      result = new Query(columnId, Query.Type.RANGE);
      result.setParam(Query.Parameter.LT.name(), value);

    } else if (CoreFunctionType.LOWER_OR_EQUALS_TO.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));
      result = new Query(columnId, Query.Type.RANGE);
      result.setParam(Query.Parameter.LTE.name(), value);

    } else if (CoreFunctionType.GREATER_THAN.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));
      result = new Query(columnId, Query.Type.RANGE);
      result.setParam(Query.Parameter.GT.name(), value);

    } else if (CoreFunctionType.GREATER_OR_EQUALS_TO.equals(type)) {

      Object value = formatValue(def, columnId, params.get(0));
      result = new Query(columnId, Query.Type.RANGE);
      result.setParam(Query.Parameter.GTE.name(), value);

    } else if (CoreFunctionType.BETWEEN.equals(type)) {

      Object value0 = formatValue(def, columnId, params.get(0));
      Object value1 = formatValue(def, columnId, params.get(1));
      result = new Query(columnId, Query.Type.RANGE);
      result.setParam(Query.Parameter.GT.name(), value0);
      result.setParam(Query.Parameter.LT.name(), value1);

    } else if (CoreFunctionType.TIME_FRAME.equals(type)) {

      TimeFrame timeFrame = TimeFrame.parse(params.get(0).toString());
      if (timeFrame != null) {
        java.sql.Date past = new java.sql.Date(timeFrame.getFrom().getTimeInstant().getTime());
        java.sql.Date future = new java.sql.Date(timeFrame.getTo().getTimeInstant().getTime());
        result = new Query(columnId, Query.Type.RANGE);
        result.setParam(Query.Parameter.GTE.name(), past);
        result.setParam(Query.Parameter.LTE.name(), future);
      }

    } else {
      throw new IllegalArgumentException("Core function type not supported: " + type);
    }

    return result;
  }