private String substituteContextParameters(String currentWhereClause) {
   // This method will check for any remaining @param@s
   // If there are still some in the whereclause, they will be resolved by calling the getContext()
   // method
   if (!currentWhereClause.contains("@")) {
     return currentWhereClause;
   }
   String localWhereClause = currentWhereClause;
   while (localWhereClause.contains("@")) {
     int firstAtIndex = localWhereClause.indexOf("@");
     String prefix = localWhereClause.substring(0, firstAtIndex);
     String restOfClause = localWhereClause.substring(firstAtIndex + 1);
     int secondAtIndex = restOfClause.indexOf("@");
     if (secondAtIndex == -1) {
       // No second @. We return the clause as it is
       return localWhereClause;
     }
     String suffix = restOfClause.substring(secondAtIndex + 1);
     String param = restOfClause.substring(0, secondAtIndex);
     String paramValue =
         Utility.getContext(
             new DalConnectionProvider(false),
             RequestContext.get().getVariablesSecureApp(),
             param,
             RequestContext.get().getRequestParameter("windowId"));
     localWhereClause = prefix + getTypedParameterAlias() + suffix;
     typedParameters.add(paramValue);
   }
   return localWhereClause;
 }
 public void onUpdate(@Observes EntityUpdateEvent event) {
   if (!isValidEvent(event)) {
     return;
   }
   VariablesSecureApp vars = null;
   try {
     vars = RequestContext.get().getVariablesSecureApp();
   } catch (Exception e) {
     logger.error("Error:", e);
   }
   String currentTabId = vars.getStringParameter("tabId");
   if (BOM_PRODUCTION.equals(currentTabId)) {
     final Entity productionLineEntity =
         ModelProvider.getInstance().getEntity(ProductionLine.ENTITY_NAME);
     final BigDecimal ZERO = new BigDecimal("0");
     final Property productionPlanProperty =
         productionLineEntity.getProperty(ProductionLine.PROPERTY_PRODUCTIONPLAN);
     final Property movementQtyProperty =
         productionLineEntity.getProperty(ProductionLine.PROPERTY_MOVEMENTQUANTITY);
     final ProductionPlan productionPlan =
         (ProductionPlan) event.getCurrentState(productionPlanProperty);
     final BigDecimal currentMovementQty = (BigDecimal) event.getCurrentState(movementQtyProperty);
     final BigDecimal previousMovementQty =
         (BigDecimal) event.getPreviousState(movementQtyProperty);
     OBCriteria<ProductionLine> productionLineCriteria =
         OBDal.getInstance().createCriteria(ProductionLine.class);
     productionLineCriteria.add(
         Restrictions.eq(ProductionLine.PROPERTY_PRODUCTIONPLAN, productionPlan));
     productionLineCriteria.add(Restrictions.gt(ProductionLine.PROPERTY_MOVEMENTQUANTITY, ZERO));
     if (productionLineCriteria.count() > 0 && previousMovementQty != currentMovementQty) {
       if (currentMovementQty.compareTo(ZERO) == 1 && previousMovementQty.compareTo(ZERO) != 1) {
         String language = OBContext.getOBContext().getLanguage().getLanguage();
         ConnectionProvider conn = new DalConnectionProvider(false);
         throw new OBException(
             Utility.messageBD(conn, "@ConsumedProductWithPostiveQty@", language));
       } else if (currentMovementQty.compareTo(ZERO) == -1
           && previousMovementQty.compareTo(ZERO) != -1
           && productionLineCriteria.count() == 1) {
         String language = OBContext.getOBContext().getLanguage().getLanguage();
         ConnectionProvider conn = new DalConnectionProvider(false);
         throw new OBException(
             Utility.messageBD(conn, "@ProducedProductWithNegativeQty@", language));
       }
     }
   }
 }
  /**
   * 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 "";
  }
  public static OBError openClosePeriodControl(String periodControlId) {
    OBError myMessage = new OBError();
    OBContext.setAdminMode(true);
    Process process = null;
    try {
      process = OBDal.getInstance().get(Process.class, "168");
    } finally {
      OBContext.restorePreviousMode();
    }

    Map<String, String> parameters = new HashMap<String, String>();
    final ProcessInstance pinstance =
        CallProcess.getInstance().call(process, periodControlId, parameters);
    VariablesSecureApp vars = RequestContext.get().getVariablesSecureApp();
    try {
      ConnectionProvider conn = new DalConnectionProvider(false);
      myMessage =
          Utility.getProcessInstanceMessage(
              conn, vars, PInstanceProcessData.select(conn, pinstance.getId()));
    } catch (ServletException e) {
      throw new OBException("Failure getting error message", e);
    }
    return myMessage;
  }
  /**
   * 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;
  }
 /**
  * Translate the message, searching the @ parameters, and making use of the ErrorTextParser class
  * to get the appropriated message.
  *
  * @param message String with the message to translate.
  * @return
  */
 public static OBError translateError(String message) {
   VariablesSecureApp vars = RequestContext.get().getVariablesSecureApp();
   final String strLanguage = OBContext.getOBContext().getLanguage().getLanguage();
   return translateError(new DalConnectionProvider(false), vars, strLanguage, message);
 }
 /**
  * Parse the text searching @ parameters to translate.
  *
  * @param text String with the text to translate.
  * @param replaceMap optional Map containing replacement values for the tokens
  * @return String translated.
  */
 public static String parseTranslation(String text, Map<String, String> map) {
   final VariablesSecureApp vars = RequestContext.get().getVariablesSecureApp();
   final String language = OBContext.getOBContext().getLanguage().getLanguage();
   return parseTranslation(new DalConnectionProvider(false), vars, map, language, text);
 }
  /**
   * Translates the filter criteria ({@link #addFilterParameter(String, String)}) to a valid HQL
   * where clause (without the 'where' keyword). After calling this method the method {@link
   * #getNamedParameters()} can be called. Note that currently only filtering on string and boolean
   * properties is supported. Also filtering on the identifier of a referenced business object is
   * supported.
   *
   * @return a valid where clause or an empty string if not set.
   */
  public String getWhereClause() {

    if (whereClause != null) {
      return whereClause;
    }

    // add some default filter parameters
    filterParameters.put(
        JsonConstants.QUERY_PARAM_USER, OBContext.getOBContext().getUser().getId());
    if (!filterParameters.containsKey(JsonConstants.QUERY_PARAM_CLIENT)) {
      filterParameters.put(
          JsonConstants.QUERY_PARAM_CLIENT, OBContext.getOBContext().getUser().getId());
    }

    final SimpleDateFormat simpleDateFormat = JsonUtils.createDateFormat();

    Check.isNotNull(entity, "Entity must be set");

    final StringBuilder sb = new StringBuilder();
    boolean addAnd = false;
    final StringBuilder orgPart = new StringBuilder();
    final List<Property> propertyDone = new ArrayList<Property>();
    String whereParameterValue = null;
    for (String key : filterParameters.keySet()) {
      String value = filterParameters.get(key);

      if (key.equals(JsonConstants.WHERE_PARAMETER)) {
        // there are cases where null is set as a string
        // handle this
        if (value.equals("null") || value.length() == 0) {
          continue;
        }
        whereParameterValue = value;
        continue;
      }

      // handle the case that we should filter on the accessible organizations
      if (key.equals(JsonConstants.ORG_PARAMETER)) {
        if (entity.isOrganizationEnabled() && value != null && value.length() > 0) {
          final Set<String> orgs =
              OBContext.getOBContext().getOrganizationStructureProvider().getNaturalTree(value);
          if (orgs.size() > 0) {
            if (getMainAlias() != null) {
              orgPart.append(" " + getMainAlias() + ".organization in (");
            } else {
              orgPart.append(" organization in (");
            }
            boolean addComma = false;
            for (String org : orgs) {
              if (addComma) {
                orgPart.append(",");
              }
              orgPart.append("'" + org + "'");
              addComma = true;
            }
            orgPart.append(") ");
          }
        }
        continue;
      }

      // determine the property
      final List<Property> properties = JsonUtils.getPropertiesOnPath(getEntity(), key);
      if (properties.isEmpty()) {
        continue;
      }
      final Property property = properties.get(properties.size() - 1);
      // invalid propname, ignore this one
      // TODO: possibly warn about it
      if (property == null || propertyDone.contains(property)) {
        continue;
      }
      propertyDone.add(property);

      // we know the property and the string representation of the value...
      // do the conversion

      if (addAnd) {
        if (doOr) {
          sb.append(" or ");
        } else {
          sb.append(" and ");
        }
      }

      String leftWherePart = null;
      if (isDoOr()) {
        leftWherePart = resolveJoins(properties, key);
      } else if (getMainAlias() != null) {
        leftWherePart = getMainAlias() + "." + key.trim();
      } else {
        leftWherePart = key;
      }

      // get rid of the identifier and replace it with the real property name
      // or with the concatenation if there are multiple parts
      // NOTE: the if and else check against the key variable and not the leftwherepart
      // because the key contains the original string (with the _identifier part).
      // Within the if the leftWherePart is used because it contains the join aliases
      if (key.equals(JsonConstants.IDENTIFIER) || key.endsWith("." + JsonConstants.IDENTIFIER)) {
        // the identifierProperties are read from the owning entity of the
        // property, that should work fine, as this last property is always part of the
        // identifier
        final List<Property> identifierProperties = property.getEntity().getIdentifierProperties();
        Check.isTrue(
            identifierProperties.contains(property),
            "Property " + property + " not part of identifier of " + property.getEntity());
        final String prefix;
        final int index = leftWherePart.lastIndexOf(".");
        if (key.equals(JsonConstants.IDENTIFIER)) {
          prefix = getMainAlias() + ".";
        } else if (index == -1) {
          prefix = "";
        } else {
          // the + 1 makes sure that the dot is included
          prefix = leftWherePart.substring(0, index + 1);
        }
        leftWherePart = createIdentifierLeftClause(identifierProperties, prefix);

        // if the value consists of multiple parts then filtering won't work
        // only search on the first part then, is pragmatic but very workable
        if (value != null && value.contains(IdentifierProvider.SEPARATOR)) {
          final int separatorIndex = value.indexOf(IdentifierProvider.SEPARATOR);
          value = value.substring(0, separatorIndex);
        }
      }

      // NOTE: If you change this part, make sure that you sync the changes with the
      // SelectorDataSourceFilter. Check issue https://issues.openbravo.com/view.php?id=14239

      // NOTE the typedParameters.add call must be done after the call to
      // getTypedParameterAlias, this to get the correct alias codes
      if (key.equals(JsonConstants.IDENTIFIER)) {
        if (textMatching == TextMatching.exact) {
          sb.append(leftWherePart + " = " + getTypedParameterAlias());
          typedParameters.add(value);
        } else if (textMatching == TextMatching.startsWith) {
          sb.append(
              "upper("
                  + leftWherePart
                  + ") like "
                  + getTypedParameterAlias()
                  + " escape '"
                  + ESCAPE_CHAR
                  + "' ");
          typedParameters.add(escapeLike(value.toUpperCase()) + "%");
        } else {
          sb.append(
              "upper("
                  + leftWherePart
                  + ") like "
                  + getTypedParameterAlias()
                  + " escape '"
                  + ESCAPE_CHAR
                  + "' ");
          typedParameters.add("%" + escapeLike(value.toUpperCase()).replaceAll(" ", "%") + "%");
        }
      } else if (!property.isPrimitive()) {
        // an in parameter use it...
        if (value.contains(JsonConstants.IN_PARAMETER_SEPARATOR)) {
          final List<String> values = new ArrayList<String>();
          final String[] separatedValues = value.split(JsonConstants.IN_PARAMETER_SEPARATOR);
          for (String separatedValue : separatedValues) {
            values.add(separatedValue);
          }
          sb.append(leftWherePart + ".id in (" + getTypedParameterAlias() + ")");
          typedParameters.add(values);
        } else {
          sb.append(leftWherePart + ".id = " + getTypedParameterAlias());
          typedParameters.add(value);
        }
      } else if (String.class == property.getPrimitiveObjectType()) {
        if (textMatching == TextMatching.exact) {
          sb.append(leftWherePart + " = " + getTypedParameterAlias());
          typedParameters.add(value);
        } else if (textMatching == TextMatching.startsWith) {
          sb.append(
              "upper("
                  + leftWherePart
                  + ") like "
                  + getTypedParameterAlias()
                  + " escape '"
                  + ESCAPE_CHAR
                  + "' ");
          typedParameters.add(escapeLike(value.toUpperCase()) + "%");
        } else {
          sb.append(
              "upper("
                  + leftWherePart
                  + ") like "
                  + getTypedParameterAlias()
                  + " escape '"
                  + ESCAPE_CHAR
                  + "' ");
          typedParameters.add("%" + escapeLike(value.toUpperCase()).replaceAll(" ", "%") + "%");
        }
      } else if (Boolean.class == property.getPrimitiveObjectType()) {
        final String alias = getTypedParameterAlias();
        typedParameters.add(new Boolean(value));
        sb.append(leftWherePart + " = " + alias);
      } else if (property.isNumericType()) {
        try {
          final String alias = getTypedParameterAlias();
          final BigDecimal bdValue = new BigDecimal(value);
          if (Long.class == property.getPrimitiveObjectType()) {
            typedParameters.add(bdValue.longValue());
          } else if (Integer.class == property.getPrimitiveObjectType()) {
            typedParameters.add(bdValue.intValue());
          } else {
            typedParameters.add(bdValue);
          }
          sb.append(leftWherePart + " = " + alias);
        } catch (NumberFormatException e) {
          // ignore on purpose, incorrect value entered by user
          // add a dummy whereclause to make the query format correct
          sb.append(" 1=1 ");
        }
      } else if (Date.class.isAssignableFrom(property.getPrimitiveObjectType())) {
        try {
          final Calendar cal = Calendar.getInstance();
          cal.setTime(simpleDateFormat.parse(value));
          final String alias1 = getTypedParameterAlias();
          typedParameters.add(cal.get(Calendar.DATE));
          final String alias2 = getTypedParameterAlias();
          typedParameters.add(cal.get(Calendar.MONTH) + 1);
          final String alias3 = getTypedParameterAlias();
          typedParameters.add(cal.get(Calendar.YEAR));
          sb.append(
              " (day("
                  + leftWherePart
                  + ") = "
                  + alias1
                  + " and month("
                  + leftWherePart
                  + ") = "
                  + alias2
                  + " and year("
                  + leftWherePart
                  + ") = "
                  + alias3
                  + ") ");
        } catch (Exception e) {
          // ignore these errors, just don't filter then
          // add a dummy whereclause to make the query format correct
          sb.append(" 1=1 ");
        }

        // } else if (property.isDate() || property.isDatetime()) {
        // NOTE: dates arrive in the format of the user....
        // sb.append(leftWherePart + " = ?");
        // typedParameters.add(value);
      } else {
        // TODO: support this....
        throw new UnsupportedOperationException(
            "Type "
                + property.getPrimitiveObjectType()
                + " not yet supported for parameter "
                + key);
      }
      addAnd = true;
    }

    log.debug("Whereclause for entity " + entity.getName());
    log.debug(sb.toString());
    for (Object param : typedParameters) {
      log.debug(param);
    }
    log.debug("Textmatching " + textMatching);

    if (sb.length() == 0) {
      whereClause = orgPart.length() > 0 ? orgPart.toString() : "";
    } else {
      whereClause =
          "(" + sb.toString() + ")" + (orgPart.length() > 0 ? " and " + orgPart.toString() : "");
    }
    if (whereParameterValue != null) {
      if (whereClause.length() > 0) {
        whereClause = " (" + whereClause + ") and (" + whereParameterValue + ") ";
      } else {
        whereClause = " " + whereParameterValue;
      }
    }
    if (whereClause.trim().length() > 0) {
      whereClause = " where " + whereClause;
    }

    // handle special transactional range parameter
    if (whereClause.contains(JsonConstants.QUERY_PARAM_TRANSACTIONAL_RANGE)) {
      final String alias = getTypedParameterAlias();
      String windowId = RequestContext.get().getRequestParameter("windowId");
      if (windowId == null) {
        windowId = "";
      }
      final String range =
          Utility.getTransactionalDate(
              new DalConnectionProvider(false),
              RequestContext.get().getVariablesSecureApp(),
              windowId);
      final int rangeNum = Integer.parseInt(range);
      final Calendar cal = Calendar.getInstance();
      cal.add(Calendar.DAY_OF_MONTH, -1 * rangeNum);
      whereClause = whereClause.replace(JsonConstants.QUERY_PARAM_TRANSACTIONAL_RANGE, alias);
      typedParameters.add(cal.getTime());
    }

    if (whereClause.contains(JsonConstants.QUERY_PARAM_CLIENT)) {
      final String alias = getTypedParameterAlias();
      String clientId = (String) DalUtil.getId(OBContext.getOBContext().getCurrentClient());
      whereClause = whereClause.replace(JsonConstants.QUERY_PARAM_CLIENT, alias);
      typedParameters.add(clientId);
    }
    whereClause = setRequestParameters(whereClause);
    whereClause = substituteContextParameters(whereClause);

    return whereClause;
  }