public ActionForward createBlackListed(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws OperationException, ApplicationException {
    ActionForward fwd = init(mapping, form, request, response);
    if (fwd != null) return fwd;

    Properties ctx = TmkJSPEnv.getCtx(request);
    DefaultForm df = (DefaultForm) form;
    BlackListedBean bean = (BlackListedBean) df.getBean();

    Trx trx = Trx.get(TrxPrefix.getPrefix(), true);

    try {
      trx.start();
      BlackListedManager.createBlackListed(ctx, bean, trx.getTrxName());
      trx.commit();
    } catch (OperationException ex) {
      trx.rollback();
      throw ex;

    } finally {
      trx.close();
    }
    request.setAttribute(Constants.BLACKLISTED_DETAILS, bean);
    return mapping.findForward(CREATE_BLACKLISTED);
  }
  public ActionForward editCheque(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws ApplicationException, OperationException {

    ActionForward fwd = init(mapping, form, request, response);
    if (fwd != null) return fwd;
    Properties ctx = TmkJSPEnv.getCtx(request);
    BlackListForm f = (BlackListForm) form;
    BlackListedBean bean = (BlackListedBean) f.getBean();

    Integer blacklistedID = bean.getBlackListedId();
    if (blacklistedID == null) {
      throw new OperationException(
          "Cannot load Cheque details. Cause BlacklistedId cannot be null!");
    }

    Trx trx = Trx.get(TrxPrefix.getPrefix(), true);
    trx.start();

    try {
      BlackListedManager.editBlackListed(ctx, bean, trx.getTrxName());
      trx.commit();
    } catch (OperationException ex) {
      trx.rollback();
      throw ex;
    } finally {
      trx.close();
    }
    request.getSession().setAttribute(Constants.BLACKLISTED_DETAILS, bean);
    return mapping.findForward(EDIT_CHEQUE);
  }
  /**
   * Notify users
   *
   * @param users AD_User_ID list
   * @param subject email subject
   * @param message email message
   * @param attachments
   * @return how many email were sent
   */
  private int notifyUsers(
      Collection<Integer> users, String subject, String message, Collection<File> attachments) {
    int countMail = 0;
    for (int user_id : users) {
      MUser user = MUser.get(getCtx(), user_id);
      if (user.isNotificationEMail()) {
        if (m_client.sendEMailAttachments(user_id, subject, message, attachments)) {
          countMail++;
        }
      }

      if (user.isNotificationNote()) {
        Trx trx = null;
        try {
          trx = Trx.get(Trx.createTrxName("AP_NU"), true);
          // Notice
          int AD_Message_ID = 52244; /* TODO - Hardcoded message=notes */
          MNote note = new MNote(getCtx(), AD_Message_ID, user_id, trx.getTrxName());
          note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
          note.setTextMsg(message);
          note.saveEx();
          // Attachment
          MAttachment attachment =
              new MAttachment(getCtx(), MNote.Table_ID, note.getAD_Note_ID(), trx.getTrxName());
          for (File f : attachments) {
            attachment.addEntry(f);
          }
          attachment.setTextMsg(message);
          attachment.saveEx();
          countMail++;
          trx.commit();
        } catch (Throwable e) {
          if (trx != null) trx.rollback();
        } finally {
          if (trx != null) trx.close();
        }
      }
    }
    return countMail;
  }
  public ActionForward deactivateCheque(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws ApplicationException, OperationException {

    ActionForward fwd = init(mapping, form, request, response);
    if (fwd != null) return fwd;
    Properties ctx = TmkJSPEnv.getCtx(request);
    BlackListForm f = (BlackListForm) form;
    f.validate(mapping, request);

    BlackListedBean bean = (BlackListedBean) f.getBean();
    Integer blackListedId = bean.getBlackListedId();

    if (blackListedId == null) {
      throw new OperationException(
          "Cannot deactivate Blacklisted Cheques. Cause BlackListed id cannot be null!");
    }

    Trx trx = Trx.get(TrxPrefix.getPrefix(), true);

    try {
      trx.start();
      BlackListedManager.deactivateBListedCheque(ctx, blackListedId.intValue(), trx.getTrxName());
      trx.commit();
    } catch (OperationException e) {
      trx.rollback();
      postGlobalError("error.deactivate.customer", request);
      mapping.getInputForward();
    } finally {
      trx.close();
    }

    return mapping.findForward(DEACTIVATE_CHEQUE);
  }
  /** @param e */
  public void valueChange(ValueChangeEvent e) {
    if (gridTab.isProcessed()) //  only active records
    {
      Object source = e.getSource();
      if (source instanceof WEditor) {
        // Elaine 2009/05/06
        WEditor editor = (WEditor) source;
        GridField gridField = editor.getGridField();

        if (gridField != null) {
          if (!gridField.isEditable(true)) {
            logger.config("(" + gridTab.toString() + ") " + e.getPropertyName());
            return;
          }
        } else if (!editor.isReadWrite()) {
          logger.config("(" + gridTab.toString() + ") " + e.getPropertyName());
          return;
        }
      } else {
        logger.config("(" + gridTab.toString() + ") " + e.getPropertyName());
        return;
      }
    } //  processed
    logger.config(
        "("
            + gridTab.toString()
            + ") "
            + e.getPropertyName()
            + "="
            + e.getNewValue()
            + " ("
            + e.getOldValue()
            + ") "
            + (e.getOldValue() == null ? "" : e.getOldValue().getClass().getName()));

    //  Get Row/Col Info
    GridTable mTable = gridTab.getTableModel();
    int row = gridTab.getCurrentRow();
    int col = mTable.findColumn(e.getPropertyName());
    //
    if (e.getNewValue() == null
        && e.getOldValue() != null
        && e.getOldValue().toString().length() > 0) //  some editors return "" instead of null
      //        	  this is the original code from GridController, don't know what it does there but
      // it breaks ignore button for web ui
      //            mTable.setChanged (true);
      mTable.setValueAt(e.getNewValue(), row, col);
    else {

      Object newValue = e.getNewValue();
      Integer newValues[] = null;

      if (newValue instanceof Integer[]) {
        newValues = ((Integer[]) newValue);
        newValue = newValues[0];

        if (newValues.length > 1) {
          Integer valuesCopy[] = new Integer[newValues.length - 1];
          System.arraycopy(newValues, 1, valuesCopy, 0, valuesCopy.length);
          newValues = valuesCopy;
        } else {
          newValues = null;
        }
      } else if (newValue instanceof Object[]) {
        logger.severe("Multiple values can only be processed for IDs (Integer)");
        throw new IllegalArgumentException(
            "Multiple Selection values not available for this field. " + e.getPropertyName());
      }

      mTable.setValueAt(newValue, row, col);
      //  Force Callout
      if (e.getPropertyName().equals("S_ResourceAssignment_ID")) {
        GridField mField = gridTab.getField(col);
        if (mField != null && mField.getCallout().length() > 0) {
          gridTab.processFieldChange(mField); //  Dependencies & Callout
        }
      }

      if (newValues != null && newValues.length > 0) {
        // Save data, since record need to be used for generating clones.
        if (!gridTab.dataSave(false)) {
          throw new AdempiereException("SaveError");
        }

        // Retrieve the current record ID
        int recordId = gridTab.getKeyID(gridTab.getCurrentRow());

        Trx trx = Trx.get(Trx.createTrxName(), true);
        trx.start();
        try {
          saveMultipleRecords(
              Env.getCtx(),
              gridTab.getTableName(),
              e.getPropertyName(),
              recordId,
              newValues,
              trx.getTrxName());
          trx.commit();
          gridTab.dataRefreshAll();
        } catch (Exception ex) {
          trx.rollback();
          logger.severe(ex.getMessage());
          throw new AdempiereException("SaveError");
        } finally {
          trx.close();
        }
      }
    }
  } // ValueChange
  /** Save */
  public void onOK() {
    log.config("Activity=" + m_activity);
    if (m_activity == null) {
      Clients.showBusy(null, false);
      return;
    }
    int AD_User_ID = Env.getAD_User_ID(Env.getCtx());
    String textMsg = fTextMsg.getValue();
    //
    MWFNode node = m_activity.getNode();

    Object forward = null; // fForward.getValue();

    // ensure activity is ran within a transaction - [ 1953628 ]
    Trx trx = null;
    try {
      trx = Trx.get(Trx.createTrxName("FWFA"), true);
      m_activity.set_TrxName(trx.getTrxName());

      if (forward != null) {
        log.config("Forward to " + forward);
        int fw = ((Integer) forward).intValue();
        if (fw == AD_User_ID || fw == 0) {
          log.log(Level.SEVERE, "Forward User="******"CannotForward");
          trx.rollback();
          trx.close();
          return;
        }
      }
      //	User Choice - Answer
      else if (MWFNode.ACTION_UserChoice.equals(node.getAction())) {
        if (m_column == null) m_column = node.getColumn();
        //	Do we have an answer?
        int dt = m_column.getAD_Reference_ID();
        String value = fAnswerText.getText();
        if (dt == DisplayType.YesNo || dt == DisplayType.List) {
          ListItem li = fAnswerList.getSelectedItem();
          if (li != null) value = li.getValue().toString();
        }
        if (value == null || value.length() == 0) {
          FDialog.error(m_WindowNo, this, "FillMandatory", Msg.getMsg(Env.getCtx(), "Answer"));
          trx.rollback();
          trx.close();
          return;
        }
        //
        log.config("Answer=" + value + " - " + textMsg);
        try {
          m_activity.setUserChoice(AD_User_ID, value, dt, textMsg);
        } catch (Exception e) {
          log.log(Level.SEVERE, node.getName(), e);
          FDialog.error(m_WindowNo, this, "Error", e.toString());
          trx.rollback();
          trx.close();
          return;
        }
      }
      //	User Action
      else {
        log.config("Action=" + node.getAction() + " - " + textMsg);
        try {
          // ensure activity is ran within a transaction
          m_activity.setUserConfirmation(AD_User_ID, textMsg);
        } catch (Exception e) {
          log.log(Level.SEVERE, node.getName(), e);
          FDialog.error(m_WindowNo, this, "Error", e.toString());
          trx.rollback();
          trx.close();
          return;
        }
      }

      trx.commit();
    } finally {
      Clients.showBusy(null, false);
      if (trx != null) trx.close();
    }

    //	Next
    loadActivities();
    display(-1);
  } //	onOK
  /**
   * Check if column exists in database and modify. If not create column.
   *
   * @param tablename
   * @param columnname
   * @param v_AD_Reference_ID
   * @param v_FieldLength
   * @param v_DefaultValue
   * @param v_IsMandatory
   */
  private int createColumn(Properties ctx, MTable table, MColumn column, boolean doAlter) {

    int no = 0;

    String sql = null;
    ResultSet rst = null;
    ResultSet rsc = null;
    Connection conn = null;
    Trx trx = Trx.get(getTrxName(ctx), true);
    if (!trx.commit()) return 0;

    try {
      // Find Column in Database
      conn = trx.getConnection();
      DatabaseMetaData md = conn.getMetaData();
      String catalog = DB.getDatabase().getCatalog();
      String schema = DB.getDatabase().getSchema();
      String tableName = table.getTableName();
      String columnName = column.getColumnName();
      if (DB.isOracle()) {
        tableName = tableName.toUpperCase();
        columnName = columnName.toUpperCase();
      } else if (DB.isPostgreSQL()) {
        tableName = tableName.toLowerCase();
        columnName = columnName.toLowerCase();
      }

      rst = md.getTables(catalog, schema, tableName, new String[] {"TABLE"});
      if (!rst.next()) {
        // table doesn't exist
        sql = table.getSQLCreate();
      } else {
        //
        rsc = md.getColumns(catalog, schema, tableName, columnName);
        if (rsc.next()) {
          if (doAlter) {
            // update existing column
            boolean notNull = DatabaseMetaData.columnNoNulls == rsc.getInt("NULLABLE");
            sql = column.getSQLModify(table, column.isMandatory() != notNull);
          }
        } else {
          // No existing column
          sql = column.getSQLAdd(table);
        }
        rsc.close();
        rsc = null;
      }

      rst.close();
      rst = null;
      // execute modify or add if needed
      if (sql != null && sql.trim().length() > 0) {
        log.info(sql);

        if (sql.indexOf(DB.SQLSTATEMENT_SEPARATOR) == -1) {
          no = DB.executeUpdate(sql, false, trx.getTrxName());
          if (no == -1) return 0;
        } else {
          String statements[] = sql.split(DB.SQLSTATEMENT_SEPARATOR);
          for (int i = 0; i < statements.length; i++) {
            int count = DB.executeUpdate(statements[i], false, trx.getTrxName());
            if (count == -1) {
              return 0;
            }
            no += count;
          }
        }
      }
      trx.commit(true);
    } catch (SQLException e) {
      log.log(Level.SEVERE, e.getLocalizedMessage(), e);
      if (rsc != null) {
        try {
          rsc.close();
        } catch (SQLException e1) {
        }
        rsc = null;
      }
      if (rst != null) {
        try {
          rst.close();
        } catch (SQLException e1) {
        }
        rst = null;
      }
      trx.rollback();
      return 0;
    }

    return 1;
  }