${database.allClassCopyright}package ${myDtoMapperPackageName};
#set ($myClassName = "${myDtoMapperClassName}")

import java.util.List;
import java.util.ArrayList;
#if ($table.hasRelation())
import java.util.Map;
import java.util.HashMap;
#end

import ${myDomainEntityPackageName}.${table.extendedEntityClassName};
import ${myExtendedEntityPackageName}.${myExtendedObjectClassName};

/**
 * The DTO mapper of ${table.basicInfoDispString}.
 * <pre>
 * [primary-key]
 *     ${table.primaryKeyNameCommaString}
 *
 * [column-property]
 *     ${table.columnNameCommaString}
 *
 * [foreign-property]
 *     ${table.foreignPropertyNameCommaString}
 *
 * [referrer-property]
 *     ${table.referrerPropertyNameCommaString}
 *
 * [sequence]
 *     ${table.definedSequenceName}
 *
 * [identity]
 *     ${table.identityColumnName}
 *
 * [update-date]
 *     ${table.updateDateColumnName}
 *
 * [version-no]
 *     ${table.versionNoColumnName}
 * </pre>
 * @author ${database.classAuthor}
 */
public class ${myClassName} {

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

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    protected Map<String, Object> _relationDtoMap;
#end

    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
#if ($table.hasRelation())
    public ${myClassName}() {
        _relationDtoMap = new HashMap<String, Object>();
    }

    public ${myClassName}(Map<String, Object> relationDtoMap) {
        _relationDtoMap = relationDtoMap;
    }
#else
    public ${myClassName}() {
    }
#end

    // ===================================================================================
    //                                                                             Mapping
    //                                                                             =======
    public List<${myExtendedObjectClassName}> map(List<${table.extendedEntityClassName}> ${table.uncapitalisedJavaName}List) {
        List<${myExtendedObjectClassName}> dtoList = new ArrayList<${myExtendedObjectClassName}>();
        for (${table.extendedEntityClassName} ${table.uncapitalisedJavaName} : ${table.uncapitalisedJavaName}List) {
            dtoList.add(map(${table.uncapitalisedJavaName}));
        }
        return dtoList;
    }

    public ${myExtendedObjectClassName} map(${table.extendedEntityClassName} ${table.uncapitalisedJavaName}) {
#if ($table.hasRelation())
        String localKey = "${table.name}@" + ${table.uncapitalisedJavaName}.getDBMeta().extractPrimaryKeyMapString(${table.uncapitalisedJavaName});
        Object localDto = _relationDtoMap.get(localKey);
        if (localDto != null) {
            return (${myExtendedObjectClassName})localDto;
        }
#end
        ${myExtendedObjectClassName} dto = new ${myExtendedObjectClassName}();
#foreach ($col in $table.columns)
        dto.set${col.javaName}(${table.uncapitalisedJavaName}.get${col.javaName}());
#end
#if ($table.hasRelation())
        _relationDtoMap.put(localKey, dto);
#foreach ($foreignKey in $table.foreignKeys)
#set ($foreignEntityClassName = "${database.simpleDtoExtendedDtoPrefix}${foreignKey.foreignTable.javaName}${database.simpleDtoExtendedDtoSuffix}")
        if (${table.uncapitalisedJavaName}.get${foreignKey.foreignJavaBeansRulePropertyNameInitCap}() != null) {
            ${glPackageExtendedEntity}.${foreignKey.foreignTableExtendedEntityClassName} relationEntity = ${table.uncapitalisedJavaName}.get${foreignKey.foreignJavaBeansRulePropertyNameInitCap}();
            String relationKey = "${foreignKey.foreignTable.name}@" + relationEntity.getDBMeta().extractPrimaryKeyMapString(relationEntity);
            Object cachedDto = _relationDtoMap.get(relationKey);
            if (cachedDto != null) {
                dto.set${foreignKey.foreignJavaBeansRulePropertyNameInitCap}((${myExtendedEntityPackageName}.${foreignEntityClassName})cachedDto);
            } else {
                ${foreignEntityClassName}Mapper mapper = new ${foreignEntityClassName}Mapper(_relationDtoMap);
                dto.set${foreignKey.foreignJavaBeansRulePropertyNameInitCap}(mapper.map(relationEntity));
                _relationDtoMap.put(relationKey, dto.get${foreignKey.foreignJavaBeansRulePropertyNameInitCap}());
            }
        };
#end
#foreach ($referrer in $table.referrers)
#set ($referrerEntityClassName = "${database.simpleDtoExtendedDtoPrefix}${referrer.table.javaName}${database.simpleDtoExtendedDtoSuffix}")
#set ($foreignEntityClassName = "${database.simpleDtoExtendedDtoPrefix}${referrer.table.javaName}${database.simpleDtoExtendedDtoSuffix}")
#if (${referrer.isOneToOne()})
        if (${table.uncapitalisedJavaName}.get${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}() != null) {
            ${glPackageExtendedEntity}.${referrer.referrerTableExtendedEntityClassName} relationEntity = ${table.uncapitalisedJavaName}.get${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}();
            String relationKey = "${foreignKey.foreignTable.name}@" + relationEntity.getDBMeta().extractPrimaryKeyMapString(relationEntity);
            Object cachedDto = _relationDtoMap.get(relationKey);
            if (cachedDto != null) {
                dto.set${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}((${myExtendedEntityPackageName}.${foreignEntityClassName})cachedDto);
            } else {
                ${foreignEntityClassName}Mapper mapper = new ${foreignEntityClassName}Mapper(_relationDtoMap);
                dto.set${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}(mapper.map(relationEntity));
                _relationDtoMap.put(relationKey, dto.get${referrer.referrerJavaBeansRulePropertyNameAsOneInitCap}());
            }
        };
#else
        if (!${table.uncapitalisedJavaName}.get${referrer.referrerJavaBeansRulePropertyNameInitCap}().isEmpty()) {
            ${referrerEntityClassName}Mapper mapper = new ${referrerEntityClassName}Mapper(_relationDtoMap);
            dto.set${referrer.referrerJavaBeansRulePropertyNameInitCap}(mapper.map(${table.uncapitalisedJavaName}.get${referrer.referrerJavaBeansRulePropertyNameInitCap}()));
        };
#end
#end
#end
        return dto;
    }
}
