public class ProductionLineEventHandler extends EntityPersistenceEventObserver {

  private static Entity[] entities = {
    ModelProvider.getInstance().getEntity(ProductionLine.ENTITY_NAME)
  };
  protected Logger logger = Logger.getLogger(this.getClass());
  private static String BOM_PRODUCTION = "321";

  @Override
  protected Entity[] getObservedEntities() {
    return entities;
  }

  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));
        }
      }
    }
  }
}
/**
 * This event handler listen to events that are fired in the TableTree table. This table is used to
 * define trees for the Tables.
 *
 * <p>This event handler is in charge of ensuring that each table define at most one ADTree table
 */
public class TableTreeEventHandler extends EntityPersistenceEventObserver {

  private static Entity[] entities = {ModelProvider.getInstance().getEntity(TableTree.ENTITY_NAME)};
  private static final String ADTREE_STRUCTURE = "ADTree";

  @Override
  protected Entity[] getObservedEntities() {
    return entities;
  }

  public void onNew(@Observes EntityNewEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    Property treeStructureProperty = entities[0].getProperty(TableTree.PROPERTY_TREESTRUCTURE);
    Property tableProperty = entities[0].getProperty(TableTree.PROPERTY_TABLE);
    String treeStructureValue = (String) event.getCurrentState(treeStructureProperty);
    Table tableValue = (Table) event.getCurrentState(tableProperty);
    checkTreeStructure(tableValue, treeStructureValue, null);
  }

  public void onUpdate(@Observes EntityUpdateEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    Property treeStructureProperty = entities[0].getProperty(TableTree.PROPERTY_TREESTRUCTURE);
    Property tableProperty = entities[0].getProperty(TableTree.PROPERTY_TABLE);
    String treeStructureValue = (String) event.getCurrentState(treeStructureProperty);
    String recordId = event.getId();
    Table tableValue = (Table) event.getCurrentState(tableProperty);
    checkTreeStructure(tableValue, treeStructureValue, recordId);
  }

  /**
   * Checks that no other ADTree structured tree exists for this table, throws an exception if this
   * occurs
   *
   * @param table table being checked
   * @param treeStructure treestructure of the added/updated tree
   * @param recordId null if a new record is being created or id of the record being modified
   */
  private void checkTreeStructure(Table table, String treeStructure, String recordId) {
    if (ADTREE_STRUCTURE.equals(treeStructure)) {
      // Check that there is no other ADTree Defined for this table
      OBCriteria<TableTree> obq = OBDal.getInstance().createCriteria(TableTree.class);
      obq.add(Restrictions.eq(TableTree.PROPERTY_TABLE, table));
      obq.add(Restrictions.eq(TableTree.PROPERTY_TREESTRUCTURE, treeStructure));
      if (recordId != null) {
        obq.add(Restrictions.ne(TableTree.PROPERTY_ID, recordId));
      }
      if (obq.count() > 0) {
        String language = OBContext.getOBContext().getLanguage().getLanguage();
        ConnectionProvider conn = new DalConnectionProvider(false);
        throw new OBException(Utility.messageBD(conn, "OBUIAPP_OneADTreePerTable", language));
      }
    }
  }
}
public class MInOutLineEventHandler extends EntityPersistenceEventObserver {
  private static Entity[] entities = {
    ModelProvider.getInstance().getEntity(ShipmentInOutLine.ENTITY_NAME)
  };
  protected Logger logger = Logger.getLogger(this.getClass());

  @Override
  protected Entity[] getObservedEntities() {
    return entities;
  }

  public void onSave(@Observes EntityNewEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    ShipmentInOutLine shipmentInOutLine = (ShipmentInOutLine) event.getTargetInstance();

    if (shipmentInOutLine.getProduct() == null
        && (shipmentInOutLine.getMovementQuantity().doubleValue() != 0)) {
      throw new OBException(OBMessageUtils.messageBD("ProductNullAndMovementQtyGreaterZero"));
    }
  }

  public void onUpdate(@Observes EntityUpdateEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    ShipmentInOutLine shipmentInOutLine = (ShipmentInOutLine) event.getTargetInstance();

    if (shipmentInOutLine.getProduct() == null
        && (shipmentInOutLine.getMovementQuantity().doubleValue() != 0)) {
      throw new OBException(OBMessageUtils.messageBD("ProductNullAndMovementQtyGreaterZero"));
    }
  }

  public void onDelete(@Observes EntityDeleteEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    checkShipmentOrderRelation((ShipmentInOutLine) event.getTargetInstance());
  }

  private void checkShipmentOrderRelation(ShipmentInOutLine shipmentInOutLine) {
    ConnectionProvider conn = new DalConnectionProvider(false);
    String language = OBContext.getOBContext().getLanguage().getLanguage();
    OBCriteria<ShipmentInOutLine> criteria =
        OBDal.getInstance().createCriteria(ShipmentInOutLine.class);
    criteria.add(
        Restrictions.eq(
            ShipmentInOutLine.PROPERTY_SHIPMENTRECEIPT, shipmentInOutLine.getShipmentReceipt()));

    if (criteria.count() == 1) {
      ShipmentInOut shipmentInOut =
          OBDal.getInstance()
              .get(ShipmentInOut.class, shipmentInOutLine.getShipmentReceipt().getId());
      if (shipmentInOut != null) {
        shipmentInOut.setSalesOrder(null);
        OBDal.getInstance().save(shipmentInOut);
        OBDal.getInstance().flush();
      }
    }
  }
}
  /**
   * Returns the where clause of a selector's field based on the given value.
   *
   * <p>This method based on the DomainType of the selector field returns the filter clause using
   * the clause left part defined on the selector field.
   *
   * <ul>
   *   <li>Numeric Domain Type: Returns an equals clause <i>field.clauseLeftPart = value</i>
   *   <li>Date Domain Type: Returns a multiple clause comparing separately value's day, month and
   *       year.
   *   <li>Boolean Domain Type: Returns an equals clause <i>field.clauseLeftPart = value</i>
   *   <li>Foreign Key Domain Type: Returns an equals clause <i>field.clauseLeftPart.id = value</i>
   *   <li>Unique Id Domain Type: Returns an equals clause <i>field.clauseLeftPart = value</i>
   *   <li>String Domain Type: Compares the clause left part with the value using the lower database
   *       function which to make comparison case insensitive.
   * </ul>
   *
   * @param value String with the value that the selector field's column is filtered by.
   * @param field The SelectorField that is filtered.
   * @param xmlDateFormat SimpleDateFormat to parse the value in case the field is a Date field.
   * @param operatorvalue
   * @return a String with the HQL where clause to filter the field by the given value.
   */
  private String getWhereClause(
      String operator,
      String value,
      SelectorField field,
      SimpleDateFormat xmlDateFormat,
      String[] operatorvalue) {
    String whereClause = "";

    if (operator != null && operator.equals(AdvancedQueryBuilder.EXISTS_QUERY_KEY)) {
      String val = "";
      for (int i = 1; i < operatorvalue.length; i++) {
        val += i > 1 ? " and " : "";
        val += operatorvalue[i];
      }
      return val;
    }

    DomainType domainType =
        ModelProvider.getInstance().getReference(field.getReference().getId()).getDomainType();
    if (domainType.getClass().getSuperclass().equals(BigDecimalDomainType.class)
        || domainType.getClass().equals(LongDomainType.class)) {
      whereClause = field.getClauseLeftPart() + " = " + value;
    } else if (domainType.getClass().equals(DateDomainType.class)) {
      try {
        final Calendar cal = Calendar.getInstance();
        cal.setTime(xmlDateFormat.parse(value));
        whereClause = " (day(" + field.getClauseLeftPart() + ") = " + cal.get(Calendar.DATE);
        whereClause +=
            "\n and month(" + field.getClauseLeftPart() + ") = " + (cal.get(Calendar.MONTH) + 1);
        whereClause +=
            "\n and year(" + field.getClauseLeftPart() + ") = " + cal.get(Calendar.YEAR) + ") ";
      } catch (Exception e) {
        // ignore these errors, just don't filter then
        // add a dummy whereclause to make the query format correct
        whereClause = "1 = 1";
      }
    } else if (domainType instanceof BooleanDomainType) {
      whereClause = field.getClauseLeftPart() + " = " + value;
    } else if (domainType instanceof UniqueIdDomainType) {
      whereClause = field.getClauseLeftPart() + " = '" + value + "'";
    } else if (domainType instanceof ForeignKeyDomainType) {
      // Assume left part definition is full object reference from HQL select
      whereClause = field.getClauseLeftPart() + ".id = '" + value + "'";
    } else if (domainType instanceof StringEnumerateDomainType) {
      // For enumerations value can be in two formats:
      // 1- VAL: in this case the expression should be property='VAL'
      // 2- ["VAL1", "VAL2"] (JSONArray): the expression should be property in ('VAL1', 'VAL2')
      JSONArray values = null;
      if (value.startsWith("[")) {
        try {
          values = new JSONArray(value);
        } catch (JSONException ignore) {
          // It is not a JSONArray: assuming format 1
        }
      }

      if (values == null) {
        // format 1
        whereClause = field.getClauseLeftPart() + " = '" + value + "'";
      } else {
        // format 2
        whereClause = field.getClauseLeftPart() + " IN (";
        for (int i = 0; i < values.length(); i++) {
          if (i > 0) {
            whereClause += ", ";
          }
          try {
            whereClause += "'" + values.getString(i) + "'";
          } catch (JSONException e) {
            log.error("Error parsing values as JSONArray:" + value, e);
          }
        }
        whereClause += ")";
      }
    } else {
      if ("iStartsWith".equals(operator)) {
        whereClause =
            "lower("
                + field.getClauseLeftPart()
                + ") LIKE '"
                + value.toLowerCase().replaceAll(" ", "%")
                + "%'";
      } else {
        whereClause =
            "lower("
                + field.getClauseLeftPart()
                + ") LIKE '%"
                + value.toLowerCase().replaceAll(" ", "%")
                + "%'";
      }
    }
    return whereClause;
  }
 public void setEntity(String entityName) {
   this.entity = ModelProvider.getInstance().getEntity(entityName);
 }
  private static int getSearchKeyColumnLength() {
    final Entity prodEntity = ModelProvider.getInstance().getEntity(Product.ENTITY_NAME);

    final Property searchKeyProperty = prodEntity.getProperty(Product.PROPERTY_SEARCHKEY);
    return searchKeyProperty.getFieldLength();
  }
/**
 * EntityPersistenceEventObserver to listen to modifications in entities that are used to compose
 * the menu. In case they are modified cached global menu is invalidated to generate it again.
 *
 * @see GlobalMenu
 * @author alostale
 */
public class MenuCacheHandler extends EntityPersistenceEventObserver {
  @Inject private GlobalMenu menu;

  private static final String MENU_TABLE_ID = "116";
  private static final String TREENODE_TABLE_ID = "289";

  private static final String WINDOW_TABLE_ID = "105";
  private static final String VIEWDEFINITION_TABLE_ID = "79127717F4514B459D9014C91E793CE9";
  private static final String FORM_TABLE_ID = "376";
  private static final String PROCESS_TABLE_ID = "284";
  private static final String PROCESSDEFINITION_TABLE_ID = "FF80818132D7FB620132D8129D1A0028";

  private static final String WINDOW_ACCESS_TABLE_ID = "201";
  private static final String VIEWDEFINITION_ACCESS_TABLE_ID = "E6F29F8A30BC4603B1D1195051C4F3A6";
  private static final String FORM_ACCESS_TABLE_ID = "378";
  private static final String PROCESS_ACCESS_TABLE_ID = "197";
  private static final String PROCESSDEFINITION_ACCESS_TABLE_ID =
      "FF80818132D85DB50132D860924E0004";

  private static Entity[] entities = {
    ModelProvider.getInstance().getEntityByTableId(MENU_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(TREENODE_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(WINDOW_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(VIEWDEFINITION_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(FORM_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(PROCESS_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(PROCESSDEFINITION_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(WINDOW_ACCESS_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(VIEWDEFINITION_ACCESS_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(FORM_ACCESS_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(PROCESS_ACCESS_TABLE_ID),
    ModelProvider.getInstance().getEntityByTableId(PROCESSDEFINITION_ACCESS_TABLE_ID)
  };

  public void onNew(@Observes EntityNewEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    menu.invalidateCache();
  }

  public void onUpdate(@Observes EntityUpdateEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    menu.invalidateCache();
  }

  public void onDelete(@Observes EntityDeleteEvent event) {
    if (!isValidEvent(event)) {
      return;
    }
    menu.invalidateCache();
  }

  @Override
  protected Entity[] getObservedEntities() {

    return entities;
  }
}