/**
 * Copyright (c) 2003-2004 System Integrator Corporation.
 *                 All Rights Reserved.
 */
package jp.co.sint.database;

import java.util.Collection;

import jp.co.sint.config.SIConfig;
import jp.co.sint.config.SIDBMultiConf;
import jp.co.sint.tools.SIUtil;

import org.apache.log4j.Category;
import org.apache.log4j.Logger;

public class SITableCondition {

  //ログ用のインスタンスの生成
  private static Category log=Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  //条件の前に、アリアス名をつける
  private String tableName="";
  //条件の項目名
  private String itemName="";
  //項目に対するデータ
  private Object itemValue;
  //Default の比較のタイプは、"="です ex. name=data
  private int compareType=SIConfig.SICONDITION_TYPE_EQUAL;
  //条件の文字列
  private String compareTypeName=SIConfig.SICONDITION_TYPE_COMPARE_NAME[compareType];
  //条件の結合のタイプ(default:なし) ex. item=data
  private int andOrType=SIConfig.SICONDITION_TYPE_NOT;
  //連結の条件の文字列
  private String andOrTypeName=SIConfig.SICONDITION_TYPE_NAME[andOrType];
  //値がnullの場合に、出力するかどうかフラグ. ex. item is null
  private boolean blankEnable=false;

  private String freeWord = "";
  
  //ログインスタンス
  private Logger logger=Logger.getLogger(SITableCondition.class.getName());

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  なし
   * @return なし
   * @throws なし
   */
  public SITableCondition() {
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lFreeWord){
    this();
    this.freeWord=lFreeWord;
  }
  
  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lItemName,Object lItemValue){
    this();
    this.itemName=lItemName;
    this.itemValue=lItemValue;
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue){
    this(lItemName,lItemValue);
    this.tableName=lTableName;
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  lCompareType 条件のタイプ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,int lCompareType){
    this(lTableName,lItemName,lItemValue);
    this.compareType=lCompareType;
    this.compareTypeName =SIConfig.SICONDITION_TYPE_COMPARE_NAME[this.compareType];
  }

  /**
   * <b>lCompareType</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  compareType 条件のタイプ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,String lCompareTypeName){
    this(lTableName,lItemName,lItemValue);
    this.compareTypeName =lCompareTypeName;
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  compareType 条件のタイプ
   * @param  andOrType   連結のタイプ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,int lCompareType,int lAndOrType){
    this(lTableName,lItemName,lItemValue,lCompareType);
    this.andOrType =lAndOrType;
    this.andOrTypeName=SIConfig.SICONDITION_TYPE_NAME[this.andOrType];
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  lCompareTypeName 条件のタイプ名
   * @param  lAndOrType   連結のタイプ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,String lCompareTypeName,int lAndOrType){
    this(lTableName,lItemName,lItemValue,lCompareTypeName);
    this.andOrType =lAndOrType;
    this.andOrTypeName=SIConfig.SICONDITION_TYPE_NAME[this.andOrType];
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  lCompareTypeName 条件のタイプ名
   * @param  lAndOrType   連結のタイプ
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,String lCompareTypeName,String lAndOrTypeName){
    this(lTableName,lItemName,lItemValue,lCompareTypeName);
    this.andOrTypeName=lAndOrTypeName;
  }

  /**
   * <b>SITableCondition</b>
   * コンストラクタ
   * @param  lTableName テーブル名
   * @param  lItemName  項目名
   * @param  lItemValue 上記の項目名に対するデータ
   * @param  lCompareType 条件のタイプ
   * @param  lAndOrType   連結のタイプの名
   * @return なし
   * @throws なし
   */
  public SITableCondition(String lTableName,String lItemName,Object lItemValue,int lCompareType,String lAndOrTypeName){
    this(lTableName,lItemName,lItemValue,lCompareType);
    this.andOrTypeName=lAndOrTypeName;
  }

  /**
   * <b>setBlankEnable</b>
   * 項目のデータが空データの場合には、条件の文を出力するかどうかフラグを設定します。
   * @param  lBlankEnable フラグ
   * @return なし
   * @throws なし
   */
  public void setBlankEnable(boolean lBlankEnable){
    this.blankEnable=lBlankEnable;
  }

  /**
   * <b>setTableName</b>
   * テーブル名を設定します。
   * @param  lTableName テーブル名
   * @return なし
   * @throws なし
   */
  public void setTableName(String lTableName){
    this.tableName =lTableName;
  }

  /**
   * <b>setItemName</b>
   * 検索項目名を設定します。
   * @param  lItemName 項目名
   * @return なし
   * @throws なし
   */
  public void setItemName(String lItemName){
    this.itemName =lItemName;
  }

  /**
   * <b>setItemValue</b>
   * 検索項目のデータを設定します。
   * @param  lItemValue 検索項目のデータ
   * @return なし
   * @throws なし
   */
  public void setItemValue(Object lItemValue){
    this.itemValue=lItemValue;
  }

  /**
   * <b>setCompareType</b>
   * 条件のタイプを設定します。
   * @param  lCompareType 条件のタイプ
   * @return なし
   * @throws なし
   */
  public void setCompareType(int lCompareType){
    this.compareType=lCompareType;
    this.compareTypeName =SIConfig.SICONDITION_TYPE_COMPARE_NAME[this.compareType];
  }

  /**
   * <b>setCompareTypeName</b>
   * 条件のタイプを設定します。
   * @param  lCompareTypeName 条件のタイプ名
   * @return なし
   * @throws なし
   */
  public void setCompareTypeName(String lCompareTypeName){
    this.compareTypeName =lCompareTypeName;
  }

  /**
   * <b>setAndOrType</b>
   * 連結条件のタイプを設定します。
   * @param  lAndOrType 連結条件のタイプ
   * @return なし
   * @throws なし
   */
  public void setAndOrType(int lAndOrType){
    this.andOrType=lAndOrType;
    this.andOrTypeName=SIConfig.SICONDITION_TYPE_NAME[this.andOrType];
  }

  /**
   * <b>setAndOrTypeName</b>
   * 連結条件のタイプ名を設定します。
   * @param  lAndOrType 連結条件のタイプ名
   * @return なし
   * @throws なし
   */
  public void setAndOrTypeName(String lAndOrTypeName){
    this.andOrTypeName=lAndOrTypeName;
  }

  /**
   * <b>getTableName</b>
   * テーブル名を取得します。
   * @param  なし
   * @return テーブル名
   * @throws なし
   */
  public String getTableName(){
    return this.tableName;
  }

  /**
   * <b>getItemName</b>
   * 検索項目の名を取得します。
   * @param  なし
   * @return 検索の項目名
   * @throws なし
   */
  public String getItemName(){
    return this.itemName;
  }

  /**
   * <b>getItemValue</b>
   * 検索項目に対するデータを取得します。
   * @param  なし
   * @return 検索項目のデータ
   * @throws なし
   */
  public Object getItemValue(){
    return this.itemValue;
  }

  /**
   * <b>getCompareType</b>
   * 条件のタイプを取得します。
   * @param  なし
   * @return 条件のタイプ
   * @throws なし
   */
  public int getCompareType(){
    return this.compareType;
  }

  /**
   * <b>getBlankEnable</b>
   * nullのデータを出力するかどうかフラグを取得します。
   * @param  なし
   * @return nullのデータを出力するかどうかフラグ
   * @throws なし
   */
  public boolean getBlankEnable(){
    return this.blankEnable;
  }

  /**
   * <b>getCondition</b>
   * 連結条件のタイプを設定します。
   * @param  なし
   * @return 条件の文を構成して出力します。
   * @throws なし
   */
  public String getCondition(){

    StringBuffer resultBuf=new StringBuffer();
    String middleRes="";

    logger.debug("getCondition:itemName="+itemName+",andOrType="+andOrType+",andOrTypeName="+andOrTypeName+",compareType="+compareType+",compareTypeName="+compareTypeName+",freeWord="+freeWord);
    if(SIUtil.isNotNull(freeWord)){
		resultBuf.append(freeWord);
		return resultBuf.toString();
    }
    if (itemValue==null) logger.debug("getCondition:itemValue is null");
    else logger.debug("getCondition:itemValue="+itemValue.toString());

    if (SIUtil.isNull(itemName)) return "";
    
    if(compareType != 7 && compareType != 8){
		if (itemValue==null && !blankEnable) return "";
		if (itemValue instanceof String && SIUtil.isNull((String)itemValue) && !blankEnable)return "";    	
    }


    if (SIUtil.isNotNull(andOrTypeName))resultBuf.append(andOrTypeName);
    else resultBuf.append(" ");

    if (SIUtil.isNotNull(tableName))resultBuf.append(tableName+".");

    if (SIUtil.isNull(compareTypeName)) return "";
    else if (compareTypeName.trim().equalsIgnoreCase(SIConfig.SICONDITION_TYPE_COMPARE_NAME[SIConfig.SICONDITION_TYPE_LIKE].trim())){
      if (itemValue instanceof String){
        resultBuf.append(itemName);
        if (SIDBMultiConf.SIDB_CURRENT_INX ==SIDBMultiConf.SIDB_POSTGRESQL_INX){
          resultBuf.append(" LIKE '%"+SIDBUtil.SQL2Like(((String)itemValue).trim())+"%' ");
        }else{//オラクルの場合には、特別の文字の対応
          String lEsc="";
          String lValue=(String)itemValue;
          if (lValue.indexOf("%")!=-1||lValue.indexOf("_")!=-1 || lValue.indexOf("\\")!=-1){//7.4.0 ST2083 修正
            lEsc="ESCAPE '\\' ";
          }
          resultBuf.append(" LIKE '%"+SIDBUtil.SQL2Like(((String)itemValue).trim())+"%' ").append(lEsc);
        }
      }else return "";
    }else if (compareTypeName.trim().equalsIgnoreCase(SIConfig.SICONDITION_TYPE_COMPARE_NAME[SIConfig.SICONDITION_TYPE_FRONTLIKE].trim())){
      if (itemValue instanceof String){
        resultBuf.append(itemName);
        if (SIDBMultiConf.SIDB_CURRENT_INX ==SIDBMultiConf.SIDB_POSTGRESQL_INX){
          resultBuf.append(" LIKE '"+SIDBUtil.SQL2Like(((String)itemValue).trim())+"%' ");
        }else{//オラクルの場合には、特別の文字の対応
          String lEsc="";
          String lValue=(String)itemValue;
          if (lValue.indexOf("%")!=-1||lValue.indexOf("_")!=-1 || lValue.indexOf("\\")!=-1){//7.4.0 ST2083 修正
            lEsc="ESCAPE '\\' ";
          }
          resultBuf.append(" LIKE '"+SIDBUtil.SQL2Like(((String)itemValue).trim())+"%' ").append(lEsc);
        }
      }else return "";
    }else if(compareTypeName.trim().equalsIgnoreCase(SIConfig.SICONDITION_TYPE_COMPARE_NAME[SIConfig.SICONDITION_TYPE_IS_NULL].trim())
    		||compareTypeName.trim().equalsIgnoreCase(SIConfig.SICONDITION_TYPE_COMPARE_NAME[SIConfig.SICONDITION_TYPE_IS_NOT_NULL].trim())){
          resultBuf.append(itemName);
          resultBuf.append(compareTypeName);
    }else {
      if (itemValue==null){return itemName+" IS NULL ";}
      else if (itemValue instanceof String){
        resultBuf.append(itemName);
        if (((String)itemValue).trim().length()==0 && blankEnable)resultBuf.append(" IS NULL ");
        else if (((String)itemValue).trim().length()==0 ) return "";
        else resultBuf.append(compareTypeName+"'"+SIDBUtil.sqlEncode(((String)itemValue).trim()) +"' ");
      }else if (itemValue instanceof Integer){
        resultBuf.append(itemName);
        resultBuf.append(compareTypeName+((Integer)itemValue).intValue()+" ");
      }else if (itemValue instanceof Long){
        resultBuf.append(itemName);
        resultBuf.append(compareTypeName+((Long)itemValue).longValue()+" ");
      }else if (itemValue instanceof Float){
        resultBuf.append(itemName);
        resultBuf.append(compareTypeName+((Float)itemValue).floatValue()+" ");
      }else if (itemValue instanceof Collection){
        middleRes=SIDBUtil.getCondition((Collection)itemValue);
        if (SIUtil.isNull(middleRes)) return "";
        resultBuf.append(" ("+middleRes+") ");
      }else if (itemValue instanceof SISpcType){
				resultBuf.append(itemName);
				resultBuf.append(compareTypeName+((SISpcType)itemValue).toValue()+" ");
      }else return "";
    }
    return resultBuf.toString();
  }
}