${database.allClassCopyright}package ${glPackageBaseParameterBean};
#set ($myClassName = "${myBaseParameterBeanClassName}")

import java.io.Serializable;
import java.util.*;

#if ($database.isPmbMetaDataForProcedure($pmbClassName))
import org.seasar.dbflute.outsidesql.ProcedurePmb;
#else
import org.seasar.dbflute.twowaysql.pmbean.ParameterBean;
#end
import org.seasar.dbflute.jdbc.*;
import org.seasar.dbflute.jdbc.ParameterUtil.ShortCharHandlingMode;
#if ($database.hasPmbMetaDataPropertyOptionAnyLikeSearch($pmbClassName))
import org.seasar.dbflute.cbean.coption.LikeSearchOption;
import org.seasar.dbflute.exception.IllegalOutsideSqlOperationException;
import org.seasar.dbflute.exception.RequiredOptionNotFoundException;
#end
#if ($database.hasPmbMetaDataPropertyOptionAnyFromTo($pmbClassName))
import org.seasar.dbflute.cbean.coption.FromToOption;
#end
import org.seasar.dbflute.util.DfTypeUtil;
#if ($database.isPmbMetaDataRefCustomizeEntity($pmbClassName))
import ${glPackageExtendedCustomizeEntity}.*;
#end

/**
 * The parameter-bean of ${pmbClassName}.
 * @author ${database.classAuthor}
 */
#if ($database.isPmbMetaDataForProcedure($pmbClassName))
public class ${myClassName} implements ProcedurePmb, FetchBean, Serializable {
#else
public class ${myClassName}${database.getPmbMetaDataSuperClassDefinition($pmbClassName)} implements ParameterBean, FetchBean, Serializable {
#end

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    /** Serial version UID. (Default) */
    private static final long serialVersionUID = 1L;
#if ($database.isPmbMetaDataForProcedure($pmbClassName))

    // -----------------------------------------------------
    //                                   Procedure Parameter
    //                                   -------------------
#if ($database.hasPmbMetaDataProcedureOverload($pmbClassName))
    // this procedure has overload parameters so you need to extend this class
    // and set up parameter annotations for one call of overload
#end
#set ($procedureParameterIndex = 0)
#set ($procedureNotParamResultIndex = 1000)
#foreach ($propertyName in $database.getPmbMetaDataPropertySet($pmbClassName))
#set ($annotationPropName = ${propertyName})
#set ($propertyType = $database.getPmbMetaDataPropertyType($pmbClassName, $propertyName))
#if ($database.isPmbMetaDataPropertyOptionProcedureParameterIn($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_PROCEDURE_PARAMETER = "in, ${procedureParameterIndex}";
#set ($procedureParameterIndex = $procedureParameterIndex + 1)
#elseif ($database.isPmbMetaDataPropertyOptionProcedureParameterOut($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_PROCEDURE_PARAMETER = "out, ${procedureParameterIndex}";
#set ($procedureParameterIndex = $procedureParameterIndex + 1)
#elseif ($database.isPmbMetaDataPropertyOptionProcedureParameterInOut($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_PROCEDURE_PARAMETER = "inout, ${procedureParameterIndex}";
#set ($procedureParameterIndex = $procedureParameterIndex + 1)
#elseif ($database.isPmbMetaDataPropertyOptionProcedureParameterReturn($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_PROCEDURE_PARAMETER = "return, -1";
#elseif ($database.isPmbMetaDataPropertyOptionProcedureParameterResult($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_PROCEDURE_PARAMETER = "notParamResult, ${procedureNotParamResultIndex}";
#set ($procedureNotParamResultIndex = $procedureNotParamResultIndex + 1)
#end
#if ($database.needsPmbMetaDataProcedureParameterStringClobHandling($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_VALUE_TYPE = "stringClobType";
#end
#if ($database.needsPmbMetaDataProcedureParameterBytesOidHandling($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_VALUE_TYPE = "bytesOidType";
#end
#if ($database.needsPmbMetaDataProcedureParameterFixedLengthStringHandling($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_VALUE_TYPE = "fixedLengthStringType";
#end
#if ($database.needsPmbMetaDataProcedureParameterObjectBindingBigDecimalHandling($pmbClassName, $propertyName))
    public static final String ${annotationPropName}_VALUE_TYPE = "objectBindingBigDecimalType";
#end
#if ($database.needsPmbMetaDataProcedureParameterOracleArrayHandling($pmbClassName, $propertyName))
    public static final ValueType ${annotationPropName}_VALUE_TYPE
            = new ${glPackageBaseCommon}.${glDBFluteConfig}.ImplementedOracleArrayType
                  ("${database.getPmbMetaDataProcedureParameterOracleArrayTypeName($pmbClassName, $propertyName)}", ${database.getPmbMetaDataProcedureParameterOracleArrayElementJavaNativeTypeLiteral($pmbClassName, $propertyName)});
#end
#if ($database.needsPmbMetaDataProcedureParameterOracleStructHandling($pmbClassName, $propertyName))
    public static final ValueType ${annotationPropName}_VALUE_TYPE
            = new ${glPackageBaseCommon}.${glDBFluteConfig}.ImplementedOracleStructType
                  ("${database.getPmbMetaDataProcedureParameterOracleStructTypeName($pmbClassName, $propertyName)}", ${database.getPmbMetaDataProcedureParameterOracleStructEntityTypeTypeLiteral($pmbClassName, $propertyName)});
#end
#end
#end

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
#foreach ($propertyName in $database.getPmbMetaDataPropertySet($pmbClassName))
#set ($variableName = "_$database.initUncap(${propertyName})")
#set ($propertyType = $database.getPmbMetaDataPropertyType($pmbClassName, $propertyName))
    /** ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)} */
    protected ${propertyType} ${variableName};

#if ($database.hasPmbMetaDataPropertyOptionAnyLikeSearch($pmbClassName, $propertyName))
    /** The value of likeSearchOption for ${propertyName}. */
    protected LikeSearchOption ${variableName}InternalLikeSearchOption;

#end
#end
#if (!$database.hasPmbMetaDataCheckSafetyResult($pmbClassName))
    /** The max size of safety result. */
    protected int _safetyMaxResultSize;

#end
    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
    public ${myClassName}() {
    }

#if ($database.isPmbMetaDataForProcedure($pmbClassName))
    // ===================================================================================
    //                                                                           Procedure
    //                                                                           =========
    /**
     * {@inheritDoc}
     */
    public String getProcedureName() {
        return "${database.getPmbMetaDataProcedureName($pmbClassName)}";
    }

    /**
     * {@inheritDoc}
     */
     public boolean isEscapeStatement() {
         return true; // as default
     }

    /**
     * {@inheritDoc}
     */
     public boolean isCalledBySelect() {
         return ${database.isPmbMetaDataProcedureCalledBySelect($pmbClassName)}; // resolved by generator
     }

#end
#if (!$database.hasPmbMetaDataCheckSafetyResult($pmbClassName))
    // ===================================================================================
    //                                                                       Safety Result
    //                                                                       =============
    /**
     * {@inheritDoc}
     */
    public void checkSafetyResult(int safetyMaxResultSize) {
        _safetyMaxResultSize = safetyMaxResultSize;
    }

    /**
     * {@inheritDoc}
     */
    public int getSafetyMaxResultSize() {
        return _safetyMaxResultSize;
    }

#end
    // ===================================================================================
    //                                                                       Assist Helper
    //                                                                       =============
    protected String convertEmptyToNull(String value) {
        return ParameterUtil.convertEmptyToNull(value);
    }

    protected String handleShortChar(String propertyName, String value, Integer size) {
        ShortCharHandlingMode mode = getShortCharHandlingMode(propertyName, value, size);
        return ParameterUtil.handleShortChar(propertyName, value, size, mode);
    }

    protected ShortCharHandlingMode getShortCharHandlingMode(String propertyName, String value, Integer size) {
        return ShortCharHandlingMode.${database.shortCharHandlingMode};
    }

    @SuppressWarnings("unchecked")
    protected <NUMBER extends Number> NUMBER toNumber(Object obj, Class<NUMBER> type) {
        return (NUMBER)DfTypeUtil.toNumber(obj, type);
    }

    protected Boolean toBoolean(Object obj) {
        return DfTypeUtil.toBoolean(obj);
    }

    protected Date toUtilDate(Date date) {
        return DfTypeUtil.toDate(date); // if sub class, re-create as pure date
    }

    protected String formatUtilDate(Date date) {
#if ($database.isDatabaseOracle())
        String pattern = "yyyy-MM-dd HH:mm:ss"; // for Oracle
#else
        String pattern = "yyyy-MM-dd";
#end
        return DfTypeUtil.toString(date, pattern);
    }

    protected String formatByteArray(byte[] bytes) {
        return "byte[" + (bytes != null ? String.valueOf(bytes.length) : "null") + "]";
    }

#if ($database.hasPmbMetaDataPropertyOptionAnyLikeSearch($pmbClassName))
    protected void assertLikeSearchOptionValid(String name, LikeSearchOption option) {
        if (option == null) {
            String msg = "The like-search option is required!";
            throw new RequiredOptionNotFoundException(msg);
        }
        if (option.isSplit()) {
            String msg = "The split of like-search is NOT available on parameter-bean.";
            msg = msg + " Don't use splitByXxx(): " + option;
            throw new IllegalOutsideSqlOperationException(msg);
        }
    }

#end
    // ===================================================================================
    //                                                                      Basic Override
    //                                                                      ==============
    /**
     * @return The display string of all parameters. (NotNull)
     */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(DfTypeUtil.toClassTitle(this)).append(":");
        sb.append(xbuildColumnString());
        return sb.toString();
    }
    private String xbuildColumnString() {
        final String c = ", ";
        final StringBuilder sb = new StringBuilder();
#foreach ($propertyName in $database.getPmbMetaDataPropertySet($pmbClassName))
#set ($variableName = "_$database.initUncap(${propertyName})")
#set ($propertyType = $database.getPmbMetaDataPropertyType($pmbClassName, $propertyName))
#if ($propertyType.equals("Date"))
        sb.append(c).append(formatUtilDate(${variableName}));
#elseif ($propertyType.equals("byte[]"))
        sb.append(c).append(formatByteArray(${variableName}));
#else
        sb.append(c).append(${variableName});
#end
#end
        if (sb.length() > 0) { sb.delete(0, c.length()); }
        sb.insert(0, "{").append("}");
        return sb.toString();
    }

    // ===================================================================================
    //                                                                            Accessor
    //                                                                            ========
#foreach ($propertyName in $database.getPmbMetaDataPropertySet($pmbClassName))
#set ($variableName = "_$database.initUncap(${propertyName})")
#set ($argumentName = "$database.initUncap(${propertyName})")
#set ($propertyType = $database.getPmbMetaDataPropertyType($pmbClassName, $propertyName))
    /**
     * [get] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @return The value of ${propertyName}. (Nullable, NotEmptyString(when String): if empty string, returns null)
     */
    public ${propertyType} get${database.initCap($propertyName)}() {
#if ($propertyType.endsWith("String"))
#if ($database.isShortCharHandlingValid() && $database.isPmbMetaDataPropertyRefColumnChar($pmbClassName, $propertyName))
        String filtered = convertEmptyToNull(${variableName});
        filtered = handleShortChar("${propertyName}", filtered, ${database.getPmbMetaDataPropertyRefSize($pmbClassName, $propertyName)});
        return filtered;
#else
        return convertEmptyToNull(${variableName});
#end
#else
#if ($propertyType.equals("Date"))
        return toUtilDate(${variableName});
#else
        return ${variableName};
#end
#end
    }
#if (!$database.hasPmbMetaDataPropertyOptionOriginalOnlyOneSetter($pmbClassName, $propertyName))

    /**
     * [set] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}(${propertyType} ${argumentName}) {
        ${variableName} = ${argumentName};
    }
#end
#if ($database.isPmbMetaDataPropertyOptionLikeSearch($pmbClassName, $propertyName))

    /**
     * [set as likeSearch] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     * @param ${argumentName}Option The option of likeSearch for ${propertyName} which is NOT split mode. (NotNull)
     */
    public void set${database.initCap($propertyName)}(${propertyType} ${argumentName}, LikeSearchOption ${argumentName}Option) {
        assertLikeSearchOptionValid("${argumentName}Option", ${argumentName}Option);
        ${variableName} = ${argumentName};
        ${variableName}InternalLikeSearchOption = ${argumentName}Option;
    }
#end
#if ($database.isPmbMetaDataPropertyOptionPrefixSearch($pmbClassName, $propertyName))

    /**
     * [set as prefixSearch] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}_PrefixSearch(${propertyType} ${argumentName}) {
        ${variableName} = ${argumentName};
        ${variableName}InternalLikeSearchOption = new LikeSearchOption().likePrefix();
    }
#end
#if ($database.isPmbMetaDataPropertyOptionContainSearch($pmbClassName, $propertyName))

    /**
     * [set as containSearch] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}_ContainSearch(${propertyType} ${argumentName}) {
        ${variableName} = ${argumentName};
        ${variableName}InternalLikeSearchOption = new LikeSearchOption().likeContain();
    }
#end
#if ($database.isPmbMetaDataPropertyOptionSuffixSearch($pmbClassName, $propertyName))

    /**
     * [set as suffixSearch] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}_SuffixSearch(${propertyType} ${argumentName}) {
        ${variableName} = ${argumentName};
        ${variableName}InternalLikeSearchOption = new LikeSearchOption().likeSuffix();
    }
#end
#if ($database.hasPmbMetaDataPropertyOptionAnyLikeSearch($pmbClassName, $propertyName))

    /**
     * Get the internal option of likeSearch for ${propertyName}. {Internal Method: Don't Invoke This!}
     * @return The internal option of likeSearch for ${propertyName}. (Nullable)
     */
    public LikeSearchOption get${database.initCap($propertyName)}InternalLikeSearchOption() {
        return ${variableName}InternalLikeSearchOption;
    }
#end
#if ($database.isPmbMetaDataPropertyOptionFromDate($pmbClassName, $propertyName))

    /**
     * [set as fromDate] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}_FromDate(${propertyType} ${argumentName}) {
        ${variableName} = new FromToOption().compareAsDate().filterFromDate(${argumentName});
    }
#end
#if ($database.isPmbMetaDataPropertyOptionToDate($pmbClassName, $propertyName))

    /**
     * [set as toDate] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)}
     * @param ${argumentName} The value of ${propertyName}. (Nullable)
     */
    public void set${database.initCap($propertyName)}_ToDate(${propertyType} ${argumentName}) {
        ${variableName} = new FromToOption().compareAsDate().filterToDate(${argumentName});
    }
#end
#if ($database.isPmbMetaDataPropertyOptionClassification($pmbClassName, $propertyName))
#set ($classificationName = $database.getPmbMetaDataPropertyOptionClassificationName($pmbClassName, $propertyName))
#foreach ($classificationMap in $database.getPmbMetaDataPropertyOptionClassificationMapList($pmbClassName, $propertyName))

    /**
     * [set as ${classificationMap.get('name')}] ${propertyName}${database.getPmbMetaDataPropertyRefColumnInfo($pmbClassName, $propertyName)} <br />
     * ${database.getMapValue($classificationMap, 'comment')}
     */
    public void set${database.initCap($propertyName)}_${classificationMap.get('name')}() {
#if ($database.isPmbMetaDataPropertyJavaNativeNumberObject($pmbClassName, $propertyName))
        ${variableName} = toNumber(${glPackageBaseCommon}.${glCDef}.${classificationName}.${classificationMap.get('name')}.code(), ${propertyType}.class);
#elseif ($database.isPmbMetaDataPropertyJavaNativeBooleanObject($pmbClassName, $propertyName))
        ${variableName} = toBoolean(${glPackageBaseCommon}.${glCDef}.${classificationName}.${classificationMap.get('name')}.code());
#else
        ${variableName} = ${glPackageBaseCommon}.${glCDef}.${classificationName}.${classificationMap.get('name')}.code();
#end
    }
#end
#end

#end
}
