package org.itscool.commons.dao;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import org.itscool.commons.bean.BeanUtil;
import org.itscool.commons.bean.BeanUtilRuntimeException;
import org.itscool.commons.util.StringUtil;

/**
 * <p>
 * POJO-SQLマッピングクラス
 * </p>
 *
 * RecordMapインスタンスを使ってテーブル操作に必要なクエリを作成するクラスです <BR>
 * 永続化対象となるJavaBeansのクラス情報を元にテーブルマッピングクラス(RecordMap)
 * インスタンスを生成します <BR>
 * JavaBeansクラスには、永続化対象となるプロパティとそのアクセッサメソッド(getter/setter)
 * を定義しておく必要があります <BR>
 * 又、クラス名とテーブルのマッピング情報とプロパティとフィールドのマッピング情報を
 * JavaBeansに定義しなければなりません。 <BR>
 * テーブルのマッピング情報はpublic static final String TABLE="物理テーブル名"で 定義します。 <BR>
 * TABLE定数が未定義の場合は、JavaBeansのクラス名がテーブル名とマッピングされます <BR>
 * プロパティとフィールドのマッピング情報はpublic static final String CULM_プロパティ名="フィールド名" で定義します
 * <BR>
 * フィールド定数が未定義の場合は、プロパティとフィールドのマッピングは行われません。
 * <P>
 * <PRE>
 * JavaBeansの作成例
 * -----------------
 *
 * public class Customer {
 *    //CustomerクラスとCUSTOMERテーブルのマッピング情報を定義します。
 *    //TABEL="テーブル名"でこのクラスに対応するテーブル名を定義しています
 *    //COLUM_メンバ名="フィールド名"でCustomerクラスの各メンバに対応するフィールド名を定義しています<BR>
 *    public static final String TABLE = "CUSTOMER";
 *    public static final String PK_COLUM_id = "id";
 *    public static final String COLUM_name = "name";
 *    public static final String COLUM_companyId = "company_id";
 *    public static final String COLUM_postId = "post_id";
 *
 *    //1対1関連 1対1関連を定義する場合は以下のように記述します。
 *    //FK_TABLE_オブジェクト名="テーブル名"
 *    //外部参照先のテーブル名を定義しています。
 *    //オブジェクト名は、外部参照先テーブルに対応するJavaBeansクラスを定義します。
 *    //このオブジェクト名に対応するオブジェクトの宣言が、このクラスに定義されている必要があります。
 *    //
 *    //例えば、外部参照先テーブル"POST"の宣言は以下のようになります。
 *    //
 *    //public static final String FK_TABLE_post = "POST";
 *    //
 *    //又、この外部参照先テーブルに対応するオブジェクトの宣言を以下のように定義しなければなりません。
 *    //
 *    //private Post post; //Postクラスにテーブルマッピング情報が定義されているものとします
 *    //
 *    //FK_COLUM_オブジェクト名_メンバ名="フィールド名"
 *    //オブジェクト名_メンバ名はこのクラスで定義された外部参照オブジェクトと
 *    //外部参照キーをあらわすプロパティ名を宣言します。
 *    //"フィールド名"には外部参照テーブルの参照先フィールド名を指定します。
 *    //
 *    //例えばPostクラスのpostオブジェクトの参照キーがpostIdの場合、以下のように定義します
 *    //
 *    //public static final String FK_COLUM_post_postId = "id";
 *    //
 *    public static final String FK_TABLE_post = "POST"; 			//外部参照テーブル情報
 *    public static final String FK_COLUM_post_postId = "id";		//外部参照キーと関連フィールドの指定
 *
 *    public static final String FK_TABLE_company = "COMPANY"; 		//外部参照テーブル情報
 *    public static final String FK_COLUM_company_companyId = "id";	//外部参照キーと関連フィールドの指定
 *
 *    private int id;
 *    private String name;
 *    private int companyId;
 *    private int
 *    postId;
 *
 *    private Post post; private Company company;
 *
 *   // ・・・以下、上記メンバのアクセッサメソッドを定義してください
 * }
 *
 *
 * Criteriaを使用したデータアクセスクラスの実装例
 * --------------------------------------------
 *
 * public class CustomerDao extends BaseDao{
 *    public CustomerDao(Transaction trn){
 *        super(trn);
 *    }
 *
 *    public List getCustomerAll(){
 *        Criteria crt = new Criteria(Customer.class);
 *        System.out.println(crt.toString());
 *        System.out.println(crt.toSelectString());
 *        List lst = select(crt);
 *        return lst;
 *    }
 *
 *    //テストメソッド
 *    public static void main(String[] argv){
 *       //･･･（前略)･･･
 *       //Connectionインスタンスを取得
 *       Connection con = ds.getConnection();
 *       Transaction trn = new Transaction(con);
 *       CustomerDao dao = new CustomerDao(trn);
 *       List customers = dao.getCustomerAll();
 *       for(int i=0; i<customers.size(); i++){
 *           Customer customer = (Customer)customers.get(i);
 *           String postName = "(null)";
 *           String companyName = "(null)";
 *           Post post = customer.getPost();
 *           Company company = customer.getCompany();
 *           if( post != null )postName = post.getName();
 *           if( company != null )companyName = company.getName();
 *
 *           System.out.print("ID[" + customer.getId() + "] NAME["+ customer.getName() + "] ");
 *           System.out.println("POST[" + postName + "] COMPANY["+ companyName + "] ");
 *       }
 *   }
 * </PRE>
 *
 * @author KANO
 * @since jdk1.4.1
 * @version 1.00A 2004/11/1
 */
public class Criteria{
    protected Class entity;
    
    /**
     * 改行コード
     */
    protected static final String line
            = System.getProperty("line.separator");
    
    /**
     * タブコード
     */
    protected static final String tab = "    ";
    
    /**
     * 基本となるRecordMapインスタンス
     */
    protected RecordMap gRecordMap;
    
    /**
     * WHERE句リスト
     */
    protected LinkedList whereList;
    
    /**
     * ORDER BY句リスト
     */
    protected LinkedList orderByList;
    
    /**
     * GROUP BY句リスト
     */
    protected LinkedList groupByList;
    
    /**
     * 外部参照（Forigne Keyで指定したフィールド情報）テーブルのリスト
     */
    protected HashMap fkRecordMaps;
    
    private HashMap oneToManyRecordMaps;
    private boolean oneToMany = false;
    
    /**
     * LIMIT 句
     */
    protected String limit = null;
    
    /**
     * LIMIT句のセット
     * @param startRow 取得開始行(1から)
     * @param row 取得行数
     */
    public void setLimit(int startRow, int row){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        String dbType = mapping.getDbType();
        if( startRow > 0 ){
            startRow --;
        }
        if( dbType.equals(EntityInfoMapping.DB_HSQL) ){
            limit = "LIMIT " + startRow + " " + row;
        }else{
            limit = "LIMIT " + startRow + ", " + row;
        }
    }
    
    /**
     * LIMIT句の取得
     */
    public String getLimit(){
        return limit;
    }
    
    /**
     * Criteriaインスタンスの初期化<BR>
     * entityビーンクラスに定義されているTABEL、COLUM_メンバ名情報を解析し、
     * entityビーンに対応するRecordMapインスタンスを作成します。<BR>
     * @param entity 永続化対象となるJavaBeansのクラス情報
     */
    public Criteria(Class entity){
        this.entity = entity;
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        gRecordMap = mapping.getGRecordMap(entity);
        fkRecordMaps = mapping.getFkRecordMaps(entity);
        setOneToManyRecordMaps(mapping.getOneToManyRecordMaps(entity));
        if( getOneToManyRecordMaps().size() > 0 ){
            this.setOneToMany(true);
        }
        //EntityInfoMapping内部で生成するため、不要
//        if(gRecordMap==null){
//            this.gRecordMap = RecordMapFactory.createRecordMap(entity);
//        }
//        if(fkRecordMaps==null){
//            //外部参照用RecordMapインスタンスの配列を作成
//            this.fkRecordMaps = RecordMapFkFactory.createFkRecordMaps(entity);
//        }
        
        this.orderByList = new LinkedList();
        this.groupByList = new LinkedList();
        this.whereList = new LinkedList();
    }
    
    /**
     * JavaBeansのプロパティ名からカラム名を取得します
     * プロパティ名が"."で区切られている場合は、外部参照先オブジェクトの
     * プロパティとみなします。
     * @param propertyName プロパティ名
     * @return String このプロパティに対応するカラム名
     */
    public String getColumName(String propertyName){
        int index = propertyName.indexOf(".");
        String columName;
        if( index > 0 ){
            String fkObjectName = propertyName.substring(0, index);
            String fkPropertyName = propertyName.substring(index+1, propertyName.length());

            columName = cnvFkColumName(fkObjectName, fkPropertyName);
        }else{
            columName = cnvColumName(propertyName);
        }
        //対応するカラム名が存在しない場合
        if( columName == null ){
            columName = StringUtil.cnvUpperNameToUnderScoreName(propertyName);
        }
        return columName;
    }
    
    /**
     * JavaBeansのプロパティ名からカラム名を取得します
     * @param propertyName プロパティ名１
     * @return String このプロパティに対応するカラム名
     */
    protected String cnvColumName(String propertyName){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        RecordMap recordMap = mapping.getGRecordMap(entity.getName());
        if( recordMap == null) return null;
        FieldMap fieldMap = recordMap.getFieldByPropertyName(propertyName);
        if( fieldMap == null ) return null;
        String columWithTableName =fieldMap.getColumWithTableName();
        return columWithTableName;
    }
    
    /**
     * JavaBeansの外部参照クラスのプロパティ名からカラム名を取得します
     * @param fkObjectName このJavaBeansに定義された外部参照テーブルのオブジェクト名
     * @param propertyName 外部参照オブジェクトのプロパティ名
     * @return String このプロパティに対応するカラム名
     */
    protected String cnvFkColumName(String fkObjectName, String fkPropertyName){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        RecordMap fkRecordMap = mapping.getFkRecordMap(entity.getName(), fkObjectName );
        if( fkRecordMap == null) return null;
        FieldMap fkFieldMap = fkRecordMap.getFieldByPropertyName(fkPropertyName);
        if( fkFieldMap == null ) return null;
        String fkColumName = fkFieldMap.getColumWithTableName();
        return fkColumName;
    }
    
    /**
     * 基本となるRecordMapインスタンスを取得します
     * @return RecordMapインスタンス
     */
    public RecordMap getRecord(){
        return gRecordMap;
    }
    
    /**
     * 指定されたRecordMapインスタンスの列リスト句を作成します
     * @param record RecordMapインスタンス
     * @return 指定されたRecordMapインスタンスの列リスト句を返します
     */
    protected String getColNames(RecordMap record){
        StringBuffer sb = new StringBuffer(line);
        HashMap fields = record.getFields();
        Set keySet = fields.keySet();
        Iterator it = keySet.iterator();
        while( it.hasNext() ){
            Object key = it.next();
            FieldMap item = (FieldMap)fields.get(key);
            String colWithTableName = item.getColumWithTableName();
            String colAsName = item.getColumAsName();
            sb.append( tab );
            sb.append( colWithTableName );
            sb.append(" as ");
            sb.append( colAsName );
            if( it.hasNext() ){
                sb.append(",");
                sb.append( line );
            }
        }
        return sb.toString();
    }
    
    /**
     * 関連テーブルの列リスト句を作成します
     * @param records RecordMapインスタンス
     * @return 関連テーブルの列リスト句を返します
     */
    protected String getColNamesByTable(HashMap records){
        StringBuffer sb = new StringBuffer();
        Set keySet = records.keySet();
        Iterator it = keySet.iterator();
        
        while( it.hasNext() ){
            Object key = it.next();
            RecordMap recordMap = (RecordMap)records.get(key);
            
            sb.append(getColNames(recordMap));
        }
        return sb.toString();
    }
    
    /**
     * 関連テーブル名のリストを返します
     * @param records RecordMapインスタンス
     * @return 関連テーブル名のリストを返します
     */
    protected String getTableNames(HashMap records){
        StringBuffer sb = new StringBuffer();
        Set keySet = records.keySet();
        Iterator it = keySet.iterator();
        
        while( it.hasNext() ){
            Object key = it.next();
            RecordMap recordMap = (RecordMap)records.get(key);
            
            sb.append(recordMap.getTableName());
            if(it.hasNext()){
                sb.append(",");
            }
        }
        return sb.toString();
    }
    
    /**
     * Criteria構成情報を取得します
     * @return Criteria構成情報
     */
    public String toString(){
        StringBuffer sb = new StringBuffer();
        sb.append(gRecordMap.toString());
        sb.append(line);
        Set keySet = fkRecordMaps.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()){
            String key = (String)it.next();
            RecordMap recordMap = (RecordMap)fkRecordMaps.get(key);
            sb.append("FK_KEY[").append(key).append("] ").append(recordMap.toString());
            sb.append(line);
        }
        return sb.toString();
    }
    
    /**
     * SELECT句を作成します<BR>
     * [select [cols] from [table] where [name]=[value] [and|or] ･･･]
     * 形式のSQLを構築します
     * @return SELECTステートメントを返します
     */
    public String toSelectString(){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        String dbType = mapping.getDbType();
        
        StringBuffer sql = new StringBuffer("SELECT");
        
        //LIMIT句（HSQL）
        if( dbType.equals(EntityInfoMapping.DB_HSQL) && limit != null ){
            sql.append(line+tab);
            sql.append(limit);
        }
        
        //列集合の作成
        sql.append(getColNames(gRecordMap));
        //外部参照テーブルのフィールドを取得
        sql.append(getFkSelectString());
        if(isOneToMany()){
            sql.append(getOneToManySelectString());
        }
        
        //単純結合テーブルのチェック
        sql.append(line);
        sql.append("FROM");
        sql.append(line + tab).append(gRecordMap.getTableName());
        
        //外部参照テーブルを取得
        sql.append(getFkTableString());
        if(isOneToMany()){
            //ONE TO MANY
            sql.append(getOneToManyTableString());
        }
        //Where句の作成
        FieldMap deleteFg = gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG);
        if( whereList.size() > 0 || fkRecordMaps.size() > 0 ||  deleteFg != null ||
            (getOneToManyRecordMaps().size() > 0 && isOneToMany())){
            sql.append(line);
            sql.append("WHERE").append(line + tab);
        }
        
        sql.append(getWhereString());
        
        //論理削除フィールドが存在する場合
        //論理削除ﾚｺｰﾄﾞを除外
        if( deleteFg != null ){
            if( whereList.size() > 0 ){
                sql.append(line + tab);
                sql.append("AND ");
            } 
            sql.append(deleteFg.getColumWithTableName());
            sql.append(" != 1 ");
        }
        
        //外部参照フィールドを取得
        sql.append(getFkWhereString());
        if(isOneToMany()){
            sql.append(getOneToManyWhereString());
        }
        //Group By句の作成
        if( groupByList.size() > 0 ){
            sql.append(line);
            sql.append("GROUP BY");
            sql.append(getGroupByString());
        }
        
        //Order By句の作成
        if( orderByList.size() > 0 ){
            sql.append(line);
            sql.append("ORDER BY");
            sql.append(getOrderByString());
        }
        
        //LIMIT句（HSQL以外）
        if( !dbType.equals(EntityInfoMapping.DB_HSQL) && limit != null ){
            sql.append(line+tab);
            sql.append(limit);
        }
        return sql.toString();
    }
    
    /**
     * SELECT COUNT 句を作成します<BR>
     * [select [cols] from [table] where [name]=[value] [and|or] ･･･]
     * 形式のSQLを構築します
     * @return SELECTステートメントを返します
     */
    public String toCountString(){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        String dbType = mapping.getDbType();
        
        StringBuffer sql = new StringBuffer("SELECT");
        
        sql.append(" COUNT(*) AS DATA_NUM");
        
        //単純結合テーブルのチェック
        sql.append(line);
        sql.append("FROM");
        sql.append(line + tab).append(gRecordMap.getTableName());
        
        //外部参照テーブルを取得
        sql.append(getFkTableString());
        
        //Where句の作成
        FieldMap deleteFg = gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG);
        if( whereList.size() > 0 || fkRecordMaps.size() > 0 || deleteFg != null){
            sql.append(line);
            sql.append("WHERE").append(line + tab);
        }
        
        sql.append(getWhereString());
        
        //論理削除フィールドが存在する場合
        //論理削除ﾚｺｰﾄﾞを除外
        if( deleteFg != null ){
            if( whereList.size() > 0 ){
                sql.append(line + tab);
                sql.append("AND ");
            } 
            sql.append(deleteFg.getColumWithTableName());
            sql.append(" != 1 ");
        }
        
        //外部参照フィールドを取得
        sql.append(getFkWhereString());
        
        //Group By句の作成
        if( groupByList.size() > 0 ){
            sql.append(line);
            sql.append("GROUP BY");
            sql.append(getGroupByString());
        }
        
        return sql.toString();
    }
    
    /**
     * 外部参照用RecordMapインスタンスからSELECT句を取得します
     * @param sql SELECT句を返します
     */
    private String getFkSelectString() {
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = fkRecordMaps.keySet();
        Iterator it = keySet.iterator();
        if( it.hasNext() ){
            sql.append(",");
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap fkRecordMap = (RecordMap)fkRecordMaps.get(key);
            //外部参照情報で取得したクラスのRecordMapインスタンスを作成
            sql.append(getColNames(fkRecordMap));
            if( it.hasNext() ){
                sql.append(",");
            }
        }
        return sql.toString();
    }
    
    private String getOneToManySelectString() {
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = getOneToManyRecordMaps().keySet();
        Iterator it = keySet.iterator();
        if( it.hasNext() ){
            sql.append(",");
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap oneToManyRecordMap = (RecordMap)getOneToManyRecordMaps().get(key);
            //外部参照情報で取得したクラスのRecordMapインスタンスを作成
            sql.append(getColNames(oneToManyRecordMap));
            if( it.hasNext() ){
                sql.append(",");
            }
        }
        return sql.toString();
    }
    
    /**
     * 外部参照用RecordMapインスタンスから結合時のテーブル名を取得します
     * @param sql テーブル名を返します
     */
    private String getFkTableString() {
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = fkRecordMaps.keySet();
        Iterator it = keySet.iterator();
        if( it.hasNext() ){
            sql.append(",");
            sql.append(line + tab);
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap fkRecordMap = (RecordMap)fkRecordMaps.get(key);
            //外部参照情報で取得したクラスのRecordMapインスタンスを作成
            String fkTableName = fkRecordMap.getTableName();
            sql.append(fkTableName);
            if( it.hasNext() ){
                sql.append(",");
                sql.append(line + tab);
            }
        }
        return sql.toString();
    }
    
    private String getOneToManyTableString() {
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = getOneToManyRecordMaps().keySet();
        Iterator it = keySet.iterator();
        if( it.hasNext() ){
            sql.append(",");
            sql.append(line + tab);
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap oneToManyRecordMap = (RecordMap)getOneToManyRecordMaps().get(key);
            //外部参照情報で取得したクラスのRecordMapインスタンスを作成
            String fkTableName = oneToManyRecordMap.getTableName();
            sql.append(fkTableName);
            if( it.hasNext() ){
                sql.append(",");
                sql.append(line + tab);
            }
        }
        return sql.toString();
    }
    
    /**
     * 外部参照用RecordMapインスタンスからWHERE句を取得します
     * @param sql WHERE句を返します
     */
    private String getFkWhereString(){
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = fkRecordMaps.keySet();
        Iterator it = keySet.iterator();
        
        if( it.hasNext() && 
            ( whereList.size() > 0 || gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG) != null) ){
            sql.append(line + tab);
            sql.append("AND ");
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap fkRecordMap = (RecordMap)fkRecordMaps.get(key);
            //外部参照情報にセットされているテーブル名を追加
            Set fieldKeySet = fkRecordMap.getFields().keySet();
            Iterator fieldIt = fieldKeySet.iterator();
            
            while(fieldIt.hasNext()){
                String fieldKey = (String)fieldIt.next();
                FieldMap fieldMap = (FieldMap)fkRecordMap.getField(fieldKey);
                if(!fieldMap.isForignKey()){
                    continue;
                }
                String propertyName = fieldMap.getPropertyName();
                String columWithTableName = fieldMap.getColumWithTableName();
                String fkPropertyName = fieldMap.getFkPropertyName();
                sql.append(columWithTableName);
                sql.append(" = ");
                sql.append(getFkFieldName(fkPropertyName));
                if( it.hasNext() ){
                    sql.append(line + tab);
                    sql.append("AND ");
                }
            }
        }
        return sql.toString();
    }
    
    private String getOneToManyWhereString(){
        StringBuffer sql = new StringBuffer();
        //外部参照テーブルのフィールドを取得
        Set keySet = getOneToManyRecordMaps().keySet();
        Iterator it = keySet.iterator();
        
        if( it.hasNext() && 
            ( whereList.size() > 0 || gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG) != null) ){
            sql.append(line + tab);
            sql.append("AND ");
        }
        while(it.hasNext()){
            String key = (String)it.next();
            //外部参照情報を取得
            RecordMap oneToManyRecordMap = (RecordMap)getOneToManyRecordMaps().get(key);
            //外部参照情報にセットされているテーブル名を追加
            Set fieldKeySet = oneToManyRecordMap.getFields().keySet();
            Iterator fieldIt = fieldKeySet.iterator();
            
            while(fieldIt.hasNext()){
                String fieldKey = (String)fieldIt.next();
                FieldMap fieldMap = (FieldMap)oneToManyRecordMap.getField(fieldKey);
                if(!fieldMap.isForignKey()){
                    continue;
                }
                String propertyName = fieldMap.getPropertyName();
                String columWithTableName = fieldMap.getColumWithTableName();
                String oneToManyPropertyName = fieldMap.getFkPropertyName();
                sql.append(columWithTableName);
                sql.append(" = ");
                //sql.append(getFkFieldName(oneToManyPropertyName));
                FieldMap current = gRecordMap.getFieldByPropertyName(oneToManyPropertyName);
                sql.append(current.getColumWithTableName());
                
                if( it.hasNext() ){
                    sql.append(line + tab);
                    sql.append("AND ");
                }
            }
        }
        return sql.toString();
    }
    
    /**
     * 外部参照用RecordMapインスタンスからWHERE句に指定するフィールド名
     * を取得します
     * @param propertyName 外部参照先のプロパティ名
     * @param sql フィールド名を返します
     */
    private String getFkFieldName(String propertyName){
        HashMap fields = gRecordMap.getFields();
        Set keySet = fields.keySet();
        Iterator it = keySet.iterator();
        String fkFieldName = "";
        while(it.hasNext()){
            String key = (String)it.next();
            FieldMap fieldMap = (FieldMap)fields.get(key);
            if( fieldMap.getPropertyName().equals(propertyName)){
                return fieldMap.getColumWithTableName();
            }
        }
        return fkFieldName;
    }
    
    /**
     * DELETE句を作成します<BR>
     * [delte * from [table] where [name]=[value] [and|or] ･･･]
     * 形式のSQLを構築します
     * @return DELETEステートメントを返します
     */
    public String toDeleteString(){
        if( gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG) != null){
            return toLogicalDeleteString();
        }else{
            StringBuffer sql = new StringBuffer("DELETE FROM ");
            sql.append(" ").append(gRecordMap.getTableName()).append(" ");
            //Where句の作成
            if( whereList.size() > 0 ){
                sql.append(line);
                sql.append("WHERE").append(line + tab);
                sql.append(getWhereString());
            }
            return sql.toString();
        }
    }
    
    public String toLogicalDeleteString(){
        StringBuffer sql = new StringBuffer("UPDATE ");
        FieldMap deleteFg = gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_FG);
        FieldMap deleteDt = gRecordMap.getFieldByFieldName(FieldMap.FLD_DELETE_DT);
        
        sql.append(line);
            
        sql.append(" ").append(gRecordMap.getTableName()).append(" ");
        sql.append(" SET ");
        sql.append(line + tab);
        sql.append(deleteFg.getColumWithTableName());
        sql.append("=1");
        if( deleteDt != null ){
            sql.append(", ");
            sql.append(deleteDt.getColumWithTableName());
            sql.append("=");
            sql.append(deleteDt.cnvSqlValue(new Date()));
        }
        //Where句の作成
        if( whereList.size() > 0 ){
            sql.append(line);
            sql.append("WHERE").append(line + tab);
            sql.append(getWhereString());
        }
        return sql.toString();
    }
    
    /**
     * INSERT句を作成します<BR>
     * [insert into [table]([name],･･･) values([value],･･･) ]
     * 形式のSQLを構築します
     * @param bean 永続化対象オブジェクト
     * @return INSERTステートメントを返します
     */
    public String toInsertString(Object bean){
        StringBuffer sql = new StringBuffer("INSERT INTO");
        HashMap fields = gRecordMap.getFields();
        sql.append(" ").append(gRecordMap.getTableName());
        sql.append("(");
        sql.append( toItemNames(fields) );
        sql.append(") VALUES(");
        sql.append( toItemValues(fields, bean) );
        sql.append(")");
        
        return sql.toString();
    }
    
    /**
     * 楽観的ロック用のバージョン番号UPDATE文を作成します<br/>
     * フィールド名にROCK_VERSIONが存在する場合、楽観的ロック用のUPDATE文を
     * 作成します。
     * @param bean 永続化対象オブジェクト
     * [update [table] set [name] = [value],･･･ ]
     */
    public String toUpdateString(Object bean){
        StringBuffer sql = new StringBuffer("UPDATE");
        HashMap fields = gRecordMap.getFields();
        Object version = null;
        try{
            version = getLockVersion(bean);
        }catch(Exception e){}
        
        sql.append(" ").append(gRecordMap.getTableName()).append(line);;
        sql.append("SET ").append(line + tab);;
        sql.append(toUpdateNames(fields, bean));
        
        //Where句の作成
        if( whereList.size() > 0 ){
            sql.append(line);
            sql.append("WHERE").append(line + tab);
            sql.append(getWhereString());
        }
        if( version != null ){
            if(  whereList.size() == 0 ){
                sql.append(line);
                sql.append("WHERE").append(line + tab);
            }else{
                sql.append(line + tab).append("AND ");
            }
            
            try{
                int versionNum = Integer.parseInt(version.toString());
                if( versionNum == 0){
                    //ロックバージョンが未登録の可能性もあるのでNULLも検索条件に含める
                    sql.append("(");
                    sql.append(FieldMap.FLD_LOCK_VERSION).append(" = ").append(version);
                    sql.append(" OR ").append(FieldMap.FLD_LOCK_VERSION).append(" is null");
                    sql.append(")");
                }else{
                    sql.append(FieldMap.FLD_LOCK_VERSION).append(" = ").append(version);
                }
            }catch(Exception e){
                sql.append(FieldMap.FLD_LOCK_VERSION).append(" = ").append(version);
            }
        }
        return sql.toString();
    }

    public Object getLockVersion(Object bean) throws BeanUtilRuntimeException {
        Object version;
        FieldMap rockVersionField = 
            gRecordMap.getFieldByFieldName(FieldMap.FLD_LOCK_VERSION);
        if( rockVersionField == null ){
            return null;
        }
        version = BeanUtil.getProperty(bean, rockVersionField.getPropertyName());
        return version;
    }
    /**
     * UPDATE句のset以降のキーワードを作成します。<BR>
     * @param bean 永続化対象オブジェクト
     * [name] = [value],･･･
     */
    protected static String toUpdateNames(HashMap fields, Object bean){
        StringBuffer sb = new StringBuffer();
        Set keySet = fields.keySet();
        Iterator it = keySet.iterator();
        boolean nextFlg = false;
        while( it.hasNext() ){
            Object key = it.next();
            FieldMap item = (FieldMap)fields.get(key);
            if( item.isPrimaryKey() ){
                continue;
            }else if(nextFlg){
                sb.append(",");
                sb.append(line + tab);
            }
            String propertyName = item.getPropertyName();
//            String value = String.valueOf(BeanUtil.getProperty(bean, propertyName));
            Object value = BeanUtil.getProperty(bean, propertyName);
            sb.append( item.getColumName() );
            sb.append( "=" );
            //楽観的ロック対応
            if( item.getColumName().equals(FieldMap.FLD_LOCK_VERSION)){
                //現行バージョン＋１をセット
                value = String.valueOf( Integer.parseInt(value.toString()) + 1 );
                //新バージョンをセット
//                BeanUtil.setProperty(bean, propertyName, value);
                sb.append(value);
            //最終更新日付の自動セット対応
            }else if( item.getColumName().equals(FieldMap.FLD_UPDATE_DT)){
                //最終更新日をセット
                Date updateDt = new Date();
                value = item.cnvSqlValue(updateDt);
                //最終更新日をセット
//                BeanUtil.setProperty(bean, propertyName, updateDt);
                sb.append(value);
            }else{
                sb.append(item.cnvSqlValue(value));
            }
            
            if( !nextFlg ){
                nextFlg = true;
            }
        }
        return sb.toString();
    }
    
    /**
     * SELECT句を作成します<BR>
     * [select [cols] from [table] where [name]=[value] [and|or] ･･･]
     * 形式のSQLを構築します
     * @return SELECTステートメントを返します
     */
    public String toSelectLockVersionString(){
        EntityInfoMapping mapping = EntityInfoMapping.getInstance();
        String dbType = mapping.getDbType();
        
        StringBuffer sql = new StringBuffer("SELECT");
        FieldMap lckField = gRecordMap.getFieldByFieldName(FieldMap.FLD_LOCK_VERSION);
        if(lckField ==null ) return null;
        
        sql.append(line+tab);
        sql.append(gRecordMap.getTableName()).append(".");
        sql.append(lckField.getColumName());
        sql.append(" AS ").append(lckField.getColumName());
        
        //単純結合テーブルのチェック
        sql.append(line);
        sql.append("FROM");
        sql.append(line + tab).append(gRecordMap.getTableName());
        
        //外部参照テーブルを取得
        sql.append(getFkTableString());
        
        //Where句の作成
        if( whereList.size() > 0 || fkRecordMaps.size() > 0 ){
            sql.append(line);
            sql.append("WHERE").append(line + tab);
        }
        
        sql.append(getWhereString());
        //外部参照フィールドを取得
        sql.append(getFkWhereString());
        
        //Group By句の作成
        if( groupByList.size() > 0 ){
            sql.append(line);
            sql.append("GROUP BY");
            sql.append(getGroupByString());
        }
        
        //Order By句の作成
        if( orderByList.size() > 0 ){
            sql.append(line);
            sql.append("ORDER BY");
            sql.append(getOrderByString());
        }
        return sql.toString();
    }
    
    /**
     * [ [name],[name]･･･ ]形式のSQLを構築します
     * @param fields フィールドのリスト
     * @return SQLを返します
     */
    protected static String toItemNames(HashMap fields){
        StringBuffer sb = new StringBuffer();
        Set keySet = fields.keySet();
        Iterator it = keySet.iterator();
        
        while( it.hasNext() ){
            Object key = it.next();
            FieldMap item = (FieldMap)fields.get(key);
            sb.append( item.getColumName().toUpperCase() );
            if( it.hasNext() ){
                sb.append(",");
            }
        }
        return sb.toString();
    }
    
    /**
     * [ [value],['value(string)']･･･ ]形式のSQLを構築します
     * @param fields フィールドのリスト
     * @return SQLを返します
     */
    protected static String toItemValues(HashMap fields, Object bean){
        StringBuffer sb = new StringBuffer();
        Set keySet = fields.keySet();
        Iterator it = keySet.iterator();
        
        while( it.hasNext() ){
            Object key = it.next();
            FieldMap item = (FieldMap)fields.get(key);
            String propertyName = item.getPropertyName();
            //String className = item.getRecordMap().getClassName();
            Object value = BeanUtil.getProperty(bean, propertyName);
            
            //楽観的ロック対応
            if( item.getColumName().equals(FieldMap.FLD_LOCK_VERSION)){
                //新バージョン１をセット
                value = String.valueOf(1);
                //新バージョンをセット
                BeanUtil.setProperty(bean, propertyName, value);
                sb.append(value);
            //最終更新日付の自動セット対応
            }else if( item.getColumName().equals(FieldMap.FLD_UPDATE_DT)){
                //最終更新日をセット
                Date updateDt = new Date();
                value = item.cnvSqlValue(updateDt);
                //最終更新日をセット
                BeanUtil.setProperty(bean, propertyName, updateDt);
                sb.append(value);
            }else if(item.getColumName().equals(FieldMap.FLD_DELETE_DT)){
                sb.append("null");
            }else{
                sb.append(item.cnvSqlValue(value));
            }
            
            if( it.hasNext() ){
                sb.append(",");
            }
        }
        return sb.toString();
    }
    
    /**
     * Criteriaインスタンスに登録されているWhere句を取得します
     * @return Criteriaインスタンスに登録されているWhere句
     */
    public String getWhereString(){
        StringBuffer sb = new StringBuffer();
        Iterator it = whereList.iterator();
        
        while( it.hasNext() ){
            String sql = (String)it.next();
            sb.append(sql);
//modify 2005/07/25 Start
//            if( it.hasNext() ){
//                sb.append(line + tab);
//                sb.append("AND ");
//            }
//modify 2005/07/25 End
        }
        return sb.toString();
    }
    
    /**
     * Criteriaインスタンスに登録されているOrder By句を取得します
     * @return Criteriaインスタンスに登録されているWhere句
     */
    public String getOrderByString(){
        StringBuffer sb = new StringBuffer();
        Iterator it = orderByList.iterator();
        
        while( it.hasNext() ){
            String sql = (String)it.next();
            sb.append(sql.toUpperCase());
            if( it.hasNext() ){
                sb.append(",");
            }
        }
        return sb.toString();
    }
    
    /**
     * Criteriaインスタンスに登録されているGroup By句を取得します
     * @return Criteriaインスタンスに登録されているWhere句
     */
    public String getGroupByString(){
        StringBuffer sb = new StringBuffer();
        Iterator it = groupByList.iterator();
        
        while( it.hasNext() ){
            String sql = (String)it.next();
            sb.append(sql.toUpperCase());
            if( it.hasNext() ){
                sb.append(",");
            }
        }
        return sb.toString();
    }
    
    /**
     * OR句を作成します
     */
    public Criteria or(){
        StringBuffer sb = new StringBuffer();
        sb.append(line);
        sb.append(tab);
        sb.append("OR ");
        whereList.add( sb.toString() );
        return this;
    }
    
    /**
     * AND句を作成します
     */
    public Criteria and(){
        StringBuffer sb = new StringBuffer();
        sb.append(line);
        sb.append(tab);
        sb.append("AND ");
        whereList.add( sb.toString() );
        return this;
    }
    
    /**
     * 昇順のORDER BY句を作成します
     * @param propertyName JavaBeansのプロパティ名
     */
    public Criteria orderby(String propertyName){
        return orderby(propertyName, true);
    }
    
    /**
     * ORDER BY句を作成します
     * @param propertyName JavaBeansのプロパティ名
     * @param sort 昇順/降順を指定します。trueを指定すると昇順になります
     */
    public Criteria orderby(String propertyName, boolean sort){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        String sortStr = "";
        if(sort == true){
            sortStr = "ASC";
        }else{
            sortStr = "DESC";
        }
        StringBuffer sb = new StringBuffer();
        sb.append(line);
        sb.append(tab);
        sb.append(fieldName);
        sb.append(" ").append(sortStr);
        orderByList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * GROUP BY句を作成します
     * @param JavaBeansのプロパティ名
     */
    public Criteria groupby(String propertyName){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        String sortStr = "";
        StringBuffer sb = new StringBuffer();
        sb.append(line);
        sb.append(tab);
        sb.append(fieldName);
        sb.append(" ").append(sortStr);
        groupByList.add( sb.toString() );
        return this;
    }
    
    /**
     * 外部参照フィールドを取得します
     * @param propertyName JavaBeansのプロパティ名
     */
    public FieldMap getFkField(String propertyName){
        String fieldName = getColumName(propertyName);
        if( fieldName == null){
            fieldName = propertyName;
        }
        Set keySet = fkRecordMaps.keySet();
        Iterator it = keySet.iterator();
        while(it.hasNext()){
            Object key = it.next();
            //外部参照情報を取得
            RecordMap fkRecordMap = (RecordMap)fkRecordMaps.get(key);
            FieldMap fieldMap = fkRecordMap.getField(fieldName);
            if(fieldMap != null){
                return fieldMap;
            }
        }
        return null;
    }
    
    /**
     * IS NULL句を作成します
     * @param propertyName JavaBeansのプロパティ名
     */
    public Criteria isnull(String propertyName){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        sb.append(fieldName).append(" IS NULL");
        whereList.add( sb.toString() );
        return this;
    }
    
    /**
     * IS NOT NULL 句を作成します
     * @param propertyName JavaBeansのプロパティ名
     */
    public Criteria isnotnull(String propertyName){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        sb.append(fieldName).append(" IS NOT NULL");
        whereList.add( sb.toString() );
        return this;
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, Object value1, Object value2){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        sb.append(fieldName);
        sb.append(" BETWEEN ");
        sb.append(fieldMap.cnvSqlValue(value1));
        sb.append(" AND ");
        sb.append(fieldMap.cnvSqlValue(value2));
        whereList.add( sb.toString() );
        return this;
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, int value1, int value2){
        return between(propertyName, String.valueOf(value1), String.valueOf(value2));
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, short value1, short value2){
        return between(propertyName, String.valueOf(value1), String.valueOf(value2));
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, double value1, double value2){
        return between(propertyName, String.valueOf(value1), String.valueOf(value2));
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, long value1, long value2){
        return between(propertyName, String.valueOf(value1), String.valueOf(value2));
    }
    
    /**
     * [BETWEEN テーブル名.フィールド 値1 AND 値2] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value1 値1
     * @param value2 値2
     */
    public Criteria between(String propertyName, float value1, float value2){
        return between(propertyName, String.valueOf(value1), String.valueOf(value2));
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param field ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria like(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        
        sb.append(fieldName).append(" ");
        sb.append("LIKE ");
        sb.append(fieldMap.cnvSqlValue(value));
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param fieldName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public void like(String fieldName, int value){
        like(fieldName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param fieldName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria like(String fieldName, short value){
        return like(fieldName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param fieldName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria like(String fieldName, double value){
        return like(fieldName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param fieldName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria like(String fieldName, long value){
        return like(fieldName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド LIKE 値] 句を作成します
     * @param fieldName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria like(String fieldName, float value){
        return like(fieldName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        if(fieldMap == null){
            fieldMap = getFkField(propertyName);
        }
        StringBuffer sb = new StringBuffer();
        
        if( fieldMap == null ){
            sb.append(propertyName).append(" = ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" = ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add(sb.toString());
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, int value){
        return eq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, short value){
        return eq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, double value){
        return eq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, long value){
        return eq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド = 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria eq(String propertyName, float value){
        return eq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        if( fieldMap == null ){
            sb.append(fieldName).append(" != ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" != ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, short value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, int value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, long value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, double value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, float value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド != 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria neq(String propertyName, Date value){
        return neq(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        if( fieldMap == null ){
            sb.append(fieldName).append(" > ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" > ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, short value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, int value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, long value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, double value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, float value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド > 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria morebig(String propertyName, Date value){
        return morebig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        if( fieldMap == null ){
            sb.append(fieldName).append(" < ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" < ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, short value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, int value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, long value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, double value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値     */
    public Criteria moresmall(String propertyName, float value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド < 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria moresmall(String propertyName, Date value){
        return moresmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        if( fieldMap == null ){
            sb.append(fieldName).append(" >= ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" >= ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, short value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, int value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, long value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, double value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, float value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド >= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria overbig(String propertyName, Date value){
        return overbig(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, Object value){
        FieldMap fieldMap = null;
        String fieldName = getColumName(propertyName);
        if( fieldName != null ){
            fieldMap = gRecordMap.getField(fieldName);
        }
        StringBuffer sb = new StringBuffer();
        if( fieldMap == null ){
            sb.append(fieldName).append(" <= ");
            sb.append(value);
        }else{
            sb.append(fieldMap.getColumWithTableName()).append(" <= ");
            sb.append(fieldMap.cnvSqlValue(value));
        }
        whereList.add( sb.toString() );
        
        return this;
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, short value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, int value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, long value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, double value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, float value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * [テーブル名.フィールド <= 値] 句を作成します
     * @param propertyName ”JavaBeansのプロパティ名
     * @param value 値
     */
    public Criteria oversmall(String propertyName, Date value){
        return oversmall(propertyName, String.valueOf(value));
    }
    
    /**
     * @return fkRecordMaps を戻します。
     */
    public HashMap getFkRecordMaps() {
        return fkRecordMaps;
    }
    /**
     * @param fkRecordMaps fkRecordMaps を設定。
     */
    public void setFkRecordMaps(HashMap fkRecordMaps) {
        this.fkRecordMaps = fkRecordMaps;
    }

    public boolean isOneToMany() {
        return oneToMany;
    }

    public void setOneToMany(boolean oneToMany) {
        this.oneToMany = oneToMany;
    }

    public HashMap getOneToManyRecordMaps() {
        return oneToManyRecordMaps;
    }

    public void setOneToManyRecordMaps(HashMap oneToManyRecordMaps) {
        this.oneToManyRecordMaps = oneToManyRecordMaps;
    }
}