${database.allClassCopyright}package ${myBaseEntityPackageName};
#set ($myClassName = "${myBaseObjectClassName}")

import java.io.Serializable;
#if ($table.hasReferrerAsMany())
import java.util.List;
#end
import javax.persistence.*;

#if ($table.hasAllCommonColumn())
import ${glPackageBaseCommon}.${glCommonColumnAutoSetupper};
import ${glPackageBaseCommon}.${glEntityDefinedCommonColumn};
#end
#if ($table.hasClassification())
import ${glPackageBaseCommon}.${glCDef};
#end
#foreach ($foreignKey in $table.foreignKeys)
#set ($foreignEntityClassName = "${foreignKey.foreignTable.javaName}")
import ${myExtendedEntityPackageName}.${foreignEntityClassName};
#end
#foreach ($referrer in $table.referrers)
#set ($referrerEntityClassName = "${referrer.table.javaName}")
import ${myExtendedEntityPackageName}.${referrerEntityClassName};
#end
#set ($myEntityInterfaceName = "")
#if (${table.hasAllCommonColumn()})
  #set ($myEntityInterfaceName = "${glEntityDefinedCommonColumn}, Serializable")
#else
  #set ($myEntityInterfaceName = "${glPackageBaseCommon}.${glEntity}, Serializable")
#end

/**
 * The entity of ${table.basicInfoDispString}. <br />
#if ($table.isCommentForJavaDocValid())
 * ${table.commentForJavaDoc}
#end
 * <pre>
 * [primary-key]
 *     ${table.primaryKeyNameCommaString}
 * 
 * [column]
 *     ${table.columnNameCommaString}
 * 
 * [sequence]
 *     ${table.definedSequenceName}
 * 
 * [identity]
 *     ${table.identityColumnName}
 * 
 * [version-no]
 *     ${table.versionNoColumnName}
 * 
 * [foreign-table]
 *     ${table.foreignTableNameCommaString}
 * 
 * [referrer-table]
 *     ${table.referrerTableNameCommaString}
 * 
 * [foreign-property]
 *     ${table.foreignPropertyNameCommaString}
 * 
 * [referrer-property]
 *     ${table.referrerPropertyNameCommaString}
 * </pre>
 * @author ${database.classAuthor}
 */
@MappedSuperclass
public abstract class ${myClassName} implements ${myEntityInterfaceName} {

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    /** Serial version UID. (Default) */
    private static final long serialVersionUID = 1L;

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    // -----------------------------------------------------
    //                                                Column
    //                                                ------
#foreach ($col in $table.columns)
#if (!$col.isForeignKey())
    /** Property for ${col.javaBeansRulePropertyName} column. {${col.columnDefinitionLineDisp}} */
#if ($col.isPrimaryKey())
    @Id
#end
#if ($col.isIdentity())
    @GeneratedValue(strategy = GenerationType.IDENTITY)
#end
#if ($col.isJdbcTypeBlob() && $col.isJdbcTypeClob())
    @Lob
#end
#if ($table.isUseVersionNo() && $col.isVersionNo())
    @Version
#end
    @Column(name="${col.name}")
    protected ${col.javaNative} ${col.uncapitalisedJavaName};
    
#end
#end
#if ($table.hasAllCommonColumn())
    // -----------------------------------------------------
    //                                              Internal
    //                                              --------
    /** Is common column auto set up effective? */
    @Transient
    protected boolean _canCommonColumnAutoSetup = true;

#end
#if ($table.hasClassification())
    // ===================================================================================
    //                                                          Classification Classifying
    //                                                          ==========================
#foreach ($col in $table.columns)
#if (${col.hasClassification()})
#set ($existTop = false)
#if ($database.classificationTopDefinitionMap.containsKey($col.classificationName))
  #set ($classificationTopMap = $database.classificationTopDefinitionMap.get($col.classificationName))
  #set ($existTop = true)
#end
    /**
     * Classify the value of ${col.uncapitalisedJavaName} as the classification of ${col.classificationName}. <br />
#if ($existTop && $classificationTopMap.containsKey('topComment'))
     * $classificationTopMap.get('topComment')
#end
     * @param cls The value of ${col.uncapitalisedJavaName} as the classification of ${col.classificationName}. (Nullable)
     */
    public void classify${col.javaName}(${glCDef}.${col.classificationName} cls) {
#if ($col.isForeignKey())
        final ${col.foreignKey.foreignTable.extendedEntityClassName} entity = new ${col.foreignKey.foreignTable.extendedEntityClassName}();
#if ($col.isJavaNativeStringObject())
        entity.set${col.foreignKey.foreignTable.primaryKeyJavaNameAsOne}(cls.code());
#elseif ($col.isJavaNativeValueOfAbleObject())
        entity.set${col.foreignKey.foreignTable.primaryKeyJavaNameAsOne}(${col.javaNative}.valueOf(cls.code()));
#else
        entity.set${col.foreignKey.foreignTable.primaryKeyJavaNameAsOne}(new ${col.javaNative}(cls.code()));
#end
        set${col.foreignKey.foreignJavaBeansRulePropertyNameInitCap}(entity);
#else
#if ($col.isJavaNativeStringObject())
        set${col.javaName}(cls != null ? cls.code() : null);
#elseif ($col.isJavaNativeValueOfAbleObject())
        set${col.javaName}(cls != null ? ${col.javaNative}.valueOf(cls.code()) : null);
#else
        set${col.javaName}(cls != null ? new ${col.javaNative}(cls.code()) : null);
#end
#end
    }

#foreach ($classificationMap in $col.classificationMapList)
    /**
     * Classify the value of ${col.uncapitalisedJavaName} as ${classificationMap.get('name')}. <br />
     * $database.buildClassificationApplicationComment($classificationMap)
     */
    public void classify${col.javaName}${classificationMap.get('name')}() {
        classify${col.javaName}(${glCDef}.${col.classificationName}.${classificationMap.get('name')});
    }

#end
#end
#end
    // ===================================================================================
    //                                                        Classification Determination
    //                                                        ============================
#foreach ($col in $table.columns)
#if (${col.hasClassification()})
#set ($existTop = false)
#if ($database.classificationTopDefinitionMap.containsKey($col.classificationName))
  #set ($classificationTopMap = $database.classificationTopDefinitionMap.get($col.classificationName))
  #set ($existTop = true)
#end
    /**
     * Get the value of ${col.uncapitalisedJavaName} as the classification of ${col.classificationName}. <br />
#if ($existTop && $classificationTopMap.containsKey('topComment'))
     * $classificationTopMap.get('topComment')
#end
     * @return The value of ${col.uncapitalisedJavaName} as the classification of ${col.classificationName}. (Nullable)
     */
    public ${glCDef}.${col.classificationName} get${col.javaName}As${col.classificationName}() {
#if ($col.isForeignKey())
        return ${glCDef}.${col.classificationName}.codeOf(get${col.foreignKey.foreignJavaBeansRulePropertyNameInitCap}().get${col.foreignKey.foreignTable.primaryKeyJavaNameAsOne}());
#else
        return ${glCDef}.${col.classificationName}.codeOf(${col.uncapitalisedJavaName});
#end
    }

#foreach ($classificationMap in $col.classificationMapList)
    /**
     * Is the value of ${col.uncapitalisedJavaName} '${classificationMap.get('name')}'? <br />
     * $database.buildClassificationApplicationComment($classificationMap)
     * <p>
     * The difference of capital letters and small letters is NOT distinguished.
     * If the value is null, this method returns false!
     * </p>
     * @return Determination.
     */
    public boolean is${col.JavaName}${classificationMap.get('name')}() {
        ${glCDef}.${col.classificationName} cls = get${col.javaName}As${col.classificationName}();
        return cls != null ? cls.equals(${glCDef}.${col.classificationName}.${classificationMap.get('name')}) : false;
    }

#end
#end
#end
    // ===================================================================================
    //                                                           Classification Name/Alias
    //                                                           =========================
#foreach ($col in $table.Columns)
#if (${col.hasClassification()})
#if (!$col.isTableClassification())
#if (${col.hasClassificationName()})
    /**
     * Get the value of the column '${col.uncapitalisedJavaName}' as classification name.
     * @return The value of the column '${col.uncapitalisedJavaName}' as classification name. (Nullable)
     */
    public String get${col.JavaName}Name() {
        ${glCDef}.${col.classificationName} cls = get${col.javaName}As${col.classificationName}();
        return cls != null ? cls.name() : null;
    }

#end
#if (${col.hasClassificationAlias()})
    /**
     * Get the value of the column '${col.uncapitalisedJavaName}' as classification alias.
     * @return The value of the column '${col.uncapitalisedJavaName}' as classification alias. (Nullable)
     */
    public String get${col.JavaName}Alias() {
        ${glCDef}.${col.classificationName} cls = get${col.javaName}As${col.classificationName}();
        return cls != null ? cls.alias() : null;
    }

#end
#end
#end
#end
#end
    // ===================================================================================
    //                                                                       Foreign Table
    //                                                                       =============
#foreach ($foreignKey in $table.foreignKeys)
#set ($foreignTable = $foreignKey.foreignTable)
#set ($foreignEntityClassName = "${foreignKey.foreignTableExtendedEntityClassName}")
#set ($foreignVariableName = "${foreignKey.foreignPropertyName}")
    /** ${foreignTable.aliasExpression}${foreignTable.name} as '${foreignKey.foreignJavaBeansRulePropertyName}'. */
#if ($foreignKey.isOneToOne())
    @OneToOne(fetch=FetchType.${database.hibernateManyToOneFetch})
#else
    @ManyToOne(fetch=FetchType.${database.hibernateManyToOneFetch})
#end
#if ($foreignKey.isSimpleKeyFK())
    @JoinColumn(name="${foreignKey.localColumnNameAsOne}")
#end
    protected ${foreignEntityClassName} ${foreignVariableName};

    /**
     * ${foreignTable.aliasExpression}${foreignTable.name} as '${foreignKey.foreignJavaBeansRulePropertyName}'.
     * @return The entity of foreign property '${foreignKey.foreignJavaBeansRulePropertyName}'. (Nullable: If the foreign key does not have 'NotNull' constraint, please check null.)
     */
    public ${foreignEntityClassName} get${foreignKey.foreignJavaBeansRulePropertyNameInitCap}() {
        return ${foreignVariableName};
    }

    /**
     * ${foreignTable.aliasExpression}${foreignTable.name} as '${foreignKey.foreignJavaBeansRulePropertyName}'.
     * @param ${foreignKey.foreignPropertyName} The entity of foreign property '${foreignKey.foreignJavaBeansRulePropertyName}'. (Nullable)
     */
    public void set${foreignKey.foreignJavaBeansRulePropertyNameInitCap}(${foreignEntityClassName} ${foreignKey.foreignPropertyName}) {
        this.${foreignVariableName} = ${foreignKey.foreignPropertyName};
    }

#set ($foreignKeyIndex = $foreignKeyIndex + 1)
#end
#foreach ($referrer in $table.referrers)
#set ($referrerTable = $referrer.table)
#set ($referrerEntityClassName = "${referrer.referrerTableExtendedEntityClassName}")
#set ($referrerVariableName = "${referrer.referrerPropertyNameAsOne}")
#if ($referrer.isOneToOne())
    /** ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyNameAsOne}'. */
    @OneToOne(mappedBy = "${referrer.foreignPropertyName}", fetch=FetchType.${database.hibernateOneToOneFetch})
    protected ${referrerEntityClassName} ${referrerVariableName};

    /**
     * ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyNameAsOne}'. <br />
     * @return the entity of foreign property(referrer-as-one) '${referrer.referrerJavaBeansRulePropertyNameAsOne}'. (Nullable: If the foreign key does not have 'NotNull' constraint, please check null.)
     */
    public ${referrerEntityClassName} get${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}() {
        return ${referrerVariableName};
    }

    /**
     * ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyNameAsOne}'.
     * @param ${referrer.referrerJavaBeansRulePropertyNameAsOne} The entity of foreign property(referrer-as-one) '${referrer.referrerJavaBeansRulePropertyNameAsOne}'. (Nullable)
     */
    public void set${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}(${referrerEntityClassName} ${referrer.referrerJavaBeansRulePropertyNameAsOne}) {
        this.${referrerVariableName} = ${referrer.referrerJavaBeansRulePropertyNameAsOne};
    }

#set ($foreignKeyIndex = $foreignKeyIndex + 1)
#end
#end
    // ===================================================================================
    //                                                                      Referrer Table
    //                                                                      ==============
#foreach ($referrer in $table.referrers)
#set ($referrerTable = $referrer.table)
#set ($referrerEntityClassName = "${referrer.referrerTableExtendedEntityClassName}")
#set ($referrerVariableName = "${referrer.referrerPropertyName}")
#if (!${referrer.isOneToOne()})
    /** ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyName}'. */
    @OneToMany(mappedBy = "${referrer.foreignPropertyName}", fetch=FetchType.${database.hibernateOneToManyFetch})
    @org.hibernate.annotations.Fetch(org.hibernate.annotations.FetchMode.SUBSELECT)
    protected List<${referrerEntityClassName}> $referrerVariableName;

    /**
     * ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyName}'. <br />
     * @return The entity list of referrer property '${referrer.referrerJavaBeansRulePropertyName}'. (NotNull: If it's not loaded yet, initializes the list instance of referrer as empty and returns it.)
     */
    public List<${referrerEntityClassName}> get${referrer.referrerJavaBeansRulePropertyNameInitCap}() {
        return ${referrerVariableName};
    }

    /**
     * ${referrerTable.aliasExpression}${referrerTable.name} as '${referrer.referrerJavaBeansRulePropertyName}'.
     * @param ${referrer.referrerPropertyName} The entity list of referrer property '${referrer.referrerJavaBeansRulePropertyName}'. (Nullable)
     */
    public void set${referrer.referrerJavaBeansRulePropertyNameInitCap}(List<${referrerEntityClassName}> ${referrer.referrerPropertyName}) {
        this.${referrerVariableName} = ${referrer.referrerPropertyName};
    }

#end
#end
#if ($table.hasAllCommonColumn())
    // ===================================================================================
    //                                                              Common Column Handling
    //                                                              ======================
    @PrePersist
    public void doPrePersist() {
        ${glCommonColumnAutoSetupper} setupper = createCommonColumnAutoSetupper();
        setupper.handleCommonColumnOfInsertIfNeeds(this);
    }

    @PreUpdate
    public void doPreUpdate() {
        ${glCommonColumnAutoSetupper} setupper = createCommonColumnAutoSetupper();
        setupper.handleCommonColumnOfUpdateIfNeeds(this);
    }

    protected ${glCommonColumnAutoSetupper} createCommonColumnAutoSetupper() {
        return new ${glCommonColumnAutoSetupper}();
    }

    /**
     * Enable common column auto set up. {for after disable because the default is enabled}
     */
    public void enableCommonColumnAutoSetup() {
        _canCommonColumnAutoSetup = true;
    }

    /**
     * Disables auto set-up of common columns.
     */
    public void disableCommonColumnAutoSetup() {
        _canCommonColumnAutoSetup = false;
    }
    
    /**
     * Can the entity set up common column by auto?
     * @return Determination.
     */
    public boolean canCommonColumnAutoSetup() { // for Framework
        return _canCommonColumnAutoSetup;
    }

#end
    // ===================================================================================
    //                                                                      Basic Override
    //                                                                      ==============
#if ($table.hasPrimaryKey())
    /**
     * If the primary-key of the other is same as this one, returns true.
     * @param other Other entity.
     * @return Comparing result.
     */
    public boolean equals(Object other) {
        if (other == null || !(other instanceof $myClassName)) { return false; }
        $myClassName otherEntity = ($myClassName)other;
#foreach ($col in $table.primaryKey)
#if (!$col.isForeignKey())
        if (!helpComparingValue(get${col.JavaName}(), otherEntity.get${col.JavaName}())) { return false; }
#end
#end
        return true;
    }

    protected boolean helpComparingValue(Object value1, Object value2) {
        if (value1 == null && value2 == null) { return true; }
        return value1 != null && value2 != null && value1.equals(value2);
    }

    /**
     * Calculates hash-code from primary-key.
     * @return Hash-code from primary-key.
     */
    public int hashCode() {
        int result = 17;
#foreach ($col in $table.primaryKey)
#if (!$col.isForeignKey())
        if (get${col.JavaName}() != null) { result = (31*result) + get${col.JavaName}().hashCode(); }
#end
#end
        return result;
    }
#else
    /**
     * If the all-column value of the other is same as this one, returns true.
     * @param other Other entity. (Nullable)
     * @return Comparing result. If other is null, returns false.
     */
    public boolean equals(Object other) {
        if (other == null || !(other instanceof $myClassName)) { return false; }
        final $myClassName otherEntity = ($myClassName)other;
#foreach ($col in $table.columns)
#if (!$col.isForeignKey())
        if (!helpComparingValue(get${col.JavaName}(), otherEntity.get${col.JavaName}())) { return false; }
#end
#end
        return true;
    }

    protected boolean helpComparingValue(Object value1, Object value2) {
        if (value1 == null && value2 == null) { return true; }
        return value1 != null && value2 != null && value1.equals(value2);
    }

    /**
     * Calculates hash-code from all columns.
     * @return Hash-code from all columns.
     */
    public int hashCode() {
        int result = 17;
#foreach ($col in $table.columns)
#if (!$col.isForeignKey())
        if (get${col.javaName}() != null) { result = (31*result) + get${col.javaName}().hashCode(); }
#end
#end
        return result;
    }
#end

    /**
     * @return The display string of all columns. (NotNull)
     */
    public String toString() {
        return buildDisplayString(getClass().getSimpleName(), true, false);
    }

    /**
     * @return The display string of basic informations with one-nested relation values. (NotNull)
     */
    public String toStringWithRelation() {
        StringBuilder sb = new StringBuilder();
        sb.append(toString());
#if ($table.hasRelation())
        String l = "\n  ";
#foreach ($foreignKey in $table.foreignKeys)
#set ($foreignVariableName = "${foreignKey.foreignPropertyName}")
        if (${foreignVariableName} != null)
        { sb.append(l).append(xbRDS(${foreignVariableName}, "${foreignKey.foreignPropertyName}")); }
#end
#foreach ($referrer in $table.referrers)
#if (${referrer.isOneToOne()})
#set ($referrerVariableName = "${referrer.referrerPropertyNameAsOne}")
        if (${referrerVariableName} != null)
        { sb.append(l).append(xbRDS(${referrerVariableName}, "${referrer.referrerPropertyNameAsOne}")); }
#end
#end
#foreach ($referrer in $table.referrers)
#if (!${referrer.isOneToOne()})
#set ($referrerVariableName = "${referrer.referrerPropertyName}")
        if (${referrerVariableName} != null)
        { for (${glPackageBaseCommon}.${glEntity} e : ${referrerVariableName})
        { if (e != null) { sb.append(l).append(xbRDS(e, "${referrer.referrerPropertyName}")); } } }
#end
#end
#end
        return sb.toString();
    }
#if ($table.hasRelation())
    private String xbRDS(${glPackageBaseCommon}.${glEntity} e, String name) { // buildRelationDisplayString()
        return e.buildDisplayString(name, true, true);
    }
#end

    /**
     * @param name The name for display. (Nullable: If it's null, it does not have a name)
     * @param column Does it contains column values or not?
     * @param relation Does it contains relation existences or not?
     * @return The display string for this entity. (NotNull)
     */
    public String buildDisplayString(String name, boolean column, boolean relation) {
        StringBuilder sb = new StringBuilder();
        if (name != null) { sb.append(name).append(column || relation ? ":" : ""); }
        if (column) { sb.append(xbuildColumnString()); }
        if (relation) { sb.append(xbuildRelationString()); }
        sb.append("@").append(Integer.toHexString(hashCode()));
        return sb.toString();
    }
    private String xbuildColumnString() {
        String c = ",";
        StringBuilder sb = new StringBuilder();
#foreach ($col in $table.columns)
#if (!$col.isForeignKey())
        sb.append(c).append(${col.uncapitalisedJavaName});
#end
#end
        if (sb.length() > 0) { sb.delete(0, c.length()); }
        sb.insert(0, "{").append("}");
        return sb.toString();
    }
    private String xbuildRelationString() {
#if ($table.hasRelation())
        StringBuilder sb = new StringBuilder();
        String c = ",";
#foreach ($foreignKey in $table.foreignKeys)
#set ($foreignVariableName = "${foreignKey.foreignPropertyName}")
        if (${foreignVariableName} != null) { sb.append(c).append("${foreignKey.foreignPropertyName}"); }
#end
#foreach ($referrer in $table.referrers)
#if (${referrer.isOneToOne()})
#set ($referrerVariableName = "${referrer.referrerPropertyNameAsOne}")
        if (${referrerVariableName} != null) { sb.append(c).append("${referrer.referrerPropertyNameAsOne}"); }
#end
#end
#foreach ($referrer in $table.referrers)
#if (!${referrer.isOneToOne()})
#set ($referrerVariableName = "${referrer.referrerPropertyName}")
        if (${referrerVariableName} != null && !${referrerVariableName}.isEmpty())
        { sb.append(c).append("${referrer.referrerPropertyName}"); }
#end
#end
        if (sb.length() > 0) { sb.delete(0, c.length()).insert(0, "(").append(")"); }
        return sb.toString();
#else
        return "";
#end
    }

#set ($propertyLoopIndex = 0)
#foreach ($col in $table.columns)
#if (!$col.isForeignKey())
#if ($propertyLoopIndex == 0)
    // ===================================================================================
    //                                                                            Accessor
    //                                                                            ========
#else

#end
    /**
     * ${col.aliasExpression}${col.name}: {${col.columnDefinitionLineDisp}} <br />
#if ($col.isCommentForJavaDocValid())
     * ${col.commentForJavaDoc}
#end
     * @return The value of the column '${col.name}'. (Nullable)
     */
    public ${col.JavaNative} get${col.javaName}() {
        return ${col.uncapitalisedJavaName};
    }

    /**
     * ${col.aliasExpression}${col.name}: {${col.columnDefinitionLineDisp}} <br />
#if ($col.isCommentForJavaDocValid())
     * ${col.commentForJavaDoc}
#end
     * @param ${col.UncapitalisedJavaName} The value of the column '${col.name}'. (Nullable)
     */
    public void set${col.javaName}(${col.javaNative} ${col.uncapitalisedJavaName}) {
        this.${col.UncapitalisedJavaName} = ${col.UncapitalisedJavaName};
    }
#set ($propertyLoopIndex = $propertyLoopIndex + 1)
#end
#end
#if ($table.hasAllCommonColumn())
#foreach ($columnName in ${database.commonColumnNameConversionList})
#set ($filteredColumnName = ${database.filterCommonColumn(${columnName})})
#set ($commonColumnMap = ${database.commonColumnMap})
#set ($columnType = ${commonColumnMap.get(${columnName})})
#set ($javaNative = ${database.convertJavaNativeByJdbcType(${columnType})})
#set ($javaName = ${database.convertJavaNameByJdbcNameAsColumn(${filteredColumnName})})
#set ($uncapitalisedJavaName = ${database.convertUncapitalisedJavaNameByJdbcNameAsColumn(${filteredColumnName})})
#set ($targetJavaName = ${table.findTargetColumnJavaNameByCommonColumnName(${columnName})})

    /**
     * Get the value of the column '${uncapitalisedJavaName}'. <br />
     * @return The value of the column '${uncapitalisedJavaName}'. (Nullable)
     */
    public ${javaNative} get${javaName}() {
        return get${targetJavaName}();
    }

    /**
     * Set the value of the column '${uncapitalisedJavaName}'. <br />
     * @param ${uncapitalisedJavaName} The value of the column '${uncapitalisedJavaName}'. (Nullable)
     */
    public void set${javaName}(${javaNative} ${uncapitalisedJavaName}) {
        set${targetJavaName}(${uncapitalisedJavaName});
    }
#end
#end
}
