Beispiel #1
0
/**
 * Performance Goal
 *
 * @author Jorg Janke
 * @version $Id: MGoal.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $
 */
public class MGoal extends X_PA_Goal {
  /** Logger for class MGoal */
  private static final org.compiere.util.CLogger log =
      org.compiere.util.CLogger.getCLogger(MGoal.class);
  /** */
  private static final long serialVersionUID = 1L;

  /**
   * Get User Goals
   *
   * @param ctx context
   * @param AD_User_ID user
   * @return array of goals
   */
  public static MGoal[] getUserGoals(Ctx ctx) {
    int AD_Role_ID = ctx.getAD_Role_ID();
    MRole role = MRole.get(ctx, AD_Role_ID);
    int AD_User_ID = ctx.getAD_User_ID();

    if (AD_User_ID < 0) return getTestGoals(ctx);
    ArrayList<MGoal> list = new ArrayList<MGoal>();
    String sql =
        "SELECT * FROM PA_Goal g "
            + "WHERE IsActive='Y'"
            + " AND AD_Client_ID=?" //	#1
            + " AND (";
    if (!role.isWebStoreRole()) sql += " (AD_User_ID IS NULL AND AD_Role_ID IS NULL) OR ";
    sql +=
        " AD_User_ID=?" //	#2
            + " OR EXISTS (SELECT * FROM AD_User_Roles ur "
            + "WHERE ?=ur.AD_User_ID AND g.AD_Role_ID=ur.AD_Role_ID AND ur.IsActive='Y')) "
            + "ORDER BY SeqNo";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      pstmt.setInt(1, ctx.getAD_Client_ID());
      pstmt.setInt(2, AD_User_ID);
      pstmt.setInt(3, AD_User_ID);
      rs = pstmt.executeQuery();
      while (rs.next()) {
        MGoal goal = new MGoal(ctx, rs, null);
        goal.updateGoal(false);
        list.add(goal);
      }
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    MGoal[] retValue = new MGoal[list.size()];
    list.toArray(retValue);
    return retValue;
  } //	getUserGoals

  /**
   * Get Accessible Goals
   *
   * @param ctx context
   * @return array of goals
   */
  public static MGoal[] getGoals(Ctx ctx) {
    ArrayList<MGoal> list = new ArrayList<MGoal>();
    String sql = "SELECT * FROM PA_Goal WHERE IsActive='Y' " + "ORDER BY SeqNo";
    sql =
        MRole.getDefault(ctx, false)
            .addAccessSQL(sql, "PA_Goal", false, true); // 	RW to restrict Access
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      rs = pstmt.executeQuery();
      while (rs.next()) {
        MGoal goal = new MGoal(ctx, rs, null);
        goal.updateGoal(false);
        list.add(goal);
      }
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeStatement(pstmt);
      DB.closeResultSet(rs);
    }
    MGoal[] retValue = new MGoal[list.size()];
    list.toArray(retValue);
    return retValue;
  } //	getGoals

  /**
   * Create Test Goals
   *
   * @param ctx context
   * @return array of goals
   */
  public static MGoal[] getTestGoals(Ctx ctx) {
    MGoal[] retValue = new MGoal[4];
    retValue[0] = new MGoal(ctx, "Test 1", "Description 1", new BigDecimal(1000), null);
    retValue[0].setMeasureActual(new BigDecimal(200));
    retValue[1] = new MGoal(ctx, "Test 2", "Description 2", new BigDecimal(1000), null);
    retValue[1].setMeasureActual(new BigDecimal(900));
    retValue[2] = new MGoal(ctx, "Test 3", "Description 3", new BigDecimal(1000), null);
    retValue[2].setMeasureActual(new BigDecimal(1200));
    retValue[3] = new MGoal(ctx, "Test 4", "Description 4", new BigDecimal(1000), null);
    retValue[3].setMeasureActual(new BigDecimal(3200));
    return retValue;
  } //	getTestGoals

  /**
   * Get Goals with Measure
   *
   * @param ctx context
   * @param PA_Measure_ID measure
   * @return goals
   */
  public static MGoal[] getMeasureGoals(Ctx ctx, int PA_Measure_ID) {
    ArrayList<MGoal> list = new ArrayList<MGoal>();
    String sql = "SELECT * FROM PA_Goal WHERE IsActive='Y' AND PA_Measure_ID=? " + "ORDER BY SeqNo";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      pstmt.setInt(1, PA_Measure_ID);
      rs = pstmt.executeQuery();
      while (rs.next()) list.add(new MGoal(ctx, rs, null));
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeStatement(pstmt);
      DB.closeResultSet(rs);
    }
    MGoal[] retValue = new MGoal[list.size()];
    list.toArray(retValue);
    return retValue;
  } //	getMeasureGoals

  /**
   * Get Multiplier from Scope to Display
   *
   * @param goal goal
   * @return null if error or multiplier
   */
  public static BigDecimal getMultiplier(MGoal goal) {
    String MeasureScope = goal.getMeasureScope();
    String MeasureDisplay = goal.getMeasureDisplay();
    if (MeasureDisplay == null || MeasureScope.equals(MeasureDisplay)) return Env.ONE; // 	1:1

    if (MeasureScope.equals(MEASURESCOPE_Total) || MeasureDisplay.equals(MEASUREDISPLAY_Total))
      return null; //	Error

    BigDecimal Multiplier = null;
    if (MeasureScope.equals(MEASURESCOPE_Year)) {
      if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) Multiplier = new BigDecimal(1.0 / 4.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) Multiplier = new BigDecimal(1.0 / 12.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) Multiplier = new BigDecimal(1.0 / 52.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) Multiplier = new BigDecimal(1.0 / 364.0);
    } else if (MeasureScope.equals(MEASURESCOPE_Quarter)) {
      if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) Multiplier = new BigDecimal(4.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) Multiplier = new BigDecimal(1.0 / 3.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) Multiplier = new BigDecimal(1.0 / 13.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) Multiplier = new BigDecimal(1.0 / 91.0);
    } else if (MeasureScope.equals(MEASURESCOPE_Month)) {
      if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) Multiplier = new BigDecimal(12.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) Multiplier = new BigDecimal(3.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) Multiplier = new BigDecimal(1.0 / 4.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) Multiplier = new BigDecimal(1.0 / 30.0);
    } else if (MeasureScope.equals(MEASURESCOPE_Week)) {
      if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) Multiplier = new BigDecimal(52.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) Multiplier = new BigDecimal(13.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) Multiplier = new BigDecimal(4.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Day)) Multiplier = new BigDecimal(1.0 / 7.0);
    } else if (MeasureScope.equals(MEASURESCOPE_Day)) {
      if (MeasureDisplay.equals(MEASUREDISPLAY_Year)) Multiplier = new BigDecimal(364.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Quarter)) Multiplier = new BigDecimal(91.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Month)) Multiplier = new BigDecimal(30.0);
      else if (MeasureDisplay.equals(MEASUREDISPLAY_Week)) Multiplier = new BigDecimal(7.0);
    }
    return Multiplier;
  } //	getMultiplier

  /** Logger */
  private static CLogger s_log = CLogger.getCLogger(MGoal.class);

  /**
   * ************************************************************************ Standard Constructor
   *
   * @param ctx context
   * @param PA_Goal_ID id
   * @param trx p_trx
   */
  public MGoal(Ctx ctx, int PA_Goal_ID, Trx trx) {
    super(ctx, PA_Goal_ID, trx);
    if (PA_Goal_ID == 0) {
      //	setName (null);
      //	setAD_User_ID (0);
      //	setPA_ColorSchema_ID (0);
      setSeqNo(0);
      setIsSummary(false);
      setMeasureScope(MEASUREDISPLAY_Year);
      setGoalPerformance(Env.ZERO);
      setRelativeWeight(Env.ONE);
      setMeasureTarget(Env.ZERO);
      setMeasureActual(Env.ZERO);
    }
  } //	MGoal

  /**
   * Load Constructor
   *
   * @param ctx context
   * @param rs result set
   * @param trx p_trx
   */
  public MGoal(Ctx ctx, ResultSet rs, Trx trx) {
    super(ctx, rs, trx);
  } //	MGoal

  /**
   * Base Constructor
   *
   * @param ctx context
   * @param Name Name
   * @param Description Decsription
   * @param MeasureTarget target
   * @param trx p_trx
   */
  public MGoal(Ctx ctx, String Name, String Description, BigDecimal MeasureTarget, Trx trx) {
    super(ctx, 0, trx);
    setName(Name);
    setDescription(Description);
    setMeasureTarget(MeasureTarget);
  } //	MGoal

  /** Restrictions */
  private MGoalRestriction[] m_restrictions = null;

  /**
   * Get Restriction Lines
   *
   * @param reload reload data
   * @return array of lines
   */
  public MGoalRestriction[] getRestrictions(boolean reload) {
    if (m_restrictions != null && !reload) return m_restrictions;
    ArrayList<MGoalRestriction> list = new ArrayList<MGoalRestriction>();
    //
    String sql =
        "SELECT * FROM PA_GoalRestriction "
            + "WHERE PA_Goal_ID=? AND IsActive='Y' "
            + "ORDER BY Org_ID, C_BPartner_ID, M_Product_ID";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, get_Trx());
      pstmt.setInt(1, getPA_Goal_ID());
      rs = pstmt.executeQuery();
      while (rs.next()) list.add(new MGoalRestriction(getCtx(), rs, get_Trx()));
    } catch (Exception e) {
      log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeStatement(pstmt);
      DB.closeResultSet(rs);
    }
    //
    m_restrictions = new MGoalRestriction[list.size()];
    list.toArray(m_restrictions);
    return m_restrictions;
  } //	getRestrictions

  /**
   * Get Measure
   *
   * @return measure or null
   */
  public MMeasure getMeasure() {
    if (getPA_Measure_ID() != 0) return MMeasure.get(getCtx(), getPA_Measure_ID());
    return null;
  } //	getMeasure

  /**
   * ************************************************************************ Update/save Goals for
   * the same measure
   *
   * @param force force to update goal (default once per day)
   * @return true if updated
   */
  public boolean updateGoal(boolean force) {
    log.config("Force=" + force);
    MMeasure measure = MMeasure.get(getCtx(), getPA_Measure_ID());
    if (force || getDateLastRun() == null || !TimeUtil.isSameHour(getDateLastRun(), null)) {
      if (measure.updateGoals()) // 	saves
      {
        load(get_ID(), get_Trx());
        return true;
      }
    }
    return false;
  } //	updateGoal

  /**
   * Set Measure Actual
   *
   * @param MeasureActual actual
   */
  @Override
  public void setMeasureActual(BigDecimal MeasureActual) {
    if (MeasureActual == null) return;
    super.setMeasureActual(MeasureActual);
    setDateLastRun(new Timestamp(System.currentTimeMillis()));
    setGoalPerformance();
  } //	setMeasureActual

  /** Calculate Performance Goal as multiplier */
  public void setGoalPerformance() {
    BigDecimal MeasureTarget = getMeasureTarget();
    BigDecimal MeasureActual = getMeasureActual();
    BigDecimal GoalPerformance = Env.ZERO;
    if (MeasureTarget.signum() != 0)
      GoalPerformance = MeasureActual.divide(MeasureTarget, 6, BigDecimal.ROUND_HALF_UP);
    super.setGoalPerformance(GoalPerformance);
  } //	setGoalPerformance

  /**
   * Get Goal Performance as Double
   *
   * @return performance as multipier
   */
  public double getGoalPerformanceDouble() {
    BigDecimal bd = getGoalPerformance();
    return bd.doubleValue();
  } //	getGoalPerformanceDouble

  /**
   * Get Goal Performance in Percent
   *
   * @return performance in percent
   */
  public int getPercent() {
    BigDecimal bd = getGoalPerformance().multiply(Env.ONEHUNDRED);
    return bd.intValue();
  } //	getPercent

  /**
   * Get Color
   *
   * @return color - white if no target
   */
  public Color getColor() {
    if (getMeasureTarget().signum() == 0) return Color.white;
    else return MColorSchema.getColor(getCtx(), getPA_ColorSchema_ID(), getPercent());
  } //	getColor

  /**
   * Get the color schema for this goal.
   *
   * @return the color schema, or null if the measure targer is 0
   */
  public MColorSchema getColorSchema() {
    return (getMeasureTarget().signum() == 0)
        ? null
        : MColorSchema.get(getCtx(), getPA_ColorSchema_ID());
  }

  /**
   * Get Measure Display
   *
   * @return Measure Display
   */
  @Override
  public String getMeasureDisplay() {
    String s = super.getMeasureDisplay();
    if (s == null) {
      if (MEASURESCOPE_Week.equals(getMeasureScope())) s = MEASUREDISPLAY_Week;
      else if (MEASURESCOPE_Day.equals(getMeasureScope())) s = MEASUREDISPLAY_Day;
      else s = MEASUREDISPLAY_Month;
    }
    return s;
  } //	getMeasureDisplay

  /**
   * Get Measure Display Text
   *
   * @return Measure Display Text
   */
  public String getXAxisText() {
    MMeasure measure = getMeasure();
    if (measure != null
        && X_PA_Measure.MEASUREDATATYPE_StatusQtyAmount.equals(measure.getMeasureDataType())) {
      if (X_PA_Measure.MEASURETYPE_Request.equals(measure.getMeasureType()))
        return Msg.getElement(getCtx(), "R_Status_ID");
      if (X_PA_Measure.MEASURETYPE_Project.equals(measure.getMeasureType()))
        return Msg.getElement(getCtx(), "C_Phase_ID");
    }
    String value = getMeasureDisplay();
    String display = MRefList.getListName(getCtx(), X_Ref_PA_Goal_Scope.AD_Reference_ID, value);
    return display == null ? value : display;
  } //	getMeasureDisplayText

  /**
   * Goal has Target
   *
   * @return true if target
   */
  public boolean isTarget() {
    return getMeasureTarget().signum() != 0;
  } //	isTarget

  /**
   * String Representation
   *
   * @return info
   */
  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer("MGoal[");
    sb.append(get_ID())
        .append("-")
        .append(getName())
        .append(",")
        .append(getGoalPerformance())
        .append("]");
    return sb.toString();
  } //	toString

  /**
   * Before Save
   *
   * @param newRecord new
   * @return true
   */
  @Override
  protected boolean beforeSave(boolean newRecord) {
    //	if (getMultiplier(this) == null)	//	error
    //		setMeasureDisplay(getMeasureScope());

    //	Measure required if nor Summary
    if (!isSummary() && getPA_Measure_ID() == 0) {
      log.saveError("FillMandatory", Msg.getElement(getCtx(), "PA_Measure_ID"));
      return false;
    }
    if (isSummary() && getPA_Measure_ID() != 0) setPA_Measure_ID(0);

    //	User/Role Check
    if ((newRecord || is_ValueChanged("AD_User_ID") || is_ValueChanged("AD_Role_ID"))
        && getAD_User_ID() != 0) {
      MUser user = MUser.get(getCtx(), getAD_User_ID());
      MRole[] roles = user.getRoles(getAD_Org_ID());
      if (roles.length == 0) // 	No Role
      setAD_Role_ID(0);
      else if (roles.length == 1) // 	One
      setAD_Role_ID(roles[0].getAD_Role_ID());
      else {
        int AD_Role_ID = getAD_Role_ID();
        if (AD_Role_ID != 0) // 	validate
        {
          boolean found = false;
          for (MRole element : roles) {
            if (AD_Role_ID == element.getAD_Role_ID()) {
              found = true;
              break;
            }
          }
          if (!found) AD_Role_ID = 0;
        }
        if (AD_Role_ID == 0) // 	set to first one
        setAD_Role_ID(roles[0].getAD_Role_ID());
      } //	multiple roles
    } //	user check

    return true;
  } //	beforeSave

  /**
   * After Save
   *
   * @param newRecord new
   * @param success success
   * @return true
   */
  @Override
  protected boolean afterSave(boolean newRecord, boolean success) {
    if (!success) return success;

    //	Update Goal if Target / Scope Changed
    if (newRecord || is_ValueChanged("MeasureTarget") || is_ValueChanged("MeasureScope"))
      updateGoal(true);

    return success;
  }
} //	MGoal
Beispiel #2
0
/**
 * Script Model
 *
 * @author Jorg Janke
 * @version $Id: Scriptlet.java,v 1.2 2006/07/30 00:51:03 jjanke Exp $
 */
public class Scriptlet {
  /**
   * Run Script
   *
   * @param variable
   * @param script
   * @param ctx
   * @param WindowNo Included Window variables
   * @return result
   */
  static Object run(String variable, String script, Ctx ctx, int WindowNo) {
    Scriptlet scr = new Scriptlet(variable, script, ctx, WindowNo);
    scr.execute();
    return scr.getResult(false);
  } //  run

  /** Constructor */
  public Scriptlet() {
    this(VARIABLE, "", Env.getCtx(), 0);
  } //  Scriptlet

  /** Default Result Variable Name */
  public static final String VARIABLE = "result";

  /** Logger */
  private static CLogger log = CLogger.getCLogger(Scriptlet.class);

  /**
   * Full Constructor
   *
   * @param variable Variable Name
   * @param script The Script
   * @param ctx Context
   * @param WindowNo Included Window variables
   */
  public Scriptlet(String variable, String script, Ctx ctx, int WindowNo) {
    setVariable(variable);
    setScript(script);
    setEnvironment(ctx, WindowNo);
  } //  Scriptlet

  /**
   * Full Constructor
   *
   * @param variable Variable Name
   * @param script The Script
   * @param ctx Environment
   */
  public Scriptlet(String variable, String script, HashMap<String, Object> ctx) {
    setVariable(variable);
    setScript(script);
    setEnvironment(ctx);
  } //  Scriptlet

  /** Variable */
  private String m_variable;
  /** Script */
  private String m_script;
  /** Context */
  private HashMap<String, Object> m_ctx;
  /** Result */
  private Object m_result;

  /** ********************************************************************** */

  /**
   * Execute Script Loads environment and saves result
   *
   * @return null or Exception
   */
  public Exception execute() {
    m_result = null;
    if (m_variable == null
        || m_variable.length() == 0
        || m_script == null
        || m_script.length() == 0) {
      IllegalArgumentException e = new IllegalArgumentException("No variable/script");
      log.config(e.toString());
      return e;
    }
    Interpreter i = new Interpreter();
    loadEnvironment(i);
    try {
      log.config(m_script);
      i.eval(m_script);
    } catch (Exception e) {
      log.config(e.toString());
      return e;
    }
    try {
      m_result = i.get(m_variable);
      log.config("Result (" + m_result.getClass().getName() + ") " + m_result);
    } catch (Exception e) {
      log.config("Result - " + e);
      if (e instanceof NullPointerException)
        e = new IllegalArgumentException("Result Variable not found - " + m_variable);
      return e;
    }
    return null;
  } //  execute

  /**
   * Set Environment for Interpreter
   *
   * @param i Interpreter
   */
  private void loadEnvironment(Interpreter i) {
    if (m_ctx == null) return;
    Iterator<String> it = m_ctx.keySet().iterator();
    while (it.hasNext()) {
      String key = it.next();
      Object value = m_ctx.get(key);
      try {
        if (value instanceof Boolean) i.set(key, ((Boolean) value).booleanValue());
        else if (value instanceof Integer) i.set(key, ((Integer) value).intValue());
        else if (value instanceof Double) i.set(key, ((Double) value).doubleValue());
        else i.set(key, value);
      } catch (EvalError ee) {
        log.log(Level.SEVERE, "", ee);
      }
    }
  } //  setEnvironment

  /** ********************************************************************** */

  /**
   * Get Variable
   *
   * @return variable
   */
  public String getVariable() {
    return m_variable;
  } //  getVariable

  /**
   * Set Variable
   *
   * @param variable - if null set to VARIABLE
   */
  public void setVariable(String variable) {
    if (variable == null || variable.length() == 0) m_variable = VARIABLE;
    else m_variable = variable;
  }

  /**
   * Set Script
   *
   * @param script
   */
  public void setScript(String script) {
    if (script == null) m_script = "";
    else m_script = script;
  } //  setScript

  /**
   * Get Script
   *
   * @return script
   */
  public String getScript() {
    return m_script;
  } //  getScript

  /**
   * Set Environment
   *
   * @param prop
   * @param WindowNo included Window variables
   */
  public void setEnvironment(Ctx prop, int WindowNo) {
    if (prop == null) prop = Env.getCtx();

    m_ctx = new HashMap<String, Object>();
    //  Convert properties to HashMap
    Iterator<String> it = prop.keySet().iterator();
    while (it.hasNext()) {
      String key = it.next();
      //  filter
      if (key == null
          || key.length() == 0
          || key.startsWith("P") //  Preferences
          || (key.indexOf("|") != -1
              && !key.startsWith(String.valueOf(WindowNo))) //  other Window Settings
      ) continue;

      String value = prop.getContext(key);
      setEnvironment(key, value);
    }
  } //  setEnvironment

  /**
   * Set Environment key to value
   *
   * @param key variable name ('#' will be converted to '_')
   * @param stringValue try to convert to Object
   */
  public void setEnvironment(String key, String stringValue) {
    if (key == null || key.length() == 0) return;
    //	log.fine( "Scriptlet.setEnvironment " + key, stringValue);
    if (stringValue == null) {
      m_ctx.remove(key);
      return;
    }

    //  Boolean
    if (stringValue.equals("Y")) {
      m_ctx.put(convertKey(key), Boolean.valueOf(true));
      return;
    }
    if (stringValue.equals("N")) {
      m_ctx.put(convertKey(key), Boolean.valueOf(false));
      return;
    }

    //  Timestamp
    Timestamp timeValue = null;
    try {
      timeValue = Timestamp.valueOf(stringValue);
      m_ctx.put(convertKey(key), timeValue);
      return;
    } catch (Exception e) {
    }

    //  Numeric
    Integer intValue = null;
    try {
      intValue = Integer.valueOf(stringValue);
    } catch (NumberFormatException e) {
    }
    Double doubleValue = null;
    try {
      doubleValue = Double.valueOf(stringValue);
    } catch (NumberFormatException e) {
    }
    if (doubleValue != null) {
      if (intValue != null) {
        double di = Double.parseDouble(intValue.toString());
        //  the numbers are the same -> integer
        if (Double.compare(di, doubleValue.doubleValue()) == 0) {
          m_ctx.put(convertKey(key), intValue);
          return;
        }
      }
      m_ctx.put(convertKey(key), doubleValue);
      return;
    }
    if (intValue != null) {
      m_ctx.put(convertKey(key), intValue);
      return;
    }
    m_ctx.put(convertKey(key), stringValue);
  } //  SetEnvironment

  /**
   * Set Environment key to value
   *
   * @param key variable name ('#' will be vonverted to '_')
   * @param value
   */
  public void setEnvironment(String key, Object value) {
    if (key != null && key.length() > 0) {
      //	log.fine( "Scriptlet.setEnvironment " + key, value);
      if (value == null) m_ctx.remove(key);
      else m_ctx.put(convertKey(key), value);
    }
  } //  SetEnvironment

  /**
   * Convert Key # -> _
   *
   * @param key
   * @return converted key
   */
  private String convertKey(String key) {
    String retValue = Util.replace(key, "#", "_");
    return retValue;
  } //  convertKey

  /**
   * Set Environment
   *
   * @param ctx
   */
  public void setEnvironment(HashMap<String, Object> ctx) {
    if (ctx == null) m_ctx = new HashMap<String, Object>();
    else m_ctx = ctx;
  } //  setEnvironment

  /**
   * Get Environment
   *
   * @return environment
   */
  public HashMap<String, Object> getEnvironment() {
    return m_ctx;
  } //  getEnvironment

  /**
   * ************************************************************************ Get Result
   *
   * @param runIt if true, execute script
   * @return result or null
   */
  public Object getResult(boolean runIt) {
    if (runIt) execute();
    return m_result;
  } //  getResult

  /**
   * String Representation incl. Result
   *
   * @return Scipt
   */
  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer(m_variable);
    sb.append(" { ").append(m_script).append(" } = ").append(getResult(true));
    return sb.toString();
  } //  toString
} //  Scriptlet
Beispiel #3
0
/**
 * Calendar Period Model
 *
 * @author Jorg Janke
 * @version $Id: MPeriod.java,v 1.4 2006/07/30 00:51:05 jjanke Exp $
 */
public class MPeriod extends X_C_Period {
  /** Logger for class MPeriod */
  private static final org.compiere.util.CLogger log =
      org.compiere.util.CLogger.getCLogger(MPeriod.class);
  /** */
  private static final long serialVersionUID = 1L;

  /**
   * Get Period from Cache
   *
   * @param ctx context
   * @param C_Period_ID id
   * @return MPeriod
   */
  public static MPeriod get(Ctx ctx, int C_Period_ID) {
    Integer key = Integer.valueOf(C_Period_ID);
    MPeriod retValue = s_cache.get(ctx, key);
    if (retValue != null) return retValue;
    //
    retValue = new MPeriod(ctx, C_Period_ID, null);
    if (retValue.get_ID() != 0) s_cache.put(key, retValue);
    return retValue;
  } //	get

  /**
   * Find standard Period of DateAcct based on Client Calendar
   *
   * @param ctx context
   * @param DateAcct date
   * @return active Period or null
   */
  public static MPeriod getOfOrg(Ctx ctx, int AD_Org_ID, Timestamp DateAcct) {
    int C_Calendar_ID = 0;
    if (AD_Org_ID != 0) {
      MOrgInfo info = MOrgInfo.get(ctx, AD_Org_ID, null);
      C_Calendar_ID = info.getC_Calendar_ID();
    }
    if (C_Calendar_ID == 0) {
      MClientInfo cInfo = MClientInfo.get(ctx);
      C_Calendar_ID = cInfo.getC_Calendar_ID();
    }

    return getOfCalendar(ctx, C_Calendar_ID, DateAcct);
  } //	get

  /**
   * Find standard Period of DateAcct based on Client Calendar
   *
   * @param ctx context
   * @param C_Calendar_ID calendar
   * @param DateAcct date
   * @return active Period or null
   */
  public static MPeriod getOfCalendar(Ctx ctx, int C_Calendar_ID, Timestamp DateAcct) {
    if (DateAcct == null) {
      s_log.warning("No DateAcct");
      return null;
    }
    if (C_Calendar_ID == 0) {
      s_log.warning("No Calendar");
      return null;
    }
    //	Search in Cache first
    Iterator<MPeriod> it = s_cache.values().iterator();
    while (it.hasNext()) {
      MPeriod period = it.next();
      if (period.getC_Calendar_ID() == C_Calendar_ID
          && period.isStandardPeriod()
          && period.isInPeriod(DateAcct)) return period;
    }

    //	Get it from DB
    MPeriod retValue = null;
    String sql =
        "SELECT * FROM C_Period "
            + "WHERE C_Year_ID IN "
            + "(SELECT C_Year_ID FROM C_Year WHERE C_Calendar_ID=?)"
            + " AND ? BETWEEN TRUNC(StartDate,'DD') AND TRUNC(EndDate,'DD')"
            + " AND IsActive='Y' AND PeriodType='S'";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      pstmt.setInt(1, C_Calendar_ID);
      pstmt.setTimestamp(2, TimeUtil.getDay(DateAcct));
      rs = pstmt.executeQuery();
      while (rs.next()) {
        MPeriod period = new MPeriod(ctx, rs, null);
        Integer key = Integer.valueOf(period.getC_Period_ID());
        s_cache.put(key, period);
        if (period.isStandardPeriod()) retValue = period;
      }
    } catch (SQLException e) {
      s_log.log(Level.SEVERE, "DateAcct=" + DateAcct, e);
    } finally {
      DB.closeStatement(pstmt);
      DB.closeResultSet(rs);
    }
    if (retValue == null)
      s_log.warning(
          "No Standard Period for " + DateAcct + " (C_Calendar_ID=" + C_Calendar_ID + ")");
    return retValue;
  } //	get

  /**
   * Find valid standard Period of DateAcct based on Client Calendar
   *
   * @param ctx context
   * @param DateAcct date
   * @return C_Period_ID or 0
   */
  public static int getC_Period_ID(Ctx ctx, int AD_Org_ID, Timestamp DateAcct) {
    MPeriod period = getOfOrg(ctx, AD_Org_ID, DateAcct);
    if (period == null) return 0;
    return period.getC_Period_ID();
  } //	getC_Period_ID

  /**
   * Is standard Period Open for Document Base Type - does not check Orgs
   *
   * @param ctx context
   * @param DateAcct date
   * @param DocBaseType base type
   * @return true if open
   * @deprecated use new isOpen
   */
  @Deprecated
  public static boolean isOpenOld(Ctx ctx, Timestamp DateAcct, String DocBaseType) {
    if (DateAcct == null) {
      s_log.warning("No DateAcct");
      return false;
    }
    if (DocBaseType == null) {
      s_log.warning("No DocBaseType");
      return false;
    }
    MPeriod period = MPeriod.getOfOrg(ctx, 0, DateAcct);
    if (period == null) {
      s_log.warning("No Period for " + DateAcct + " (" + DocBaseType + ")");
      return false;
    }
    String error = period.isOpen(DocBaseType, DateAcct);
    if (error != null) s_log.warning(error + " - " + period.getName());
    return error == null;
  } //	isOpen

  /**
   * Is standard Period Open for specified orgs for the client. For best performance, ensure that
   * the list of orgs does not contain duplicates.
   *
   * @param ctx
   * @param AD_Client_ID
   * @param orgs
   * @param DateAcct accounting date
   * @param DocBaseType document base type
   * @return error message or null
   */
  public static String isOpen(
      Ctx ctx, int AD_Client_ID, ArrayList<Integer> orgs, Timestamp DateAcct, String DocBaseType) {
    if (DateAcct == null) return "@NotFound@ @DateAcct@";
    if (DocBaseType == null) return "@NotFound@ @DocBaseType@";

    MAcctSchema as = MClient.get(ctx, AD_Client_ID).getAcctSchema();
    if (as == null) return "@NotFound@ @C_AcctSchema_ID@ for AD_Client_ID=" + AD_Client_ID;
    if (as.isAutoPeriodControl()) {
      if (as.isAutoPeriodControlOpen(DateAcct)) return null;
      else return "@PeriodClosed@ - @AutoPeriodControl@";
    }

    //	Get all Calendars in line with Organizations
    MClientInfo clientInfo = MClientInfo.get(ctx, AD_Client_ID, null);
    ArrayList<Integer> orgCalendars = new ArrayList<Integer>();
    ArrayList<Integer> calendars = new ArrayList<Integer>();
    for (int org : orgs) {
      MOrgInfo orgInfo = MOrgInfo.get(ctx, org, null);
      int C_Calendar_ID = orgInfo.getC_Calendar_ID();
      if (C_Calendar_ID == 0) C_Calendar_ID = clientInfo.getC_Calendar_ID();
      orgCalendars.add(C_Calendar_ID);
      if (!calendars.contains(C_Calendar_ID)) calendars.add(C_Calendar_ID);
    }
    //	Should not happen
    if (calendars.size() == 0) return "@NotFound@ @C_Calendar_ID@";

    //	For all Calendars get Periods
    for (int i = 0; i < calendars.size(); i++) {
      int C_Calendar_ID = calendars.get(i);
      MPeriod period = MPeriod.getOfCalendar(ctx, C_Calendar_ID, DateAcct);
      //	First Org for Calendar
      int AD_Org_ID = 0;
      for (int j = 0; j < orgCalendars.size(); j++) {
        if (orgCalendars.get(j) == C_Calendar_ID) {
          AD_Org_ID = orgs.get(j);
          break;
        }
      }
      if (period == null) {
        MCalendar cal = MCalendar.get(ctx, C_Calendar_ID);
        String date = DisplayType.getDateFormat(DisplayTypeConstants.Date).format(DateAcct);
        if (cal != null)
          return "@NotFound@ @C_Period_ID@: "
              + date
              + " - "
              + MOrg.get(ctx, AD_Org_ID).getName()
              + " -> "
              + cal.getName();
        else
          return "@NotFound@ @C_Period_ID@: "
              + date
              + " - "
              + MOrg.get(ctx, AD_Org_ID).getName()
              + " -> C_Calendar_ID="
              + C_Calendar_ID;
      }
      String error = period.isOpen(DocBaseType, DateAcct);
      if (error != null)
        return error
            + " - "
            + MOrg.get(ctx, AD_Org_ID).getName()
            + " -> "
            + MCalendar.get(ctx, C_Calendar_ID).getName();
    }
    return null; //	open
  } //	isOpen

  /**
   * Is standard Period Open for Document Base Type
   *
   * @param header header document record
   * @param lines document lines optional
   * @param DateAcct accounting date
   * @param DocBaseType document base type
   * @return error message or null
   */
  @Deprecated
  public static String isOpen(PO header, PO[] lines, Timestamp DateAcct, String DocBaseType) {

    // Get All Orgs
    ArrayList<Integer> orgs = new ArrayList<Integer>();
    orgs.add(header.getAD_Org_ID());
    if (lines != null) {
      for (PO line : lines) {
        int AD_Org_ID = line.getAD_Org_ID();
        if (!orgs.contains(AD_Org_ID)) orgs.add(AD_Org_ID);
      }
    }

    return isOpen(header.getCtx(), header.getAD_Client_ID(), orgs, DateAcct, DocBaseType);
  } // isOpen

  /**
   * Is standard Period closed for all Document Base Types
   *
   * @param ctx context for AD_Client
   * @param DateAcct accounting date
   * @return true if closed
   */
  public static boolean isClosed(Ctx ctx, Timestamp DateAcct) {
    if (DateAcct == null) return false;
    MAcctSchema as = MClient.get(ctx, ctx.getAD_Client_ID()).getAcctSchema();
    if (as.isAutoPeriodControl()) return !as.isAutoPeriodControlOpen(DateAcct);

    //	Get all Calendars in line with Organizations
    MClientInfo cInfo = MClientInfo.get(ctx, ctx.getAD_Client_ID(), null);
    ArrayList<Integer> calendars = new ArrayList<Integer>();
    MOrg[] orgs = MOrg.getOfClient(cInfo);
    for (MOrg org : orgs) {
      MOrgInfo info = MOrgInfo.get(ctx, org.getAD_Org_ID(), null);
      int C_Calendar_ID = info.getC_Calendar_ID();
      if (C_Calendar_ID == 0) C_Calendar_ID = cInfo.getC_Calendar_ID();
      if (!calendars.contains(C_Calendar_ID)) calendars.add(C_Calendar_ID);
    }
    //	Should not happen
    if (calendars.size() == 0) throw new IllegalArgumentException("@NotFound@ @C_Calendar_ID@");

    //	For all Calendars get Periods
    for (int i = 0; i < calendars.size(); i++) {
      int C_Calendar_ID = calendars.get(i);
      MPeriod period = MPeriod.getOfCalendar(ctx, C_Calendar_ID, DateAcct);
      //	Period not found
      if (period == null) return false;
      if (!period.isClosed()) return false;
    }
    return true; //	closed
  } //	isClosed

  /**
   * Find first Year Period of DateAcct based on Client Calendar
   *
   * @param ctx context
   * @param C_Calendar_ID calendar
   * @param DateAcct date
   * @return active first Period
   */
  public static MPeriod getFirstInYear(Ctx ctx, int C_Calendar_ID, Timestamp DateAcct) {
    MPeriod retValue = null;
    String sql =
        "SELECT * "
            + "FROM C_Period "
            + "WHERE C_Year_ID IN "
            + "(SELECT p.C_Year_ID "
            + "FROM C_Year y"
            + " INNER JOIN C_Period p ON (y.C_Year_ID=p.C_Year_ID) "
            + "WHERE y.C_Calendar_ID=?"
            + "	AND ? BETWEEN StartDate AND EndDate)"
            + " AND IsActive='Y' AND PeriodType='S' "
            + "ORDER BY StartDate";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      pstmt.setInt(1, C_Calendar_ID);
      pstmt.setTimestamp(2, DateAcct);
      rs = pstmt.executeQuery();
      if (rs.next()) // 	first only
      retValue = new MPeriod(ctx, rs, null);
    } catch (SQLException e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeStatement(pstmt);
      DB.closeResultSet(rs);
    }
    return retValue;
  } //	getFirstInYear

  /** Cache */
  private static final CCache<Integer, MPeriod> s_cache =
      new CCache<Integer, MPeriod>("C_Period", 10);

  /** Logger */
  private static final CLogger s_log = CLogger.getCLogger(MPeriod.class);

  /**
   * ************************************************************************ Standard Constructor
   *
   * @param ctx context
   * @param C_Period_ID id
   * @param trx transaction
   */
  public MPeriod(Ctx ctx, int C_Period_ID, Trx trx) {
    super(ctx, C_Period_ID, trx);
    if (C_Period_ID == 0) {
      //	setC_Period_ID (0);		//	PK
      //  setC_Year_ID (0);		//	Parent
      //  setName (null);
      //  setPeriodNo (0);
      //  setStartDate (new Timestamp(System.currentTimeMillis()));
      setPeriodType(PERIODTYPE_StandardCalendarPeriod);
    }
  } //	MPeriod

  /**
   * Load Constructor
   *
   * @param ctx context
   * @param rs result set
   * @param trx transaction
   */
  public MPeriod(Ctx ctx, ResultSet rs, Trx trx) {
    super(ctx, rs, trx);
  } //	MPeriod

  /**
   * Parent constructor
   *
   * @param year year
   * @param PeriodNo no
   * @param name name
   * @param startDate start
   * @param endDate end
   */
  public MPeriod(MYear year, int PeriodNo, String name, Timestamp startDate, Timestamp endDate) {
    this(year.getCtx(), 0, year.get_Trx());
    setClientOrg(year);
    setC_Year_ID(year.getC_Year_ID());
    setPeriodNo(PeriodNo);
    setName(name);
    setStartDate(startDate);
    setEndDate(endDate);
  } //	MPeriod

  /** Period Controls */
  private MPeriodControl[] m_controls = null;
  /** Calendar */
  private int m_C_Calendar_ID = 0;

  /**
   * Get Period Control
   *
   * @param requery requery
   * @return period controls
   */
  public MPeriodControl[] getPeriodControls(boolean requery) {
    if (m_controls != null && !requery) return m_controls;
    //
    ArrayList<MPeriodControl> list = new ArrayList<MPeriodControl>();
    String sql = "SELECT * FROM C_PeriodControl " + "WHERE C_Period_ID=?";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, get_Trx());
      pstmt.setInt(1, getC_Period_ID());
      rs = pstmt.executeQuery();
      while (rs.next()) list.add(new MPeriodControl(getCtx(), rs, get_Trx()));
    } catch (Exception e) {
      log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    m_controls = new MPeriodControl[list.size()];
    list.toArray(m_controls);
    return m_controls;
  } //	getPeriodControls

  /**
   * Get Period Control
   *
   * @param DocBaseType Document Base Type
   * @return period control or null
   */
  public MPeriodControl getPeriodControl(String DocBaseType) {
    if (DocBaseType == null) return null;
    getPeriodControls(false);
    for (MPeriodControl element : m_controls) {
      //	log.fine("getPeriodControl - " + 1 + " - " + m_controls[i]);
      if (DocBaseType.equals(element.getDocBaseType())) return element;
    }
    return null;
  } //	getPeriodControl

  /**
   * Date In Period
   *
   * @param date date
   * @return true if in period
   */
  public boolean isInPeriod(Timestamp date) {
    if (date == null) return false;
    Timestamp dateOnly = TimeUtil.getDay(date);
    Timestamp from = TimeUtil.getDay(getStartDate());
    if (dateOnly.before(from)) return false;
    Timestamp to = TimeUtil.getDay(getEndDate());
    if (dateOnly.after(to)) return false;
    return true;
  } //	isInPeriod

  /**
   * Is Period Open for Doc Base Type
   *
   * @param DocBaseType document base type
   * @param dateAcct accounting date
   * @return error message or null
   */
  public String isOpen(String DocBaseType, Timestamp dateAcct) {
    if (!isActive()) {
      s_log.warning("Period not active: " + getName());
      return "@C_Period_ID@ <> @IsActive@";
    }

    MAcctSchema as = MClient.get(getCtx(), getAD_Client_ID()).getAcctSchema();
    if (as != null && as.isAutoPeriodControl()) {
      if (!as.isAutoPeriodControlOpen(dateAcct)) return "@PeriodClosed@ - @AutoPeriodControl@";
      //	We are OK
      Timestamp today = new Timestamp(System.currentTimeMillis());
      if (isInPeriod(today) && as.getC_Period_ID() != getC_Period_ID()) {
        as.setC_Period_ID(getC_Period_ID());
        as.save();
      }
      return null;
    }

    //	Standard Period Control
    if (DocBaseType == null) {
      log.warning(getName() + " - No DocBaseType");
      return "@NotFound@ @DocBaseType@";
    }
    MPeriodControl pc = getPeriodControl(DocBaseType);
    if (pc == null) {
      log.warning(getName() + " - Period Control not found for " + DocBaseType);
      return "@NotFound@ @C_PeriodControl_ID@: " + DocBaseType;
    }
    log.fine(getName() + ": " + DocBaseType);
    if (pc.isOpen()) return null;
    return "@PeriodClosed@ - @C_PeriodControl_ID@ (" + DocBaseType + ", " + dateAcct + ")";
  } //	isOpen

  /**
   * Return true if all PC are closed
   *
   * @return true if closed
   */
  public boolean isClosed() {
    MPeriodControl[] pcs = getPeriodControls(false);
    for (MPeriodControl pc : pcs) {
      if (!pc.isClosed()) return false;
    }
    return true;
  } //	isClosed

  /**
   * Standard Period
   *
   * @return true if standard calendar period
   */
  public boolean isStandardPeriod() {
    return PERIODTYPE_StandardCalendarPeriod.equals(getPeriodType());
  } //	isStandardPeriod

  /**
   * Get Calendar of Period
   *
   * @return calendar
   */
  public int getC_Calendar_ID() {
    if (m_C_Calendar_ID == 0) {
      MYear year = MYear.get(getCtx(), getC_Year_ID());
      if (year != null) m_C_Calendar_ID = year.getC_Calendar_ID();
      else log.severe("@NotFound@ C_Year_ID=" + getC_Year_ID());
    }
    return m_C_Calendar_ID;
  } //	getC_Calendar_ID

  /**
   * Before Save. Truncate Dates
   *
   * @param newRecord new
   * @return true
   */
  @Override
  protected boolean beforeSave(boolean newRecord) {
    Timestamp startdate = getStartDate();
    Timestamp enddate = getEndDate();

    if (enddate != null && startdate.after(enddate)) {

      s_log.saveError("Error", Msg.getMsg(getCtx(), "CalPeriodInvalidDate"));
      return false;
    }
    //	Truncate Dates
    startdate = TimeUtil.getDay(startdate);
    setStartDate(startdate);

    if (enddate != null) enddate = TimeUtil.getDay(enddate);
    else enddate = TimeUtil.getMonthLastDay(getStartDate());

    //		Adding the time component of 23:59:59 to the end date
    enddate = new Timestamp(enddate.getTime() + 86399000);
    setEndDate(enddate);

    MPeriod[] periods = getAllPeriodsInYear(getC_Year_ID(), "S", getCtx(), get_Trx());
    MPeriod[] allperiods = getAllPeriodsInCalendar(getC_Calendar_ID(), "S", getCtx(), get_Trx());
    //		Check for non-negative period number
    if (getPeriodNo() < 0) {
      s_log.saveError("Error", Msg.getMsg(getCtx(), "CalNegPeriodNo"));
      return false;
    }

    //		Check for standard period
    if (isStandardPeriod() == true) {
      // Check Period number is in ascending order

      Timestamp nextPeriodStartDate = null;
      Timestamp prevPeriodStartDate = null;

      // Get the next standard period number Start Date in this year
      String sql =
          "SELECT StartDate FROM C_Period WHERE "
              + "C_Period.IsActive='Y' AND PeriodType='S' "
              + "AND C_Period.C_Year_ID =? "
              + "AND C_Period.C_Period_ID <> ?"
              + "AND  C_Period.PeriodNo "
              + " >  ?  ORDER BY  C_Period.PeriodNo ASC";
      Object[][] result = null;
      result =
          QueryUtil.executeQuery(get_Trx(), sql, getC_Year_ID(), getC_Period_ID(), getPeriodNo());

      if (result.length != 0) nextPeriodStartDate = (Timestamp) result[0][0];

      // Get the previous standard period number Start Date in this year
      sql =
          "SELECT StartDate FROM C_Period WHERE "
              + "C_Period.IsActive='Y' AND PeriodType='S'  "
              + "AND C_Period.C_Year_ID =? "
              + "AND C_Period.C_Period_ID <> ?"
              + "AND C_Period.PeriodNo "
              + "< ?  ORDER BY  C_Period.PeriodNo DESC";

      result =
          QueryUtil.executeQuery(get_Trx(), sql, getC_Year_ID(), getC_Period_ID(), getPeriodNo());
      if (result.length != 0) prevPeriodStartDate = (Timestamp) result[0][0];

      if ((prevPeriodStartDate != null
          && TimeUtil.max(prevPeriodStartDate, startdate) == prevPeriodStartDate)) {
        s_log.saveError("Error", Msg.getMsg(getCtx(), "CalPeriodAsc"));
        return false;
      }

      if ((nextPeriodStartDate != null
          && TimeUtil.max(nextPeriodStartDate, startdate) == startdate)) {
        s_log.saveError("Error", Msg.getMsg(getCtx(), "CalPeriodAsc"));
        return false;
      }

      //  Check if the Standard Period is overlapping other periods.

      for (MPeriod period : allperiods) {
        if ((TimeUtil.isValid(period.getStartDate(), period.getEndDate(), startdate) == true
                || TimeUtil.isValid(period.getStartDate(), period.getEndDate(), enddate) == true)
            && period.getC_Period_ID() != getC_Period_ID()) {
          s_log.saveError("Error", Msg.getMsg(getCtx(), "CalPeriodOverlap"));
          return false;
        }
      }

    }
    //		Check for adjusting period
    else {
      boolean startflag = false;
      boolean endflag = false;
      for (MPeriod period : periods) {
        if (TimeUtil.isValid(period.getStartDate(), period.getEndDate(), startdate) == true)
          startflag = true;
        if (TimeUtil.isValid(period.getStartDate(), period.getEndDate(), enddate) == true)
          endflag = true;
        if (startflag == true && endflag == true) break;
      }
      if (startflag == false || endflag == false) {
        s_log.saveError("Error", Msg.getMsg(getCtx(), "CalAdjPeriod"));
        return false;
      }
    }
    return true;
  } //	beforeSave

  /**
   * After Save
   *
   * @param newRecord new
   * @param success success
   * @return success
   */
  @Override
  protected boolean afterSave(boolean newRecord, boolean success) {
    if (newRecord) {
      //	SELECT Value FROM AD_Ref_List WHERE AD_Reference_ID=183
      MDocType[] types = MDocType.getOfClient(getCtx());
      int count = 0;
      ArrayList<String> baseTypes = new ArrayList<String>();
      for (MDocType type : types) {
        String DocBaseType = type.getDocBaseType();
        if (baseTypes.contains(DocBaseType)) continue;
        MPeriodControl pc = new MPeriodControl(this, DocBaseType);
        if (pc.save()) count++;
        baseTypes.add(DocBaseType);
      }
      log.fine("PeriodControl #" + count);
    }
    return success;
  } //	afterSave

  /**
   * String Representation
   *
   * @return info
   */
  @Override
  public String toString() {
    StringBuffer sb = new StringBuffer("MPeriod[");
    sb.append(get_ID())
        .append("-")
        .append(getName())
        .append(", ")
        .append(getStartDate())
        .append("-")
        .append(getEndDate())
        .append("]");
    return sb.toString();
  } //	toString

  /**
   * Returns the next period forward
   *
   * @param period MPeriod
   * @param trx trx
   * @param ctx Ctx
   * @return MPeriod
   */
  public static MPeriod getNextPeriod(MPeriod period, Ctx ctx, Trx trx) {

    MPeriod newPeriod = null;
    String sql =
        "SELECT * FROM C_Period WHERE "
            + "C_Period.IsActive='Y' AND PeriodType='S' "
            + "AND C_Period.C_Year_ID IN "
            + "(SELECT C_Year_ID FROM C_Year WHERE C_Year.C_Calendar_ID = ? ) "
            + "AND ((C_Period.C_Year_ID * 1000) + C_Period.PeriodNo) "
            + " > ((? * 1000) + ?) ORDER BY C_Period.C_Year_ID ASC, C_Period.PeriodNo ASC";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, period.getC_Calendar_ID());
      pstmt.setInt(2, period.getC_Year_ID());
      pstmt.setInt(3, period.getPeriodNo());
      rs = pstmt.executeQuery();
      if (rs.next()) newPeriod = new MPeriod(ctx, rs, trx);
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    return newPeriod;
  }

  /**
   * Returns the previous period
   *
   * @param period MPeriod
   * @param periodCount Count
   * @param trx trx
   * @param ctx Ctx
   * @return MPeriod
   */
  public static MPeriod getPreviousPeriod(MPeriod period, Ctx ctx, Trx trx) {

    MPeriod newPeriod = null;
    String sql =
        "SELECT * FROM C_Period WHERE "
            + "C_Period.IsActive='Y' AND PeriodType='S' "
            + "AND C_Period.C_Year_ID IN "
            + "(SELECT C_Year_ID FROM C_Year WHERE C_Year.C_Calendar_ID = ? ) "
            + "AND ((C_Period.C_Year_ID * 1000) + C_Period.PeriodNo) "
            + " < ((? * 1000) + ?) ORDER BY C_Period.C_Year_ID DESC, C_Period.PeriodNo DESC";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, period.getC_Calendar_ID());
      pstmt.setInt(2, period.getC_Year_ID());
      pstmt.setInt(3, period.getPeriodNo());
      rs = pstmt.executeQuery();
      if (rs.next()) newPeriod = new MPeriod(ctx, rs, trx);
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    return newPeriod;
  }

  /**
   * gets all Periods in the Range
   *
   * @param startPeriod
   * @param endPeriod
   * @param calendar_ID
   * @return MPeriod[]
   */
  public static MPeriod[] getAllPeriodsInRange(
      MPeriod startPeriod, MPeriod endPeriod, int calendar_ID, Ctx ctx, Trx trx) {
    if ((startPeriod.getC_Calendar_ID() != calendar_ID)
        || (endPeriod.getC_Calendar_ID() != calendar_ID)) {
      log.saveError("Error", "Periods do not belong to the calendar");
      return null;
    }

    ArrayList<MPeriod> periods = new ArrayList<MPeriod>();
    String sql =
        "SELECT * FROM C_Period WHERE "
            + "C_Period.IsActive='Y' AND PeriodType='S' "
            + "AND C_Period.C_Year_ID IN "
            + "(SELECT C_Year_ID FROM C_Year WHERE C_Year.C_Calendar_ID = ? ) "
            + // calendar_ID
            "AND ((C_Period.C_Year_ID * 1000) + C_Period.PeriodNo) BETWEEN"
            + " (? * 1000 + ?) AND (? * 1000 + ? )"
            + // start Period year ID, Period Number , End Period Year ID, Period Number
            " ORDER BY C_Period.C_Year_ID ASC, C_Period.PeriodNo ASC";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, calendar_ID);
      pstmt.setInt(2, startPeriod.getC_Year_ID());
      pstmt.setInt(3, startPeriod.getPeriodNo());
      pstmt.setInt(4, endPeriod.getC_Year_ID());
      pstmt.setInt(5, endPeriod.getPeriodNo());
      rs = pstmt.executeQuery();
      while (rs.next()) periods.add(new MPeriod(ctx, rs, trx));
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    MPeriod[] retValue = new MPeriod[periods.size()];
    periods.toArray(retValue);
    return retValue;
  }

  /**
   * Find Period of Date based on Client Calendar, it need not be a standard period (used in MRP)
   *
   * @param ctx context
   * @param C_Calendar_ID calendar
   * @param Date date
   * @param trx trx
   * @return active Period or null
   */
  public static MPeriod getPeriod(Ctx ctx, int C_Calendar_ID, Timestamp Date, Trx trx) {
    if (Date == null) {
      s_log.warning("No Date");
      return null;
    }
    if (C_Calendar_ID == 0) {
      s_log.warning("No Calendar");
      return null;
    }

    //	Get it from DB
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    MPeriod retValue = null;
    String sql =
        "SELECT * FROM C_Period "
            + "WHERE C_Year_ID IN "
            + "(SELECT C_Year_ID FROM C_Year WHERE C_Calendar_ID=?)"
            + " AND ? BETWEEN TRUNC(StartDate,'DD') AND TRUNC(EndDate,'DD')"
            + " AND IsActive='Y' ";
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, C_Calendar_ID);
      pstmt.setTimestamp(2, TimeUtil.getDay(Date));
      rs = pstmt.executeQuery();
      if (rs.next()) {
        retValue = new MPeriod(ctx, rs, trx);
      }
    } catch (SQLException e) {
      s_log.log(Level.SEVERE, "DateAcct=" + Date, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    if (retValue == null)
      s_log.warning("No Period for " + Date + " (C_Calendar_ID=" + C_Calendar_ID + ")");
    return retValue;
  } //	getPeriod

  /**
   * Find the periods in a calendar it need not be a standard period (used in MRP)
   *
   * @param C_Calendar_ID calendar
   * @param periodType Period Type
   * @param ctx context
   * @param trx trx
   * @return MPeriod[]
   */
  public static MPeriod[] getAllPeriodsInCalendar(
      int C_Calendar_ID, String periodType, Ctx ctx, Trx trx) {

    List<MPeriod> periods = new ArrayList<MPeriod>();
    String sql = "SELECT * FROM C_Period WHERE IsActive='Y'";

    sql = sql + " AND C_Year_ID IN ( SELECT C_Year_ID FROM C_Year WHERE C_Calendar_ID=?)";

    if (periodType != null) sql = sql + " AND PeriodType = ? ";

    sql = sql + " ORDER BY StartDate ";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, C_Calendar_ID);

      if (periodType != null) pstmt.setString(2, periodType);

      rs = pstmt.executeQuery();
      while (rs.next()) periods.add(new MPeriod(ctx, rs, trx));
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    MPeriod[] retValue = new MPeriod[periods.size()];
    periods.toArray(retValue);
    return retValue;
  }

  /**
   * Find the periods in a calendar year it need not be a standard period (used in MRP)
   *
   * @param C_Year_ID Year
   * @param periodType Period Type
   * @param ctx context
   * @param trx trx
   * @return MPeriod[]
   */
  public static MPeriod[] getAllPeriodsInYear(int C_Year_ID, String periodType, Ctx ctx, Trx trx) {

    List<MPeriod> periods = new ArrayList<MPeriod>();
    String sql = "SELECT * FROM C_Period WHERE IsActive='Y'";

    sql = sql + " AND C_Year_ID = ?";

    if (periodType != null) sql = sql + " AND PeriodType = ? ";

    sql = sql + " order by StartDate ";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, C_Year_ID);

      if (periodType != null) pstmt.setString(2, periodType);

      rs = pstmt.executeQuery();
      while (rs.next()) periods.add(new MPeriod(ctx, rs, trx));
    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }
    MPeriod[] retValue = new MPeriod[periods.size()];
    periods.toArray(retValue);
    return retValue;
  }

  /**
   * Find all the year records in a Calendar, it need not be a standard period (used in MRP)
   *
   * @param C_Calendar_ID calendar
   * @param ctx context
   * @param trx trx
   * @return MYear[]
   */
  public static MYear[] getAllYearsInCalendar(int C_Calendar_ID, Ctx ctx, Trx trx) {

    List<MYear> years = new ArrayList<MYear>();
    String sql = "SELECT * FROM C_Year WHERE " + "IsActive='Y' AND C_Calendar_ID = ? ";

    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, trx);
      pstmt.setInt(1, C_Calendar_ID);
      rs = pstmt.executeQuery();
      while (rs.next()) years.add(new MYear(ctx, rs, trx));

    } catch (Exception e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {

      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }

    MYear[] retValue = new MYear[years.size()];
    years.toArray(retValue);
    return retValue;
  }
} //	MPeriod
Beispiel #4
0
/**
 * LDAP Management Interface
 *
 * @author Jorg Janke
 * @version $Id: LDAP.java 8244 2009-12-04 23:25:29Z freyes $
 */
public class LDAP {
  /**
   * Validate User
   *
   * @param ldapURL provider url - e.g. ldap://dc.compiere.org
   * @param domain domain name = e.g. compiere.org
   * @param userName user name - e.g. jjanke
   * @param password password
   * @return true if validated with ldap
   */
  public static boolean validate(String ldapURL, String domain, String userName, String password) {
    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    //	ldap://dc.compiere.org
    env.put(Context.PROVIDER_URL, ldapURL);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    //	[email protected]
    StringBuffer principal = new StringBuffer(userName).append("@").append(domain);
    env.put(Context.SECURITY_PRINCIPAL, principal.toString());
    env.put(Context.SECURITY_CREDENTIALS, password);
    //
    try {
      // Create the initial context
      InitialLdapContext ctx = new InitialLdapContext(env, null);
      //	DirContext ctx = new InitialDirContext(env);

      //	Test - Get the attributes
      Attributes answer = ctx.getAttributes("");

      // Print the answer
      if (false) dump(answer);
    } catch (AuthenticationException e) {
      log.info("Error: " + principal + " - " + e.getLocalizedMessage());
      return false;
    } catch (Exception e) {
      log.log(Level.SEVERE, ldapURL + " - " + principal, e);
      return false;
    }
    log.info("OK: " + principal);
    return true;
  } //	validate

  /** Logger */
  private static CLogger log = CLogger.getCLogger(LDAP.class);

  /**
   * Test NT
   *
   * @throws LoginException
   *     <p>private static void testNT () throws LoginException { try { System.out.println ("NT
   *     system ----------------------------"); NTSystem ntsystem = new NTSystem ();
   *     System.out.println (ntsystem); System.out.println (ntsystem.getDomain ());
   *     System.out.println (ntsystem.getDomainSID ()); System.out.println (ntsystem.getName ());
   *     System.out.println (ntsystem.getUserSID ()); System.out.println ("NT login
   *     ----------------------------"); NTLoginModule ntlogin = new NTLoginModule ();
   *     System.out.println (ntlogin); Map<String,String> map = new HashMap<String,String>();
   *     map.put ("debug", "true"); ntlogin.initialize (null, null, null, map); System.out.println
   *     (ntlogin.login ()); } catch (LoginException le) { System.err.println ("Authentication
   *     attempt failed" + le); } } // testNT
   *     <p>/** testKerberos
   * @throws LoginException
   *     <p>private static void testKerberos () throws LoginException { System.out.println ("Krb
   *     login ----------------------------"); Map<String,String> map = new
   *     HashMap<String,String>(); // map.put("debug", "true"); // map.put("debugNative", "true");
   *     Krb5LoginModule klogin = new Krb5LoginModule (); System.out.println (klogin); map.put
   *     ("principal", "*****@*****.**"); map.put ("credential", "pass"); klogin.initialize
   *     (null, null, null, map); System.out.println (klogin.login ());
   *     /*********************************************************************** ** No krb5.ini
   *     file found in entire system Debug is true storeKey false useTicketCache false useKeyTab
   *     false doNotPrompt false ticketCache is null KeyTab is null refreshKrb5Config is false
   *     principal is jjanke tryFirstPass is false useFirstPass is false storePass is false
   *     clearPass is false [Krb5LoginModule] authentication failed Could not load configuration
   *     file c:\winnt\krb5.ini (The system cannot find the file specified)
   *     javax.security.auth.login.LoginException: Could not load configuration file
   *     c:\winnt\krb5.ini (The system cannot find the file specified)
   *     <p>} // testKerbos /*
   */

  /**
   * Print Attributes to System.out
   *
   * @param attrs
   */
  private static void dump(Attributes attrs) {
    if (attrs == null) {
      System.out.println("No attributes");
    } else {
      /* Print each attribute */
      try {
        for (NamingEnumeration<? extends Attribute> ae = attrs.getAll(); ae.hasMore(); ) {
          Attribute attr = ae.next();
          System.out.println("attribute: " + attr.getID());
          /* print each value */
          for (NamingEnumeration<?> e = attr.getAll();
              e.hasMore();
              System.out.println("    value: " + e.next())) ;
        }
      } catch (NamingException e) {
        e.printStackTrace();
      }
    }
  } //	dump

  /**
   * Test
   *
   * @param args ignored
   */
  public static void main(String[] args) {
    try {
      validate("ldap://dc.compiere.org", "compiere.org", "jjanke", "ikeepforgetting");
    } catch (Exception e) {
      e.printStackTrace();
    }
  } //	main
} //	LDAP
Beispiel #5
0
/**
 * Location Region Model (Value Object)
 *
 * @author Jorg Janke
 * @version $Id: MRegion.java 8755 2010-05-12 18:30:14Z nnayak $
 */
public final class MRegion extends X_C_Region implements Comparator<PO>, Serializable {
  /** Logger for class MRegion */
  private static final org.compiere.util.CLogger log =
      org.compiere.util.CLogger.getCLogger(MRegion.class);
  /** */
  private static final long serialVersionUID = 1L;

  /**
   * Load Regions (cached)
   *
   * @param ctx context
   */
  private static void loadAllRegions(Ctx ctx) {
    String sql = "SELECT * FROM C_Region WHERE IsActive='Y'";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = DB.prepareStatement(sql, (Trx) null);
      rs = pstmt.executeQuery();
      while (rs.next()) {
        MRegion r = new MRegion(ctx, rs, null);
        s_regions.put(String.valueOf(r.getC_Region_ID()), r);
        if (r.isDefault()) s_default = r;
      }
    } catch (SQLException e) {
      s_log.log(Level.SEVERE, sql, e);
    } finally {
      DB.closeResultSet(rs);
      DB.closeStatement(pstmt);
    }

    s_log.fine(s_regions.size() + " - default=" + s_default);
  } //	loadAllRegions

  /**
   * Get Country (cached)
   *
   * @param ctx context
   * @param C_Region_ID ID
   * @return Country
   */
  public static MRegion get(Ctx ctx, int C_Region_ID) {
    if (s_regions.isEmpty()) loadAllRegions(ctx);
    String key = String.valueOf(C_Region_ID);
    MRegion r = s_regions.get(ctx, key);
    if (r != null) return r;
    r = new MRegion(ctx, C_Region_ID, null);
    if (r.getC_Region_ID() == C_Region_ID) {
      s_regions.put(key, r);
      return r;
    }
    return null;
  } //	get

  /**
   * Get Default Region
   *
   * @param ctx context
   * @return Region or null
   */
  public static MRegion getDefault(Ctx ctx) {
    if (s_regions.isEmpty()) loadAllRegions(ctx);
    return s_default;
  } //	get

  /**
   * Return Regions as Array
   *
   * @param ctx context
   * @return MCountry Array
   */
  public static MRegion[] getRegions(Ctx ctx) {
    if (s_regions.isEmpty()) loadAllRegions(ctx);
    MRegion[] retValue = new MRegion[s_regions.size()];
    s_regions.values().toArray(retValue);
    Arrays.sort(retValue, new MRegion(ctx, 0, null));
    return retValue;
  } //	getRegions

  /**
   * Return Array of Regions of Country
   *
   * @param ctx context
   * @param C_Country_ID country
   * @return MRegion Array
   */
  public static MRegion[] getRegions(Ctx ctx, int C_Country_ID) {
    if (s_regions.isEmpty()) loadAllRegions(ctx);
    ArrayList<MRegion> list = new ArrayList<MRegion>();
    Iterator<MRegion> it = s_regions.values().iterator();
    while (it.hasNext()) {
      MRegion r = it.next();
      if (r.getC_Country_ID() == C_Country_ID) list.add(r);
    }
    //  Sort it
    MRegion[] retValue = new MRegion[list.size()];
    list.toArray(retValue);
    Arrays.sort(retValue, new MRegion(ctx, 0, null));
    return retValue;
  } //	getRegions

  /** Region Cache */
  private static final CCachePerm<String, MRegion> s_regions =
      new CCachePerm<String, MRegion>("C_Region", 100);
  /** Default Region */
  private static MRegion s_default = null;
  /** Static Logger */
  private static CLogger s_log = CLogger.getCLogger(MRegion.class);

  /**
   * ************************************************************************ Create empty Region
   *
   * @param ctx context
   * @param C_Region_ID id
   * @param trx transaction
   */
  public MRegion(Ctx ctx, int C_Region_ID, Trx trx) {
    super(ctx, C_Region_ID, trx);
    if (C_Region_ID == 0) {}
  } //  MRegion

  /**
   * Create Region from current row in ResultSet
   *
   * @param ctx context
   * @param rs result set
   * @param trx transaction
   */
  public MRegion(Ctx ctx, ResultSet rs, Trx trx) {
    super(ctx, rs, trx);
  } //	MRegion

  /**
   * Parent Constructor
   *
   * @param country country
   * @param regionName Region Name
   */
  public MRegion(MCountry country, String regionName) {
    super(country.getCtx(), 0, country.get_Trx());
    setC_Country_ID(country.getC_Country_ID());
    setName(regionName);
  } //  MRegion

  /**
   * Return Name
   *
   * @return Name
   */
  @Override
  public String toString() {
    return getName();
  } //  toString

  /**
   * Compare
   *
   * @param o1 object 1
   * @param o2 object 2
   * @return -1,0, 1
   */
  @Override
  public int compare(PO o1, PO o2) {
    String s1 = o1.toString();
    if (s1 == null) s1 = "";
    String s2 = o2.toString();
    if (s2 == null) s2 = "";
    return s1.compareTo(s2);
  } //	compare

  /**
   * Test / Load
   *
   * @param args
   */
  public static void main(String[] args) {
    Compiere.startup(true);
    /**
     * To add your regions, complete the code below. Please make sure that the file is converted via
     * the Java utility native2ascii - i.e. all seven bit code with /u0000 unicode stuff
     */
    int C_Country_ID = 216; // 	Japan
    MCountry country = new MCountry(Env.getCtx(), C_Country_ID, null);
    // Hokkaido
    MRegion temp = new MRegion(country, "\u5317\u6d77\u9053");
    temp.setDescription("\u5317\u6d77\u9053(Hokkaido)");
    temp.save();
    // Aomori
    temp = new MRegion(country, "\u9752\u68ee\u770c");
    temp.setDescription("\u9752\u68ee\u770c(Aomori)");
    temp.save();
    // Iwate
    temp = new MRegion(country, "\u5ca9\u624b\u770c");
    temp.setDescription("\u5ca9\u624b\u770c(Iwate)");
    temp.save();
    // Miyagi
    temp = new MRegion(country, "\u5bae\u57ce\u770c");
    temp.setDescription("\u5bae\u57ce\u770c(Miyagi)");
    temp.save();
    // Akita
    temp = new MRegion(country, "\u79cb\u7530\u770c");
    temp.setDescription("\u79cb\u7530\u770c(Akita)");
    temp.save();
    // Yamagata
    temp = new MRegion(country, "\u5c71\u5f62\u770c");
    temp.setDescription("\u5c71\u5f62\u770c(Yamagata)");
    temp.save();
    // Fukushima
    temp = new MRegion(country, "\u798f\u5cf6\u770c");
    temp.setDescription("\u798f\u5cf6\u770c(Fukushima)");
    temp.save();
    // Ibaraki
    temp = new MRegion(country, "\u8328\u57ce\u770c");
    temp.setDescription("\u8328\u57ce\u770c(Ibaraki)");
    temp.save();
    // Gunma
    temp = new MRegion(country, "\u7fa4\u99ac\u770c");
    temp.setDescription("\u7fa4\u99ac\u770c(Gunma)");
    temp.save();
    // Saitama
    temp = new MRegion(country, "\u57fc\u7389\u770c");
    temp.setDescription("\u57fc\u7389\u770c(Saitama)");
    temp.save();
    // Chiba
    temp = new MRegion(country, "\u5343\u8449\u770c");
    temp.setDescription("\u5343\u8449\u770c(Chiba)");
    temp.save();
    // Tokyo
    temp = new MRegion(country, "\u6771\u4eac\u90fd");
    temp.setDescription("\u6771\u4eac\u90fd(Tokyo)");
    temp.save();
    // Kanagawa
    temp = new MRegion(country, "\u795e\u5948\u5ddd\u770c");
    temp.setDescription("\u795e\u5948\u5ddd\u770c(Kanagawa)");
    temp.save();
    // Niigata
    temp = new MRegion(country, "\u65b0\u6f5f\u770c");
    temp.setDescription("\u65b0\u6f5f\u770c(Niigata)");
    temp.save();
    // Toyama
    temp = new MRegion(country, "\u5bcc\u5c71\u770c");
    temp.setDescription("\u5bcc\u5c71\u770c(Toyama)");
    temp.save();
    // Ishikawa
    temp = new MRegion(country, "\u77f3\u5ddd\u770c");
    temp.setDescription("\u77f3\u5ddd\u770c(Ishikawa)");
    temp.save();
    // Fukui
    temp = new MRegion(country, "\u798f\u4e95\u770c");
    temp.setDescription("\u798f\u4e95\u770c(Fukui)");
    temp.save();
    // Yamanashi
    temp = new MRegion(country, "\u5c71\u68a8\u770c");
    temp.setDescription("\u5c71\u68a8\u770c(Yamanashi)");
    temp.save();
    // Gifu
    temp = new MRegion(country, "\u5c90\u961c\u770c");
    temp.setDescription("\u5c90\u961c\u770c(Gifu)");
    temp.save();
    // Shizuoka
    temp = new MRegion(country, "\u9759\u5ca1\u770c");
    temp.setDescription("\u9759\u5ca1\u770c(Shizuoka)");
    temp.save();
    // Aichi
    temp = new MRegion(country, "\u611b\u77e5\u770c");
    temp.setDescription("\u611b\u77e5\u770c(Aichi)");
    temp.save();
    // Mie
    temp = new MRegion(country, "\u4e09\u91cd\u770c");
    temp.setDescription("\u4e09\u91cd\u770c(Mie)");
    temp.save();
    // Siga
    temp = new MRegion(country, "\u6ecb\u8cc0\u770c");
    temp.setDescription("\u6ecb\u8cc0\u770c(Siga)");
    temp.save();
    // Kyoto
    temp = new MRegion(country, "\u4eac\u90fd\u5e9c");
    temp.setDescription("\u4eac\u90fd\u5e9c(Kyoto)");
    temp.save();
    // Osaka
    temp = new MRegion(country, "\u5927\u962a\u5e9c");
    temp.setDescription("\u5927\u962a\u5e9c(Osaka)");
    temp.save();
    // Hyogo
    temp = new MRegion(country, "\u5175\u5eab\u770c");
    temp.setDescription("\u5175\u5eab\u770c(Hyogo)");
    temp.save();
    // Nara
    temp = new MRegion(country, "\u5948\u826f\u770c");
    temp.setDescription("\u5948\u826f\u770c(Nara)");
    temp.save();
    // Wakayama
    temp = new MRegion(country, "\u548c\u6b4c\u5c71\u770c");
    temp.setDescription("\u548c\u6b4c\u5c71\u770c(Wakayama)");
    temp.save();
    // Tottori
    temp = new MRegion(country, "\u9ce5\u53d6\u770c");
    temp.setDescription("\u9ce5\u53d6\u770c(Tottori)");
    temp.save();
    // Shimane
    temp = new MRegion(country, "\u5cf6\u6839\u770c");
    temp.setDescription("\u5cf6\u6839\u770c(Shimane)");
    temp.save();
    // Okayama
    temp = new MRegion(country, "\u5ca1\u5c71\u770c");
    temp.setDescription("\u5ca1\u5c71\u770c(Okayama)");
    temp.save();
    // Hiroshima
    temp = new MRegion(country, "\u5e83\u5cf6\u770c");
    temp.setDescription("\u5e83\u5cf6\u770c(Hiroshima)");
    temp.save();
    // Yamaguchi
    temp = new MRegion(country, "\u5c71\u53e3\u770c");
    temp.setDescription("\u5c71\u53e3\u770c(Yamaguchi)");
    temp.save();
    // Tokushima
    temp = new MRegion(country, "\u5fb3\u5cf6\u770c");
    temp.setDescription("\u5fb3\u5cf6\u770c(Tokushima)");
    temp.save();
    // Kagawa
    temp = new MRegion(country, "\u9999\u5ddd\u770c");
    temp.setDescription("\u9999\u5ddd\u770c(Kagawa)");
    temp.save();
    // Ehime
    temp = new MRegion(country, "\u611b\u5a9b\u770c");
    temp.setDescription("\u611b\u5a9b\u770c(Ehime)");
    temp.save();
    // Kouchi
    temp = new MRegion(country, "\u9ad8\u77e5\u770c");
    temp.setDescription("\u9ad8\u77e5\u770c(Kouchi)");
    temp.save();
    // Fukuoka
    temp = new MRegion(country, "\u798f\u5ca1\u770c");
    temp.setDescription("\u798f\u5ca1\u770c(Fukuoka)");
    temp.save();
    // Saga
    temp = new MRegion(country, "\u4f50\u8cc0\u770c");
    temp.setDescription("\u4f50\u8cc0\u770c(Saga)");
    temp.save();
    // Nagasaki
    temp = new MRegion(country, "\u9577\u5d0e\u770c");
    temp.setDescription("\u9577\u5d0e\u770c(Nagasaki)");
    temp.save();
    // Kumamoto
    temp = new MRegion(country, "\u718a\u672c\u770c");
    temp.setDescription("\u718a\u672c\u770c(Kumamoto)");
    temp.save();
    // Ohita
    temp = new MRegion(country, "\u5927\u5206\u770c");
    temp.setDescription("\u5927\u5206\u770c(Ohita)");
    temp.save();
    // Miyasaki
    temp = new MRegion(country, "\u5bae\u5d0e\u770c");
    temp.setDescription("\u5bae\u5d0e\u770c(Miyasaki)");
    temp.save();
    // Kagoshima
    temp = new MRegion(country, "\u9e7f\u5150\u5cf6\u770c");
    temp.setDescription("\u9e7f\u5150\u5cf6\u770c(Kagoshima)");
    temp.save();
    // Okinawa
    temp = new MRegion(country, "\u6c96\u7e04\u770c");
    temp.setDescription("\u6c96\u7e04\u770c(Okinawa)");
    temp.save();
  } //	main
} //	MRegion
Beispiel #6
0
/**
 * GWT Server Implementation. You maintain one instance per User
 *
 * @author Jorg Janke, dzhao
 * @version $Id$
 */
public class GwtServer {

  public static void resetWinDefCache() {
    Userdef_Winids.reset();
    UIWindows.reset();
  }

  private static final CCache<WindowVOCacheKey, Integer> Userdef_Winids =
      new CCache<WindowVOCacheKey, Integer>("AD_Global_WindowVO", 200, 120);

  // use only one window cache
  private static final CCache<WindowCacheKey, UIWindow> UIWindows =
      new CCache<WindowCacheKey, UIWindow>("AD_Global_Window", 2000, 120);

  /** Logger */
  private static final CLogger log = CLogger.getCLogger(GwtServer.class);
  /** Server ID */
  private static AtomicInteger s_gwtServer_ID = new AtomicInteger(1);

  /** ************************************************************************* Gwt Server */
  public GwtServer() {
    m_context = new GWTServerContext();
    m_context.setContext(MRole.GWTSERVERID, s_gwtServer_ID.getAndIncrement());
  } // GwtServer

  /** Context */
  private final GWTServerContext m_context;

  /** Login */
  private Login m_login = null;

  /** Locale */
  private Locale m_loc = null;

  /** Role for User */
  private MRole m_role = null;

  /** Window Cache */
  // private final HashMap<Integer, UIWindow> m_windows
  // = new HashMap<Integer, UIWindow>(20);
  /** Tab Cache */
  private final HashMap<Integer, UITab> m_tabs = new HashMap<Integer, UITab>(20);

  private final HashMap<Integer, UITab> m_referencetabs = new HashMap<Integer, UITab>(20);

  /** Field Cache */
  private final HashMap<Integer, UIField> m_fields = new HashMap<Integer, UIField>(200);

  /** Tab Results */
  private final HashMap<Integer, ArrayList<String[]>> m_results =
      new HashMap<Integer, ArrayList<String[]>>();

  /** Dashboard Drilldowns */
  private final HashMap<String, NodeVO> m_nodes = new HashMap<String, NodeVO>();

  /**
   * Get Login
   *
   * @return login
   */
  public Login getLogin() {
    if (m_login == null) m_login = new Login(m_context);
    return m_login;
  } // getLogin

  /**
   * Returns the context associated with this GwtServer
   *
   * @return context
   */
  public CContext getContext() {
    return m_context;
  } // getContext

  /**
   * Get Role for User
   *
   * @return role
   */
  public MRole getRole() {
    if (m_role == null) {
      if (m_login == null
          || m_login.getRole() == null
          || m_login.getAD_Role_ID() == -1
          || m_login.getAD_User_ID() == -1) throw new IllegalArgumentException("Not logged in yet");
      m_role = m_login.getRole();
    }
    return m_role;
  } // getRole

  /**
   * Set Locale
   *
   * @param loc locale (from login)
   */
  public void setLocale(Locale loc) {
    m_loc = loc;
  } // setLocale

  /**
   * Logout
   *
   * @param expired expire
   */
  public void logout(boolean expired) {

    // End Session
    MSession session = MSession.get(m_context); // finish
    if (session != null) {
      if (expired) {
        if (session.getDescription() == null) session.setDescription("Expired");
        else session.setDescription(session.getDescription() + " Expired");
      }
      session.logout(); // saves
    }
    if (m_context != null) {
      int gwtServerID = m_context.getContextAsInt(MRole.GWTSERVERID);
      if (gwtServerID > 0) MRole.resetGwt(gwtServerID);
    }
    // Clear Cache
    m_tabs.clear();
    m_fields.clear();
    // m_windows.clear();
    m_context.clear();
    m_results.clear();
    //

  } // logout

  public boolean isLogout() {
    return m_context.size() == 0;
  }

  /** Finalize. Remove Role */
  @Override
  protected void finalize() throws Throwable {
    if (m_context != null) {
      int gwtServerID = m_context.getContextAsInt(MRole.GWTSERVERID);
      if (gwtServerID > 0) MRole.resetGwt(gwtServerID);
    }
    super.finalize();
  } // finalize

  /**
   * Get Locale
   *
   * @return Locale
   */
  public Locale getLocale() {
    if (m_loc == null) return Locale.US;
    return m_loc;
  } // getLocale

  /**
   * Get Menu
   *
   * @return menu as array list
   */
  public ArrayList<CTreeNode> getMenuTree() {
    int AD_Tree_ID = getTreeID();
    log.fine("AD_Tree_ID=" + AD_Tree_ID + " - " + Env.getAD_Language(m_context));
    return getMenuTree(AD_Tree_ID, false);
  } // getMenuTree

  /**
   * Get Tree ID for role
   *
   * @return AD_Tree_ID as int
   */
  private int getTreeID() {
    int AD_Role_ID = m_context.getAD_Role_ID();
    // Load Menu Structure ----------------------
    int AD_Tree_ID =
        QueryUtil.getSQLValue(
            null,
            "SELECT COALESCE(r.AD_Tree_Menu_ID, ci.AD_Tree_Menu_ID)"
                + "FROM AD_ClientInfo ci"
                + " INNER JOIN AD_Role r ON (ci.AD_Client_ID=r.AD_Client_ID) "
                + "WHERE AD_Role_ID=?",
            AD_Role_ID);
    if (AD_Tree_ID <= 0) AD_Tree_ID = 10; // Menu
    return AD_Tree_ID;
  } // getTreeID

  /**
   * Get Menu favorites for a user
   *
   * @return menu as array list
   */
  public ArrayList<CTreeNode> getMenuFavorites() {
    MUser user = MUser.get(getContext());
    int AD_Tree_ID = user.getAD_Tree_MenuFavorite_ID();
    if (AD_Tree_ID == 0) // favorites has not yet been created
    return new ArrayList<CTreeNode>();
    return getMenuTree(AD_Tree_ID, false);
  } // get favorites menu

  /**
   * Get Menu tree that directly enter "create new" mode
   *
   * @return menu as array list
   */
  public ArrayList<CTreeNode> getMenuCreateNew() {
    MUser user = MUser.get(getContext());
    int AD_Tree_ID = user.getAD_Tree_MenuNew_ID();
    if (AD_Tree_ID == 0) // create new has not yet been created
    return new ArrayList<CTreeNode>();
    return getMenuTree(AD_Tree_ID, false);
  } // getMenuCreateNew

  /**
   * Get a menu tree representation based on a AD_Tree_ID
   *
   * @param AD_Tree_ID A tree based on AD_Menu
   * @return menu as array list
   */
  private ArrayList<CTreeNode> getMenuTree(int AD_Tree_ID, boolean edit) {
    MTree tree = new MTree(m_context, AD_Tree_ID, edit, true, true, null); // Language
    // set
    // in
    // WLogin
    // Trim tree
    CTreeNode root = tree.getRoot();
    Enumeration<?> en = root.preorderEnumeration();
    while (en.hasMoreElements()) {
      CTreeNode nd = (CTreeNode) en.nextElement();
      if (nd.isTask() || nd.isWorkbench() // || nd.isWorkFlow()
      // server
      ) {
        CTreeNode parent = (CTreeNode) nd.getParent();
        parent.remove(nd);
      }
    }
    tree.trimTree();
    en = root.preorderEnumeration();
    ArrayList<CTreeNode> retValue = new ArrayList<CTreeNode>();
    while (en.hasMoreElements()) {
      CTreeNode nd = (CTreeNode) en.nextElement();
      // Issue #420: removed menu entries for un-implemented forms
      if (nd.getAD_Form_ID() == 119 || nd.getAD_Form_ID() == 102
      //					|| nd.getAD_Workflow_ID() == 106
      //					|| nd.getAD_Workflow_ID() == 104
      //					// Review
      //					|| nd.getAD_Workflow_ID() == 112
      //					// Setup
      //					|| nd.getAD_Workflow_ID() == 113
      //					|| nd.getAD_Workflow_ID() == 110
      //					|| nd.getAD_Workflow_ID() == 111
      // || nd.getAD_Process_ID() == 205
      ) {
      } else retValue.add(nd);
    }
    return retValue;
  }

  /**
   * Make Favorites add/remove persistent ("bar" in swing client)
   *
   * @param add true if add - otherwise remove
   * @param Node_ID Node ID
   * @return true if updated
   */
  public boolean updateFavorites(boolean add, int Node_ID) {
    /*
     * Code logic now uses MUser to store favorites. TODO:
     * VTreePanel.barDBupdate should be similarly updated or deprecated for
     * Swing client.
     */
    MUser user = MUser.get(getContext());
    return user.addUserMenuFavorite(Node_ID, 0);
  } // updateFavorites

  /**
   * Update of user favorites for a user with specified ordering for favorites
   *
   * @param menuIDs List<Integer> ordered list of menuIDs to put in the tree
   * @return true if updated
   */
  public boolean updateFavorites(List<Integer> menuIDs) {
    MUser user = MUser.get(getContext());
    MTree menuTree = null;
    if ((menuTree = user.getUserFavoriteTree()) == null) return false;
    return updateUserTree(menuIDs, menuTree);
  } // updateFavorites

  /**
   * Make create new add/remove persistent ("bar" in swing client)
   *
   * @param add true if add - otherwise remove
   * @param Node_ID Node ID
   * @return true if updated
   */
  public boolean updateCreateNew(boolean add, int Node_ID) {
    /*
     * Code logic now uses MUser to store favorites. TODO:
     * VTreePanel.barDBupdate should be similarly updated or deprecated for
     * Swing client.
     */
    MUser user = MUser.get(getContext());
    return user.addUserMenuNewFavorite(Node_ID, 0);
  } // updateCreateNew

  /**
   * Update of user favorites for a user with specified ordering for favorites
   *
   * @param menuIDs List<Integer> ordered list of menuIDs to put in the tree
   * @return true if updated
   */
  public boolean updateCreateNew(List<Integer> menuIDs) {
    MUser user = MUser.get(getContext());
    MTree menuTree = null;
    if ((menuTree = user.getUserNewFavoriteTree()) == null) return false;
    return updateUserTree(menuIDs, menuTree);
  } // updateCreateNew

  /*
   * Update of user tree for ordered menu nodes (favorites, create new list)
   * favorites @param menuIDs List<Integer> ordered list of menuIDs to put in
   * the tree @param menuTree MTree the tree to be reordered @return true if
   * updated
   */
  private boolean updateUserTree(List<Integer> menuIDs, MTree menuTree) {
    CTreeNode root = menuTree.getRoot();
    if (root != null) {
      Enumeration<?> nodes = root.preorderEnumeration();
      while (nodes.hasMoreElements()) {
        CTreeNode nd = (CTreeNode) nodes.nextElement();
        if (!menuIDs.contains(nd.getNode_ID())) {
          MTreeNodeMM node = null;
          if ((node = MTreeNodeMM.get(menuTree, nd.getNode_ID())) != null) {
            if (!node.delete(true)) return false;
          }
        }
      }
    }
    int seq = 0;
    for (int id : menuIDs) {
      MTreeNodeMM node = null;
      if ((node = MTreeNodeMM.get(menuTree, id)) == null) {
        node = new MTreeNodeMM(menuTree, id);
      }
      node.setSeqNo(++seq);
      if (!node.save()) return false;
    }
    return true;
  }

  /**
   * Get Number of open Requests
   *
   * @return number of requests
   */
  public int getRequests() {
    return GwtServerUtil.getRequests(m_context);
  } // getRequests

  /**
   * Get number of open Notes
   *
   * @return Number of notes
   */
  public int getNotes() {
    return GwtServerUtil.getNotes(m_context);
  } // getNotes

  /**
   * ************************************************************************* Get Window in default
   * context based on Role
   *
   * @param windowNO relative window
   * @param AD_Window_ID window
   * @param AD_Menu_ID menu
   * @return WindowVO or null
   */
  public UIWindow getWindow(int windowNO, int AD_Window_ID, int AD_Menu_ID) {
    UIWindow win = null;
    // win = m_windows.get(AD_Window_ID);
    // if (win != null)
    // {
    // win.clearLookupCache();
    // return win;
    // }
    UIWindowVOFactory winFactory = new UIWindowVOFactory();
    UIWindowVO winVO = null;
    int AD_UserDef_Win_ID = -1;
    WindowVOCacheKey vokey =
        new WindowVOCacheKey(
            AD_Window_ID, m_context.getAD_Role_ID(), AD_Menu_ID, Env.getAD_Language(m_context));

    // note, the usage of m_context below in constructing window is only for
    // language, menu, role,
    // and those are already included in the cache key, so we can safely
    // assume the win is correctly cached
    if (Userdef_Winids.get(null, vokey) == null) {
      winVO = winFactory.get(m_context, AD_Window_ID, AD_Menu_ID);
      if (winVO == null) {
        log.config("No Window - AD_Window_ID=" + AD_Window_ID + ",AD_Menu_ID=" + AD_Menu_ID);
        return null;
      }
      int theAD_UserDef_Win_ID = winVO.getAD_UserDef_Win_ID();

      if (Userdef_Winids.putIfAbsent(vokey, theAD_UserDef_Win_ID) == null)
        AD_UserDef_Win_ID = theAD_UserDef_Win_ID;
    } else AD_UserDef_Win_ID = Userdef_Winids.get(m_context, vokey);

    WindowCacheKey key =
        new WindowCacheKey(
            AD_Window_ID,
            AD_UserDef_Win_ID,
            m_context.getAD_Role_ID(),
            AD_Menu_ID,
            Env.getAD_Language(m_context));
    win = UIWindows.get(null, key);
    if (win == null) {
      // log.warning("key:" + key + " not found, create");
      if (winVO == null) winVO = winFactory.get(m_context, AD_Window_ID, AD_Menu_ID);
      if (winVO == null) {
        log.config("No Window - AD_Window_ID=" + AD_Window_ID + ",AD_Menu_ID=" + AD_Menu_ID);
        return null;
      }
      UIWindow newWin = new UIWindow(winVO);
      AD_Window_ID = newWin.getAD_Window_ID();
      //
      UIFieldVOFactory fieldFactory = new UIFieldVOFactory();
      newWin.setFields(fieldFactory.getAll(m_context, AD_Window_ID, AD_UserDef_Win_ID));
      //
      UITabVOFactory tabFactory = new UITabVOFactory();
      // setTabVOs initrlize tabs but not fields, 'cuz fields needs to be
      // copied over and initialized later
      newWin.setTabVOsWithFieldsUninitialized(
          m_context, tabFactory.getAll(m_context, AD_Window_ID, AD_UserDef_Win_ID), windowNO);
      win = UIWindows.putIfAbsent(key, newWin);
      if (win == null) win = newWin;
    }
    // deep copy the window object so we hold a separate window object for
    // each user session
    UIWindow duplicatedWin = (UIWindow) DeepCopy.copy(win);
    log.fine(duplicatedWin.toString());
    fillTabsFieldsAndInitFieldsAndCreateDependencyRelations(duplicatedWin, windowNO);

    MSession session = MSession.get(m_context);
    if (session != null)
      session.windowLog(
          m_context.getAD_Client_ID(),
          m_context.getAD_Org_ID(),
          duplicatedWin.getAD_Window_ID(),
          0);

    return duplicatedWin;
  } // getWindowVO

  /**
   * Get Tab with ID
   *
   * @param AD_Tab_ID
   * @return tab or null
   */
  public UITab getTab(int AD_Tab_ID) {
    Integer tabKey = Integer.valueOf(AD_Tab_ID);
    UITab tab = m_tabs.get(tabKey);
    if (tab == null) {
      // Check added for referenced tabs
      if (m_referencetabs.get(tabKey) != null) return m_referencetabs.get(tabKey);
      throw new CompiereStateException("No such tab:" + AD_Tab_ID);
    } // find in window
    return tab;
  } // getTab

  /**
   * Get Field
   *
   * @param AD_Field_ID id
   * @param windowNo relative windowNo
   * @return field or null
   */
  public UIField getField(int AD_Field_ID, int windowNo) {
    Integer key = Integer.valueOf(AD_Field_ID);
    UIField field = m_fields.get(key);
    if (field == null) {
      UIFieldVOFactory fieldFactory = new UIFieldVOFactory();
      UIFieldVO vo = fieldFactory.get(m_context, AD_Field_ID);
      // m_context.setSOTrx(windowNo, isSOTrx);
      if (vo != null) {
        field = new UIField(vo);
        field.initialize(m_context, windowNo);
        log.warning("Loaded directly: " + field); // SOTrx may not
        // be correct
        m_fields.put(key, field); // save in cache
      }
    } // create new
    return field;
  } // getField

  /** Fill Tab and Field arrays */
  private void fillTabsFieldsAndInitFieldsAndCreateDependencyRelations(UIWindow win, int windowNO) {
    ArrayList<UITab> tabs = win.getTabs();
    for (int j = 0; j < tabs.size(); j++) {
      UITab winTab = tabs.get(j);
      Integer tabKey = Integer.valueOf(winTab.getAD_Tab_ID());
      Integer ReferencetabKey = Integer.valueOf(winTab.getReferenced_Tab_ID());
      m_tabs.put(tabKey, winTab);
      m_referencetabs.put(ReferencetabKey, winTab);
      //
      ArrayList<UIField> fields = winTab.getFields();
      for (int k = 0; k < fields.size(); k++) {
        UIField field = fields.get(k);
        field.initialize(m_context, windowNO);
        Integer fieldKey = Integer.valueOf(field.getAD_Field_ID());
        // set the correct value
        if (field.isLookup()) field.getLookup().setContext(m_context, windowNO);
        m_fields.put(fieldKey, field);
      }
      winTab.createDependencyRelations();
    }
  } // fillTabsFields

  /**
   * Execute Query for Tab
   *
   * @param AD_Tab_ID tab
   * @param queryVO optional query
   * @param context record context for link columns and other variables
   * @param queryResultID stored query identifier provided by client
   * @return number of records or -1 if error
   */
  public int executeQuery(
      int AD_Tab_ID, QueryVO queryVO, HashMap<String, String> context, int queryResultID) {
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return -1;
    }
    ArrayList<String[]> result = tab.executeQueryString(queryVO, context, m_context);
    if (result == null) {
      log.config("Not Result for AD_Tab_ID=" + AD_Tab_ID);
      return -1;
    }
    MRole role = getRole();
    // return -1 to indicate query exceeds
    if (role.isQueryMax(result.size())) {
      m_results.put(queryResultID, new ArrayList<String[]>());
      return -1;
    }
    m_results.put(queryResultID, result);
    return result.size();
  } // executeQuery

  public Query createQuery(int AD_Tab_ID, QueryVO queryVO, WindowCtx ctx, String tableName) {
    UITab tab = getTab(AD_Tab_ID);
    String whereClause = tab.getWhereClause();
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return null;
    }
    Query result = tab.createQueryForReport(m_context, queryVO);
    if (result == null) {
      result = new Query(tableName);
    }
    if (whereClause != null && whereClause.length() != 0) {
      QueryRestriction restriction = new QueryRestriction(whereClause);
      result.addRestriction(restriction);
    }
    return result;
  } // executeQuery

  /**
   * Retrieve results for Tab. If the from/to range does not exist, it returns existing rows
   *
   * @param queryResultID stored query identifier provided by client
   * @param fromRow from row first is 0
   * @param noRows number of rows
   * @return array of rows of array of field values or null if error. You get the columnNames via
   *     String[] columns = uiTab.getColumnNames();
   */
  public String[][] getResults(int queryResultID, int fromRow, int noRows) {
    if (noRows < 0) {
      log.config("Invalid: fromRow=" + fromRow + ",noRows" + noRows);
    } else if (noRows == 0) return new String[][] {};
    //
    ArrayList<String[]> resultAll = m_results.get(queryResultID);
    if (resultAll == null) {
      log.config("No Results for queryResultID=" + queryResultID);
      return null;
    }
    if (resultAll.size() < fromRow) {
      log.config(
          "Insufficient Results for queryResultID="
              + queryResultID
              + ", Length="
              + resultAll.size()
              + ", fromRow="
              + fromRow);
      return null;
    }
    // copy
    if (resultAll.size() < noRows) {
      log.config(
          "Insufficient Rows for queryResultID="
              + queryResultID
              + ", Length="
              + resultAll.size()
              + ", fromRow="
              + fromRow
              + ", noRows="
              + noRows);
      noRows = resultAll.size();
    }
    String[][] result = new String[noRows][];
    for (int i = 0; i < noRows; i++) {
      int index = i + fromRow;
      if (index >= resultAll.size()) break;
      result[i] = resultAll.get(index);
    }
    return result;
  } // getResult

  public void sortResults(
      int WindowNo, int AD_Tab_ID, int AD_Field_ID, int queryResultID, final boolean ascending) {
    class SortCell {

      String[] row;

      String sort;
    }
    ArrayList<String[]> results = m_results.get(queryResultID);
    if (results == null)
      log.severe("cannot sort. results non-existent for queryResultID:" + queryResultID);
    UITab tab = getTab(AD_Tab_ID);
    final UIField field = getField(AD_Field_ID, WindowNo);
    final int displayType = field.getAD_Reference_ID();
    final int idx = tab.getFieldIndex(AD_Field_ID);
    // if not a lookup, directly sort
    if (!field.isLookup()) {
      if (FieldType.isNumeric(displayType)) {
        Collections.sort(
            results,
            new Comparator<String[]>() {

              @Override
              public int compare(String[] o1, String[] o2) {
                if (o1[idx] == null) o1[idx] = "";
                if (o2[idx] == null) o2[idx] = "";
                BigDecimal s1 = new BigDecimal(o1[idx].equals("") ? "-1e-10" : o1[idx]);
                BigDecimal s2 = new BigDecimal(o2[idx].equals("") ? "-1e-10" : o2[idx]);
                return ascending ? s1.compareTo(s2) : s2.compareTo(s1);
              }
            });
      } else if (FieldType.isDate(displayType)) {
        Collections.sort(
            results,
            new Comparator<String[]>() {

              @Override
              public int compare(String[] o1, String[] o2) {
                if (o1[idx] == null) o1[idx] = "";
                if (o2[idx] == null) o2[idx] = "";
                Long s1 = new Long(o1[idx].equals("") ? "-1000000" : o1[idx]);
                Long s2 = new Long(o2[idx].equals("") ? "-1000000" : o2[idx]);
                return ascending ? s1.compareTo(s2) : s2.compareTo(s1);
              }
            });
      } else {
        Collections.sort(
            results,
            new Comparator<String[]>() {

              @Override
              public int compare(String[] o1, String[] o2) {
                if (o1[idx] == null) o1[idx] = "";
                if (o2[idx] == null) o2[idx] = "";
                String s1 = o1[idx];
                String s2 = o2[idx];
                return ascending ? s1.compareTo(s2) : s2.compareTo(s1);
              }
            });
      }
      return;
    }
    Comparator<SortCell> c =
        new Comparator<SortCell>() {

          public int compare(SortCell o1, SortCell o2) {
            if (ascending) return o1.sort.compareTo(o2.sort);
            else return o2.sort.compareTo(o1.sort);
          }
        };
    // for look up, first get id values
    ArrayList<String> fieldValues = new ArrayList<String>(results.size());
    for (String[] row : results) {
      fieldValues.add(row[idx]);
    }
    // then translate into real values
    ArrayList<String> sorts = getLookupValueOnlyDirect(AD_Field_ID, fieldValues, true);
    ArrayList<SortCell> toBeSorteds = new ArrayList<SortCell>(sorts.size());
    for (int i = 0; i < sorts.size(); i++) {
      SortCell toBeSorted = new SortCell();
      toBeSorted.row = results.get(i);
      toBeSorted.sort = sorts.get(i);
      toBeSorteds.add(toBeSorted);
    }
    // sort
    Collections.sort(toBeSorteds, c);
    // after sorting, replace col with original values
    int i = 0;
    for (SortCell toBeSorted : toBeSorteds) {
      results.set(i, toBeSorted.row);
      i++;
    }
  }

  public void copyQueryResults(int sourceID, int destID) {
    ArrayList<String[]> results = m_results.get(sourceID);
    m_results.put(destID, results);
  }

  // Method to return a list of matches according to fields for a tab, using
  // the cached results
  // this does not store the result in the cache - this behavior is deferred
  // to the caller
  private int searchTabResults(
      int WindowNo,
      UITab tab,
      List<Integer> fieldIds,
      int queryResultID,
      int searchResultID,
      String query,
      int rowCount) {
    ArrayList<String[]> results = m_results.get(queryResultID);
    if (query.trim().equals("")) {
      m_results.put(searchResultID, results);
      return results.size();
    }
    ScoreStrategy scorer = new ScoreStrategy(query);
    ScoreCell[] scores = new ScoreCell[results.size()];
    // first initialize score cells
    int j = 0;
    for (String[] result : results) {
      // initialize score cells
      ScoreCell score = new ScoreCell();
      score.row = result;
      score.score = scorer.createScore();
      scores[j++] = score;
    }
    for (int id : fieldIds) {
      UIField field = getField(id, WindowNo);
      final int idx = tab.getFieldIndex(id);
      if (field.isLookup()) {
        ArrayList<String> fieldValues = new ArrayList<String>(results.size());
        for (String[] row : results) {
          fieldValues.add(row[idx]);
        }
        ArrayList<String> sorts = getLookupValueOnlyDirect(id, fieldValues, true);
        int i = 0;
        for (String value : sorts) {
          scorer.getScore(value, scores[i].score);
          i++;
        }
      } else {
        int i = 0;
        for (String[] row : results) {
          String value = row[idx];
          scorer.getScore(value, scores[i].score);
          i++;
        }
      }
    }
    ArrayList<ScoreCell> matchingScores = new ArrayList<ScoreCell>();
    for (ScoreCell cell : scores) {
      if (cell.score.isMatch) {
        matchingScores.add(cell);
      }
    }
    Collections.sort(matchingScores, scorer);
    ArrayList<String[]> matches = new ArrayList<String[]>();
    for (ScoreCell score : matchingScores) {
      matches.add(score.row);
    }
    m_results.put(searchResultID, matches);
    return matches.size();
  }

  public String[][] getTabSearchResults(int searchResultID, int rowCount) {
    ArrayList<String[]> matches = m_results.get(searchResultID);
    if (matches != null) {
      if (matches.size() < rowCount) {
        rowCount = matches.size();
      }
      String[][] result = new String[rowCount][];
      int i = 0;
      for (String[] row : matches) {
        result[i++] = row;
        if (i == rowCount) break;
      }
      return result;
    } else {
      return new String[0][];
    }
  }

  /**
   * Execute Query for Tab. If the from/to range does not exist, it returns existing rows
   *
   * @param queryResultID stored query identifier provided by client
   * @param row row number first is 0
   * @return array of rows of array of field values or null if error. You get the columnNames via
   *     String[] columns = uiTab.getColumnNames();
   */
  public String[] requery(int queryResultID, int row) {
    // TODO requery
    String[][] results = getResults(queryResultID, row, 1);
    return results[0];
  } // requery

  /**
   * Release Results
   *
   * @param resultIDs stored query identifier provided by client
   */
  public void disposeWindow(ArrayList<Integer> resultIDs) {
    // System.out.println("before cached id:" + m_results.keySet());
    for (Integer queryResultID : resultIDs) m_results.remove(queryResultID);
    // System.out.println("after cached id:" + m_results.keySet());
    m_context.removeAllWindows();
  } // releaseResults

  /**
   * Create new Row with Default values. The new Row is not saved in Results
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param context record context for parent columns and other variables
   * @return array of field values or null if error. You get the columnNames via String[] columns =
   *     uiTab.getColumnNames();
   */
  public ChangeVO newRow(int windowNo, int AD_Tab_ID, Map<String, String> context) {
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return null;
    }
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ctx.setIsSOTrx(windowNo, tab.isSOTrx());
    ChangeVO change = tab.newRow(ctx, windowNo);
    /**
     * Very likely not needed if (change.changedDropDowns == null) change.changedDropDowns = new
     * HashMap<String,ArrayList<NamePair>>(); for(UIField f:tab.getFields()) { if
     * (f.isDependentValue()) change.changedDropDowns.put(f.getColumnName(),
     * getLookupValues(windowNo, f.getAD_Field_ID(), change.changedFields)); }
     */
    tab.canUpdate(ctx, windowNo, change);
    return change;
  } // newRow

  /**
   * Refresh current row of Tab
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param relRowNo relative row number in results
   * @param context current (relevant) context of new row
   * @return error message or null
   */
  public ChangeVO refreshRow(
      int windowNo, int AD_Tab_ID, int queryResultID, int relRowNo, Map<String, String> context) {
    if (context == null || context.size() == 0) return new ChangeVO(true, "No Context");
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
    }
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ChangeVO retValue = tab.refreshRow(ctx, windowNo);
    if (retValue.hasError()) return retValue;
    // Update Results
    ArrayList<String[]> data = m_results.get(queryResultID);
    if (data == null) retValue.addError("Data Not Found");
    else {
      String[] dataRow = retValue.rowData.clone();
      data.set(relRowNo, dataRow);
      postProcessChangeVO(retValue, windowNo, context, dataRow, tab);
      retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
    }
    return retValue;
  } // refreshRow

  public ChangeVO updateRow(
      int windowNo,
      int AD_Tab_ID,
      int queryResultID,
      int relRowNo,
      Map<String, String> context,
      boolean force) {
    if (context == null || context.size() == 0)
      return new ChangeVO(true, Msg.translate(m_context, "NoContext"));
    ArrayList<String[]> data = m_results.get(queryResultID);
    if (data == null || data.size() == 0)
      return new ChangeVO(true, Msg.translate(m_context, "CachedDataNotFound"));
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return new ChangeVO(true, Msg.translate(m_context, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID));
    }
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ChangeVO retValue;
    if (force) retValue = tab.saveRow(ctx, windowNo, false, null);
    else retValue = tab.saveRow(ctx, windowNo, false, data.get(relRowNo));
    if (retValue.hasError()) return retValue;
    // Update Results
    String[] dataRow = retValue.rowData.clone();
    data.set(relRowNo, dataRow);
    postProcessChangeVO(retValue, windowNo, context, dataRow, tab);
    retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
    if (retValue.isRefreshAll()) {}
    return retValue;
  }

  private void postProcessChangeVO(
      ChangeVO change, int windowNo, Map<String, String> context, String[] dataRow, UITab tab) {
    // make an updated context to get the necessary listboxvos
    Map<String, String> contextAfterUpdate = new HashMap<String, String>(context);
    int j = 0;
    for (UIField field : tab.getFields()) {
      contextAfterUpdate.put(field.getColumnName(), dataRow[j]);
      j++;
    }
    // now change rowData to remove password, and reload the changed
    // listboxes
    j = 0;
    for (UIField field : tab.getFields()) {
      // return an empty string for passwords etc
      if (field.isEncryptedField()
          || field.isEncryptedColumn()
          || "Password".equals(field.getColumnName())) change.rowData[j] = "";
      if (FieldType.isClientLookup(field.getAD_Reference_ID()) && field.isDependentValue()) {
        if (change.changedDropDowns == null)
          change.changedDropDowns = new HashMap<String, ArrayList<NamePair>>();
        ArrayList<NamePair> values;
        if (field.getAD_Reference_ID() == DisplayTypeConstants.Search) {
          ArrayList<String> t = new ArrayList<String>(1);
          t.add(context.get(field.getColumnName()));
          values = getLookupValueDirect(field.getAD_Field_ID(), t, true);
        } else values = getLookupData(windowNo, field.getAD_Field_ID(), context, true);
        change.changedDropDowns.put(field.getColumnName(), values);
      }
      j++;
    }
  }

  /**
   * Save (Update existing) Row of Tab
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param relRowNo relative row number in results
   * @param context current (relevant) context of new row
   * @return error message or null
   */
  public ChangeVO updateRow(
      int windowNo, int AD_Tab_ID, int queryResultID, int relRowNo, Map<String, String> context) {
    return updateRow(windowNo, AD_Tab_ID, queryResultID, relRowNo, context, false);
  } // updateRow

  /**
   * Save (Insert new) Row of Tab
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param curRow insert after relative row number in results
   * @param context current (relevant) context of new row
   * @return error message or null
   */
  public ChangeVO insertRow(
      int windowNo, int AD_Tab_ID, int queryResultID, int curRow, Map<String, String> context) {
    if (context == null || context.size() == 0) return new ChangeVO(true, "No Context");
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
    }

    log.info("Line Amt:" + context.get("LineNetAmt"));
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ChangeVO retValue = tab.saveRow(ctx, windowNo, true);
    if (retValue.hasError()) return retValue;
    // Update Results
    ArrayList<String[]> data = m_results.get(queryResultID);
    if (data == null) retValue.addError("Data Not Found");
    else {
      String[] dataRow = retValue.rowData;
      if (curRow >= data.size()) data.add(dataRow);
      else data.add(curRow, dataRow);
      retValue.trxInfo = GridTab.getTrxInfo(tab.getTableName(), ctx, windowNo, tab.getTabNo());
    }
    return retValue;
  } // insertRow

  /**
   * Delete existing Row
   *
   * @param windowNo relative window
   * @param AD_Tab_ID tab
   * @param relRowNo relative row number in results
   * @return error message or null
   */
  public ChangeVO deleteRow(int windowNo, int AD_Tab_ID, int queryResultID, int relRowNo) {
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return new ChangeVO(true, "@NotFound@ @AD_Tab_ID@=" + AD_Tab_ID);
    }
    ArrayList<String[]> data = m_results.get(queryResultID);
    if (data == null) return new ChangeVO(true, "Data Not Found");
    String[] rowData = data.get(relRowNo);
    // Copy Data into Context
    Map<String, String> context = new HashMap<String, String>();
    String[] columns = tab.getColumnNames();
    for (int i = 0; i < columns.length; i++) {
      String column = columns[i];
      context.put(column, rowData[i]);
    }
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    ChangeVO retValue = tab.deleteRow(ctx, windowNo);
    if (retValue.hasError()) return retValue;
    // Update Results
    data.remove(relRowNo);
    return retValue;
  } // deleteRow

  /**
   * Field Changed
   *
   * @param windowNo relative window
   * @param AD_Field_ID field
   * @param AD_Tab_ID tab
   * @param oldValue old field value
   * @param newValue new field value
   * @param context record context
   * @return Field Change VO
   */
  public ChangeVO fieldChanged(
      int windowNo,
      int AD_Field_ID,
      int AD_Tab_ID,
      String oldValue,
      String newValue,
      Map<String, String> context) {
    // Same Values
    if (oldValue == null || oldValue.equals(Null.NULLString)) oldValue = "";
    if (newValue == null || newValue.equals(Null.NULLString)) newValue = "";
    if (oldValue.equals(newValue)) return null;
    //
    UITab tab = getTab(AD_Tab_ID);
    if (tab == null) {
      log.config("Not found AD_Tab_ID=" + AD_Tab_ID);
      return null;
    }
    UIField field = getField(AD_Field_ID, windowNo);
    if (field == null) {
      log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
      return null;
    }

    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    CContext origCtx = new CContext(m_context.entrySet());
    origCtx.addWindow(windowNo, context);
    ChangeVO change = null;
    try {
      // reset the thread active flag, in case the thread is reused later on
      CThreadUtil.setCalloutActive(false);
      change =
          tab.fieldChanged(
              origCtx, ctx, new ArrayList<UIField>(5), windowNo, field, oldValue, newValue);
      CThreadUtil.setCalloutActive(false);
      ctx.setContext(windowNo, field.getColumnName(), change.newConfirmedFieldValue);
    } catch (Exception e) {
      log.severe("fieldChange error:" + field.getColumnName() + e.getMessage());
    } finally {
      CThreadUtil.setCalloutActive(false);
    }

    return change;
  } // fieldChanged

  /**
   * Get Field Lookup Value Direct
   *
   * @param windowNo Window
   * @param AD_Field_ID
   * @param keyValues array of id values
   * @param cache
   * @return list of display values
   */
  public ArrayList<NamePair> getLookupValueDirect(
      int AD_Field_ID, ArrayList<String> keyValues, boolean cache) {
    int windowNo = 0; // No Context
    ArrayList<NamePair> displayValues = new ArrayList<NamePair>();
    UIField field = getField(AD_Field_ID, windowNo);

    // if (cache && field.isLookup())
    // field.getLookup().removeAllElements();
    if (field == null) log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
    //
    for (int i = 0; i < keyValues.size(); i++) {
      String key = keyValues.get(i);
      String value = null;
      if (field != null) value = field.getLookupDisplay(m_context, windowNo, key, cache);
      if (value == null) {
        /*
         * if(key == null) value = ""; else value = "<" + key + ">";
         */
        value = "";
      }
      NamePair pp = new ValueNamePair(key, value);
      displayValues.add(pp);
    }
    return displayValues;
  } // getLookupValueDirect

  /**
   * Get Field Lookup Value Direct
   *
   * @param windowNo Window
   * @param AD_Field_ID
   * @param keyValues array of id values
   * @param cache
   * @return list of display values
   */
  public ArrayList<String> getLookupValueOnlyDirect(
      int AD_Field_ID, ArrayList<String> keyValues, boolean cache) {
    int windowNo = 0; // No Context
    ArrayList<String> displayValues = new ArrayList<String>();
    UIField field = getField(AD_Field_ID, windowNo);
    if (field == null) log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
    //
    for (int i = 0; i < keyValues.size(); i++) {
      String key = keyValues.get(i);
      String value = null;
      if (field != null) value = field.getLookupDisplay(m_context, windowNo, key, cache);
      if (value == null) {
        /*
         * if(key == null) value = ""; else value = "<" + key + ">";
         */
        value = "";
      }
      displayValues.add(value);
    }
    return displayValues;
  } // getLookupValueDirect

  /**
   * Get Lookup Data for Field in context
   *
   * @param AD_Field_ID field
   * @param context context
   * @param refresh requery
   * @return lookup pair array
   */
  public ArrayList<NamePair> getLookupData(
      int windowNo, int AD_Field_ID, Map<String, String> context, boolean refresh) {
    UIField field = getField(AD_Field_ID, windowNo);
    if (field == null) {
      log.warning("Cannot find AD_Field_ID=" + AD_Field_ID);
      return null;
    }
    CContext ctx = new CContext(m_context.entrySet());
    ctx.addWindow(windowNo, context);
    if (field.isLookup() || field.isButtonLookup()) return field.getAllLookupData(ctx, windowNo);
    else log.warning("No Lookup: " + field.getColumnName());
    return null;
  } // getLookupData

  /**
   * ************************************************************************* Get All Lookup Data
   * for fields w/o context dependency
   *
   * @param AD_Tab_ID tab
   * @return map if FiledName and lookup pair array public Map<String,NamePair[]> getLookupDataAll
   *     (int AD_Tab_ID) { return null; } // getLookuupDataAll /**
   *     ************************************************************************
   */
  private static int curZoomWindowNO = 0;

  public int getZoomWindowNO() {
    curZoomWindowNO += 100;
    return curZoomWindowNO;
  }

  public Boolean savePreferences(Map<String, String> ctx) {
    CContext cContext = getContext();
    MUser user = MUser.get(cContext);
    MUserPreference preference = user.getPreference();
    String printerName = ctx.get("PrinterName");
    if (printerName != null && printerName.trim().equalsIgnoreCase("")) {
      cContext.setPrinterName(printerName);
      preference.setPrinterName(printerName);
    }
    String autoCommit = ctx.get("AutoCommit");
    if (autoCommit != null) {
      cContext.setAutoCommit(autoCommit.trim().equalsIgnoreCase("Y"));
      preference.setIsAutoCommit(autoCommit.trim().equalsIgnoreCase("Y"));
    }
    String showAdvanced = ctx.get("#ShowAdvanced");
    if (showAdvanced != null) {
      cContext.setContext("#ShowAdvanced", showAdvanced);
      preference.setIsShowAdvanced(showAdvanced.trim().equalsIgnoreCase("Y"));
    }
    String showAccounting = ctx.get("#ShowAcct");
    if (showAccounting != null) {
      cContext.setContext("#ShowAcct", showAccounting);
      preference.setIsShowAcct(showAccounting.trim().equalsIgnoreCase("Y"));
    }
    String showTranslation = ctx.get("#ShowTrl");
    if (showTranslation != null) {
      cContext.setContext("#ShowTrl", showTranslation);
      preference.setIsShowTrl(showTranslation.trim().equalsIgnoreCase("Y"));
    }
    String uiTheme = ctx.get("#UITheme");
    if (uiTheme != null && !uiTheme.trim().equalsIgnoreCase("")) {
      cContext.setContext("#UITheme", uiTheme);
      preference.setUITheme(uiTheme);
    }

    String printPreview = ctx.get("#PrintPreview");
    if (printPreview != null) {
      cContext.setPrintPreview(printPreview.equalsIgnoreCase("Y"));
      Ini.setProperty(Ini.P_PRINTPREVIEW, printPreview.equalsIgnoreCase("Y"));
      Ini.saveProperties(Ini.isClient());
    }

    String date = ctx.get("#Date");
    cContext.setContext("#Date", date);

    return preference.save();
  }

  public Boolean deleteSavedSearch(int tab_ID, String savedSearchName) {
    CContext cContext = getContext();
    MUserQuery query = MUserQuery.getForUser(cContext, tab_ID, savedSearchName);
    if (query != null)
      if (query.deleteLines()) {
        if (query.delete(true)) {
          return true;
        }
      }
    return false;
  } // deleteSavedsearch

  private static class WindowCacheKey extends WindowVOCacheKey {

    WindowCacheKey(
        int AD_Window_ID,
        int AD_UserDef_Win_ID,
        int AD_Role_ID,
        int AD_Menu_ID,
        String AD_Language) {
      super(AD_Window_ID, AD_Role_ID, AD_Menu_ID, AD_Language);
      this.AD_UserDef_Win_ID = AD_UserDef_Win_ID;
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof WindowCacheKey)) return false;
      WindowCacheKey key = (WindowCacheKey) obj;
      return super.equals(obj) && AD_UserDef_Win_ID == key.AD_UserDef_Win_ID;
    }

    @Override
    public int hashCode() {
      return toString().hashCode();
    }

    @Override
    public String toString() {
      return super.toString() + AD_UserDef_Win_ID;
    }

    int AD_UserDef_Win_ID;
  }

  private static class WindowVOCacheKey {

    WindowVOCacheKey(int AD_Window_ID, int AD_Role_ID, int AD_Menu_ID, String AD_Language) {
      this.AD_Window_ID = AD_Window_ID;
      this.AD_Role_ID = AD_Role_ID;
      this.AD_Menu_ID = AD_Menu_ID;
      this.AD_Language = AD_Language;
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof WindowVOCacheKey)) return false;
      WindowVOCacheKey key = (WindowVOCacheKey) obj;
      return AD_Window_ID == key.AD_Window_ID
          // && AD_UserDef_Win_ID == key.AD_UserDef_Win_ID
          && AD_Role_ID == key.AD_Role_ID
          && AD_Menu_ID == key.AD_Menu_ID
          && AD_Language.equals(key.AD_Language);
    }

    @Override
    public int hashCode() {
      return toString().hashCode();
    }

    @Override
    public String toString() {
      return AD_Language + AD_Window_ID + AD_Role_ID + AD_Menu_ID;
    }

    int AD_Window_ID;

    int AD_Role_ID;

    int AD_Menu_ID;

    String AD_Language;
  }

  private static class ScoreStrategy implements Comparator<ScoreCell> {

    // TODO: populate from locale to strip out the/a/and etc...
    private String[] terms;

    private String query;

    public ScoreStrategy(String queryString) {
      HashSet<String> unique = new HashSet<String>();
      this.query = queryString.trim().toLowerCase();
      for (String term : this.query.split("\\s+")) {
        if (!unique.contains(term)) {
          unique.add(term);
        }
      }
      this.terms = new String[unique.size()];
      int i = 0;
      for (String term : unique) {
        this.terms[i++] = term;
      }
    }

    public Score createScore() {
      Score score = new Score();
      score.terms = new int[terms.length];
      return score;
    }

    public void getScore(String value3, Score score) {
      if (value3 == null || value3.trim().equals("")) return;
      String value2 = value3.toLowerCase();
      if (query.equals(value2)) {
        score.equalsMatches++;
        score.isMatch = true;
        return;
      }
      try {
        int occurrences = value2.length() - value2.replaceAll(query, "").length();
        if (occurrences > 0) {
          score.completeMatches += occurrences;
          score.isMatch = true;
        }
        if (terms.length > 1) {
          int termNo = 0;
          for (String term : terms) {
            int count = value2.length() - value2.replaceAll(term, "").length();
            if (count > 0) {
              score.terms[termNo++] += count;
              score.isMatch = true;
            }
          }
        }
      } catch (PatternSyntaxException pse) {
        // assume no match on pattern syntax error
      }
    }

    public int compare(ScoreCell o1, ScoreCell o2) {
      Score s1 = o1.score;
      Score s2 = o2.score;
      int difference = 0;
      if ((difference = s2.equalsMatches - s1.equalsMatches) != 0) {
        return difference;
      }
      if ((difference = s2.completeMatches - s1.completeMatches) != 0) {
        return difference;
      }
      int total1 = 0;
      int total2 = 0;
      int terms1 = 0;
      int terms2 = 0;
      // otherwise check if both terms are matched and tabulate total
      for (int score : s1.terms) {
        if (score > 0) {
          total1 += score;
          terms1++;
        }
      }
      for (int score : s2.terms) {
        if (score > 0) {
          total2 += score;
          terms2++;
        }
      }
      if ((difference = terms2 - terms1) != 0) {
        return difference;
      } else {
        return total2 - total1;
      }
    }
  }

  private static class ScoreCell {

    String[] row;

    Score score;
  }

  private static class Score {

    public int completeMatches = 0;

    public int equalsMatches = 0;

    public int[] terms;

    public boolean isMatch = false;
  }

  public int searchTabResults(
      int WindowNo,
      int AD_Tab_ID,
      int queryResultID,
      int searchResultID,
      String query,
      int rowCount) {
    UITab tab = getTab(AD_Tab_ID);
    ArrayList<Integer> ids = new ArrayList<Integer>();
    for (UIField field : tab.getFields()) {
      if (field.isSelectionColumn()
          || field.isIdentifier() && FieldType.isText(field.getAD_Reference_ID())) {
        ids.add(field.getAD_Field_ID());
      }
    }
    return searchTabResults(WindowNo, tab, ids, queryResultID, searchResultID, query, rowCount);
  }

  public NodeVO getNode(String key) {
    return m_nodes.get(key);
  }

  public void putNode(String key, NodeVO node) {
    m_nodes.put(key, node);
  }
} // GwtServer