/**
   * Given a Selector object and the request parameters it evaluates the Filter Expression in case
   * that it is defined and returns the result.
   *
   * @param sel The Selector that it is being used.
   * @param parameters parameters used for this request.
   * @return a String with the evaluated JavaScript filter expression in case it is defined.
   */
  private String getDefaultFilterExpression(Selector sel, Map<String, String> parameters) {
    if ((sel.getFilterExpression() == null || sel.getFilterExpression().equals(""))) {
      // Nothing to filter
      return "";
    }

    Object result = null;
    try {
      result =
          ParameterUtils.getJSExpressionResult(
              parameters, RequestContext.get().getSession(), sel.getFilterExpression());
    } catch (Exception e) {
      log.error("Error evaluating filter expression: " + e.getMessage(), e);
    }
    if (result != null && !result.toString().equals("")) {
      return NEW_FILTER_CLAUSE + "(" + result.toString() + ")";
    }

    return "";
  }
  /**
   * Returns the selectors HQL query. In case that it contains the '@additional_filters@' String it
   * is replaced by a set of filter clauses.
   *
   * <p>These include a filter clause:
   *
   * <ul>
   *   <li>for the main entity's client by the context's client.
   *   <li>for the main entity's organization by an organization list see {@link #getOrgs(String)}
   *   <li>with Selector's default filter expression.
   *   <li>for each default expression defined on the selector fields.
   *   <li>for each selector field in case exists a value for it on the parameters param.
   * </ul>
   *
   * @param parameters Map of String values with the request parameters.
   * @param sel the selector that it is being retrieved the data.
   * @param xmlDateFormat SimpleDataFormat to be used to parse date Strings.
   * @return a String with the HQL to be executed.
   */
  private String parseOptionalFilters(
      Map<String, String> parameters, Selector sel, SimpleDateFormat xmlDateFormat) {
    String HQL = sel.getHQL();
    if (!HQL.contains(ADDITIONAL_FILTERS)) {
      return HQL;
    }
    final String requestType = parameters.get(SelectorConstants.DS_REQUEST_TYPE_PARAMETER);
    StringBuffer additionalFilter = new StringBuffer();
    final String entityAlias = sel.getEntityAlias();
    // Client filter
    additionalFilter
        .append(entityAlias + ".client.id in ('0', '")
        .append(OBContext.getOBContext().getCurrentClient().getId())
        .append("')");

    // Organization filter
    final String orgs = DataSourceUtils.getOrgs(parameters.get(JsonConstants.ORG_PARAMETER));
    if (StringUtils.isNotEmpty(orgs)) {
      additionalFilter.append(NEW_FILTER_CLAUSE);
      additionalFilter.append(
          entityAlias
              + (sel.getTable().getName().equals("Organization")
                  ? ".id in (" + orgs + ")"
                  : ".organization in (" + orgs + ")"));
    }
    additionalFilter.append(getDefaultFilterExpression(sel, parameters));

    StringBuffer defaultExpressionsFilter = new StringBuffer();
    boolean hasFilter = false;
    List<SelectorField> fields =
        OBDao.getActiveOBObjectList(sel, Selector.PROPERTY_OBUISELSELECTORFIELDLIST);
    HashMap<String, String[]> criteria = getCriteria(parameters);
    for (SelectorField field : fields) {
      if (StringUtils.isEmpty(field.getClauseLeftPart())) {
        continue;
      }
      String operator = null;
      String value = null;
      String[] operatorvalue = null;
      if (criteria != null) {
        operatorvalue = criteria.get(field.getDisplayColumnAlias());
        if (operatorvalue != null) {
          operator = operatorvalue[0];
          value = operatorvalue[1];
        }
      }
      if (StringUtils.isEmpty(value)) {
        value = parameters.get(field.getDisplayColumnAlias());
      }
      // Add field default expression on picklist if it is not already filtered. Default expressions
      // on selector popup are already evaluated and their values came in the parameters object.
      if (field.getDefaultExpression() != null
          && !"Window".equals(requestType)
          && StringUtils.isEmpty(value)) {
        try {
          String defaultValue = "";
          Object defaultValueObject =
              ParameterUtils.getJSExpressionResult(
                  parameters, RequestContext.get().getSession(), field.getDefaultExpression());
          if (defaultValueObject != null) {
            defaultValue = defaultValueObject.toString();
          }
          if (StringUtils.isNotEmpty(defaultValue)) {
            defaultExpressionsFilter.append(NEW_FILTER_CLAUSE);
            defaultExpressionsFilter.append(
                getWhereClause(operator, defaultValue, field, xmlDateFormat, operatorvalue));
          }
        } catch (Exception e) {
          log.error("Error evaluating filter expression: " + e.getMessage(), e);
        }
      }
      if (field.isFilterable() && StringUtils.isNotEmpty(value)) {
        String whereClause = getWhereClause(operator, value, field, xmlDateFormat, operatorvalue);
        if (!hasFilter) {
          additionalFilter.append(NEW_FILTER_CLAUSE);
          additionalFilter.append(" (");
          hasFilter = true;
        } else {
          if ("Window".equals(requestType)) {
            additionalFilter.append(NEW_FILTER_CLAUSE);
          } else {
            additionalFilter.append(NEW_OR_FILTER_CLAUSE);
          }
        }
        additionalFilter.append(whereClause);
      }
    }
    if (hasFilter) {
      additionalFilter.append(")");
    }
    if (defaultExpressionsFilter.length() > 0) {
      additionalFilter.append(defaultExpressionsFilter);
    }
    HQL = HQL.replace(ADDITIONAL_FILTERS, additionalFilter.toString());
    return HQL;
  }