org.ourbeehive.mbp.builder.SelectBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.ourbeehive.mbp.builder.SelectBuilder.java

Source

/**
 * Copyright (C) 2015-2016 OurBeehive(http://ourbeehive.github.io/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * Project Name: MyBatisPioneer
 * File Name: SelectBuilder.java
 * Package Name: org.ourbeehive.mbp.builder
 * 
 * Date: Jan 20, 2016
 * Author: Sericloud
 * 
 */

package org.ourbeehive.mbp.builder;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.ourbeehive.mbp.exception.AppException;
import org.ourbeehive.mbp.factory.OrmFactory;
import org.ourbeehive.mbp.lang.JavaSrcElm;
import org.ourbeehive.mbp.lang.MapperElm;
import org.ourbeehive.mbp.model.ant.FilterConfig;
import org.ourbeehive.mbp.model.ant.MapperArtifact;
import org.ourbeehive.mbp.model.ant.MapperProfile;
import org.ourbeehive.mbp.model.ant.RelConfig;
import org.ourbeehive.mbp.model.ant.ResultMapConfig;
import org.ourbeehive.mbp.model.ant.UserFilter;
import org.ourbeehive.mbp.model.db.OrmColumn;
import org.ourbeehive.mbp.model.db.OrmTable;
import org.ourbeehive.mbp.model.mybatis3.If;
import org.ourbeehive.mbp.model.mybatis3.Include;
import org.ourbeehive.mbp.model.mybatis3.Mapper;
import org.ourbeehive.mbp.model.mybatis3.ObjectFactory;
import org.ourbeehive.mbp.model.mybatis3.Select;
import org.ourbeehive.mbp.model.mybatis3.Sql;
import org.ourbeehive.mbp.model.mybatis3.Trim;
import org.ourbeehive.mbp.register.CtxCacheFacade;
import org.ourbeehive.mbp.register.OneToOneIdx;
import org.ourbeehive.mbp.register.OneToOneIdxFacade;
import org.ourbeehive.mbp.util.ClassAnalyzer;
import org.ourbeehive.mbp.util.ExceptionUtil;
import org.ourbeehive.mbp.util.JavaFormatter;
import org.ourbeehive.mbp.util.KeyWordsTransformer;
import org.ourbeehive.mbp.util.MapperFormatter;
import org.ourbeehive.mbp.util.ProfileHelper;
import org.ourbeehive.mbp.util.StringHelper;

public class SelectBuilder {

    private static Logger logger = Logger.getLogger(SelectBuilder.class);
    private ObjectFactory mapperObjFactory;
    private OrmFactory ormFactory;

    public SelectBuilder(ObjectFactory mapperObjFactory) {
        this.mapperObjFactory = mapperObjFactory;
    }

    public void buildCountRootTableBySql(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig resultMapConfig) throws AppException {

        try {
            // The expected 'id' of 'select'.
            String rootTableName = resultMapConfig.getTableName();
            String rootTableAlias = resultMapConfig.getTableAlias();

            // count XX BySql
            String selectId = MapperFormatter.getSelIdOfCountBySql(resultMapConfig);

            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with 'id'.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            // Initiate a blank Select.
            select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);

            // Register the new 'select' element.
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate the 'id' attribute for Select with value 'count<Root Table Name>BySqlClause'.
            select.setId(selectId);

            // TODO 2016.1.25 slp.bss.model.util.MapperSqlClause  ? where??
            // Populate the 'parameterCalss' attribute for Select.
            select.setParameterType(JavaSrcElm.SQL_CLAUSE_FULL);

            // Populate the 'resultClass' attribute for Select.
            select.setResultType(JavaSrcElm.LANG_INTEGER_FULL);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            OrmTable rootTable = CtxCacheFacade.lookupOrmTable(rootTableName);
            if (rootTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + rootTableName);
                return;
            }

            // Iterate all of the columns in a table to determine the count criteria.
            Hashtable<String, OrmColumn> allColumnIdx = rootTable.getColumnIdx();
            String columnName = null;
            OrmColumn column = null;
            StringBuffer countBy = new StringBuffer();
            for (Enumeration<String> allColumnKey = allColumnIdx.keys(); allColumnKey.hasMoreElements();) {

                columnName = allColumnKey.nextElement();
                column = rootTable.getColumnIdx().get(columnName);

                // Find the primary key.
                if (column.isPrimaryKey() == true) {
                    if (StringUtils.isNotBlank(countBy)) {
                        countBy.append(MapperElm.COMMA);
                        countBy.append(MapperElm.WHITE_SPACE);
                    }
                    countBy.append(columnName);
                }

            }

            if (StringUtils.isBlank(countBy)) {
                countBy.append(MapperElm.STAR);
            }

            // Create select clause and from clause.
            StringBuffer selectClause = new StringBuffer();
            StringBuffer fromClause = new StringBuffer();
            selectClause.append(MapperElm.SQL_SELECT);
            selectClause.append(MapperElm.WHITE_SPACE);
            selectClause.append(MapperElm.SQL_COUNT);
            selectClause.append(MapperElm.LEFT_PARENTHESIS);
            selectClause.append(countBy);
            selectClause.append(MapperElm.RIGHT_PARENTHESIS);
            fromClause.append(MapperElm.SQL_FROM);
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, rootTableName, rootTableAlias));
            select.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                    + MapperElm.CDATA_ANCHOR_END);

            // Append dynamic where clause and order by clause.
            Trim whereTrim = mapperObjFactory.createTrim();
            select.getTrim().add(whereTrim);
            whereTrim.setPrefix(MapperElm.SQL_WHERE_SIMPLE);
            whereTrim.setPrefixOverrides(MapperElm.SQL_AND_OR);
            whereTrim.setCDataBegin(
                    MapperElm.CDATA_ANCHOR_BEGIN + MapperElm.ANCHOR_WHERE_CLAUSE + MapperElm.CDATA_ANCHOR_END);

            // Register a DAO method.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(JavaSrcElm.SQL_CLAUSE_FULL);
            String comments = resultMapConfig.getComments() + JavaSrcElm.COUNT_ONE_TABLE;
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, rootTableName, selectId, paramTypeNameList,
                    JavaSrcElm.LANG_INTEGER_FULL, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    public void buildSelectRootTableByPK(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig resultMapConfig) throws AppException {

        try {

            // The expected 'id' of 'select'.
            String selectId = MapperFormatter.getSelIdOfRootTabByPK(resultMapConfig);
            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with composite id containing the select element name and the 'java.lang.Long' type name.
            String selectIdLong = selectId + JavaSrcElm.LANG_LONG_SIMPLE;
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectIdLong);
            if (select == null) {
                buildSelectRootTableByPKParamType(mapper, mapperProfile, mapperArtifact, resultMapConfig,
                        selectIdLong, JavaSrcElm.LANG_LONG_FULL);
            }

            // Lookup 'select' element with composite id containing the element name and the DTOX type name.
            String selectIdDtox = selectId + JavaSrcElm.DTOX_NAME_SUFFIX;
            select = CtxCacheFacade.lookupSelect(mapperArtifact, selectIdDtox);
            if (select == null) {
                String paramTypeName = resultMapConfig.getClassName();
                buildSelectRootTableByPKParamType(mapper, mapperProfile, mapperArtifact, resultMapConfig,
                        selectIdDtox, paramTypeName);
            }

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    public void buildSelectRootTableBySql(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig resultMapConfig) throws AppException {

        try {
            // The expected 'id' of 'select'.
            String selectId = MapperFormatter.getSelIdOfRootTabBySql(resultMapConfig);
            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with id.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            // Initiate a blank 'select' and register it.
            select = mapperObjFactory.createSelect();
            select.setId(selectId);
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate the 'parameterType' attribute for select.
            select.setParameterType(JavaSrcElm.SQL_CLAUSE_FULL);

            // Populate the 'resultMap' attribute for select.
            String rootTableName = resultMapConfig.getTableName();
            // String rootTableAlias = resultMapConfig.getTableAlias();
            String resultMapId = MapperFormatter.getResultMapIdOfRootTab(resultMapConfig);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            OrmTable rootTable = CtxCacheFacade.lookupOrmTable(rootTableName);
            if (rootTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + rootTableName);
                return;
            }

            // Define separate select and from clause for easy to reuse.
            String sqlId = MapperFormatter.getSqlIdOfRootTabSel(resultMapConfig);
            MapperSql mapperSql = new MapperSql();
            defineReusableSelectFrom4RootTab(mapperSql, mapper, mapperProfile, mapperArtifact, resultMapConfig,
                    rootTable, sqlId);

            // Define the paging query.
            if (ormFactory == null) {
                this.ormFactory = new OrmFactory(mapperProfile.getAllMapperProfile());
            }
            ormFactory.getPageQueryBuilder().definePagingQuery(mapperProfile, select, resultMapConfig, mapperSql,
                    sqlId, false, mapperObjFactory);

            // Register DAO methods.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(JavaSrcElm.SQL_CLAUSE_FULL);
            String classFullName = resultMapConfig.getClassName();
            String classSimpleName = JavaFormatter.getClassSimpleName(classFullName);
            String returnTypeName = JavaSrcElm.UTIL_LIST_SIMPLE + JavaSrcElm.LESS_THAN + classSimpleName
                    + JavaSrcElm.GREATER_THAN;
            String comments = resultMapConfig.getComments() + JavaSrcElm.QUERY_ONE_TABLE;

            // The method without paging.
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, rootTableName, selectId, paramTypeNameList,
                    returnTypeName, comments);

            // The method for paged query.
            // paramTypeNameList.add(JavaSrcElm.INT);
            // paramTypeNameList.add(JavaSrcElm.INT);
            // CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, rootTableName, selectId, paramTypeNameList, returnTypeName, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    //
    // Build public select, including oneToOne and oneToMany
    //
    // <ancesResultMapConfig>
    // ....<descOneToOne />
    // </ancesResultMapConfig>
    //
    public void buildMultiTabSelectByPK(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig ancesResultMapConfig, List<OneToOneIdx> descOtoIdxList) throws AppException {

        try {

            // The expected 'id' of 'select'.
            String selectId = MapperFormatter.getSelIdOfMultiTabByPK(ancesResultMapConfig, descOtoIdxList);
            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with composite id containing the select element name and the 'java.lang.Long' type name.
            String selectIdLong = selectId + JavaSrcElm.LANG_LONG_SIMPLE;
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectIdLong);
            if (select == null) {
                buildMultiTabSelectByPKParamType(mapper, mapperProfile, mapperArtifact, ancesResultMapConfig,
                        descOtoIdxList, selectIdLong, JavaSrcElm.LANG_LONG_FULL);
            }

            // Lookup 'select' element with composite id containing the element name and the DTOX type name.
            String selectIdDtox = selectId + JavaSrcElm.DTOX_NAME_SUFFIX;
            String ancesClassName = ancesResultMapConfig.getClassName();
            select = CtxCacheFacade.lookupSelect(mapperArtifact, selectIdDtox);
            if (select == null) {
                buildMultiTabSelectByPKParamType(mapper, mapperProfile, mapperArtifact, ancesResultMapConfig,
                        descOtoIdxList, selectIdDtox, ancesClassName);
            }

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    //
    // Build public select, including oneToOne and oneToMany
    //
    // <ancesResultMapConfig>
    // ....<descOneToOne />
    // </ancesResultMapConfig>
    //
    public void buildMultiTabSelectBySql(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig ancesResultMapConfig, List<OneToOneIdx> descOtoIdxList) throws AppException {

        try {
            // The expected 'id' of 'select'.
            String selectId = MapperFormatter.getSelIdOfMultiTabBySql(ancesResultMapConfig, descOtoIdxList);
            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with id.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            // Initiate a blank 'select' and register it.
            select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate attributes of select.
            select.setId(selectId);
            select.setParameterType(JavaSrcElm.SQL_CLAUSE_FULL);
            String resultMapId = MapperFormatter.getResultMapIdOfMultiTab(ancesResultMapConfig, descOtoIdxList);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            String ancesTableName = ancesResultMapConfig.getTableName();
            OrmTable ancesTable = CtxCacheFacade.lookupOrmTable(ancesTableName);
            if (ancesTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + ancesTableName);
                return;
            }

            // Compute the select clause.
            MapperSql mapperSql = new MapperSql();
            computeSelectClause(mapperSql, mapperProfile, null, ancesResultMapConfig, ancesTable);

            // Define join type according to the association.
            int joinType = -1;
            if (descOtoIdxList == null || descOtoIdxList.size() == 0) {
                joinType = MapperSql.JOIN_TYPE_NONE;
            } else if (descOtoIdxList != null && descOtoIdxList.size() != 0
                    && hasOuterJoin(descOtoIdxList) == true) {
                joinType = MapperSql.JOIN_TYPE_OUTER;
            } else {
                joinType = MapperSql.JOIN_TYPE_PUBLIC_INNER;
            }
            mapperSql.setJoinType(joinType);

            // Populate different kinds of clause according to join tyoe.
            computeSqlElmtForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdxList);

            // Append different kinds of clause as usable sql clause.
            String sqlId = MapperFormatter.getSqlIdOfMultiTabSel(ancesResultMapConfig, descOtoIdxList, true);
            defineReusableSelectFrom4MultiTab(mapperSql, mapper, mapperArtifact, sqlId);

            // Define the paging query.
            //definePagingQuery(mapperProfile, select, ancesResultMapConfig, mapperSql, sqlId,true);
            if (ormFactory == null) {
                this.ormFactory = new OrmFactory(mapperProfile.getAllMapperProfile());
            }
            ormFactory.getPageQueryBuilder().definePagingQuery(mapperProfile, select, ancesResultMapConfig,
                    mapperSql, sqlId, true, mapperObjFactory);

            // Register DAO methods.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(JavaSrcElm.SQL_CLAUSE_FULL);
            String classFullName = ancesResultMapConfig.getClassName();
            String classSimpleName = JavaFormatter.getClassSimpleName(classFullName);
            String returnTypeName = JavaSrcElm.UTIL_LIST_SIMPLE + JavaSrcElm.LESS_THAN + classSimpleName
                    + JavaSrcElm.GREATER_THAN;
            String comments = ancesResultMapConfig.getComments() + JavaSrcElm.QUERY_MULTI_TABLE;
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, ancesTableName, selectId, paramTypeNameList,
                    returnTypeName, comments);

            // To register a method for paging query.
            // paramTypeNameList.add(JavaSrcElm.INT);
            // paramTypeNameList.add(JavaSrcElm.INT);
            // CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, ancesTableName, selectId, paramTypeNameList, returnTypeName, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    //
    // Internal selectOneToOne only comes from oneToMany, which could from both top or higher oneToOne.
    //
    // <fatherResultMapConfig>
    // ....<sonOneToMany>
    // ........<sonReultMapConfig>
    // ............<descOneToOne />
    // ........</sonReultMapConfig>
    // ........<fatherAttr />
    // ........<sonAttr />
    // ....</sonOneToMany>
    // </fatherResultMapConfig>
    //
    public void buildIntnlSelectOto(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig fatherResultMapConfig, RelConfig sonOtmConfig, List<OneToOneIdx> descOtoIdxList,
            String selectId, String resultMapId) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'buildIntnlSelectOto' with given 'selectId': " + selectId);

        try {

            // Lookup 'select' element with id.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            // Initiate a blank 'select' and register it.
            select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate attributes of select.
            select.setId(selectId);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            ResultMapConfig sonResultMapConfig = sonOtmConfig.getResultMapConfig();
            String sonTableName = sonResultMapConfig.getTableName();
            String sonTableAlias = sonResultMapConfig.getTableAlias();
            // String sonClassName = sonResultMapConfig.getClassName();
            // select.setParameterType(sonClassName);
            OrmTable sonTable = CtxCacheFacade.lookupOrmTable(sonTableName);
            if (sonTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + sonTableName);
                return;
            }

            // Compute the select clause.
            MapperSql mapperSql = new MapperSql();
            StringBuffer selectClause = mapperSql.getSelectClause();
            computeSelectClause(mapperSql, mapperProfile, null, sonResultMapConfig, sonTable);

            // Create where clause.
            StringBuffer whereClause = mapperSql.getWhereClause();
            MapperFormatter.beginWhereStatement(whereClause);
            String sonAttr = sonOtmConfig.getSonAttr();
            String sonColumnName = JavaFormatter.getDbStyle(sonAttr);
            String fatherTableName = fatherResultMapConfig.getTableName();
            String fatherTableAlias = fatherResultMapConfig.getTableAlias();
            String fatherColumnName = JavaFormatter.getDbStyle(sonOtmConfig.getFatherAttr());
            whereClause.append(
                    MapperFormatter.getColumnFullName(mapperProfile, sonTableName, sonTableAlias, sonColumnName));
            whereClause.append(MapperElm.EQUAL);
            whereClause.append(MapperElm.POUND);
            whereClause.append(MapperElm.LEFT_BRACE);
            whereClause.append(MapperFormatter.getColumnAlias(mapperProfile, fatherTableName, fatherTableAlias,
                    fatherColumnName));
            whereClause.append(MapperElm.RIGHT_BRACE);

            // Populate from clause, append those clause from one to one.
            StringBuffer fromClause = mapperSql.getFromClause();
            int joinType = (hasOuterJoin(descOtoIdxList) == true) ? MapperSql.JOIN_TYPE_OUTER
                    : MapperSql.JOIN_TYPE_PRIVATE_INNER;
            mapperSql.setJoinType(joinType);
            computeSqlElmtForJoin(mapperSql, mapperProfile, sonResultMapConfig, descOtoIdxList);

            select.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                    + whereClause.toString() + MapperElm.CDATA_ANCHOR_END);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    //
    // Internal selectOneTable comes from oneToOne, top or higher oneToMany.
    //
    // From oneToOne:
    // <ancesResultMap>
    // ....<fatherOtoIndex>
    // ........<fatherResultMapConfig>
    // ............<sonOneToMany listOfSon="" fatherAttr="">
    // ................<sonResultMapConfig />
    // ............</sonOneToMany>
    // ........</fatherResultMapConfig>
    // ....</fatherOtoIndex>
    // ....<descOneToOne />
    // </ancesResultMap>
    //
    // From top or higher oneToMany:
    // <fatherResultMapConfig>
    // ....<sonOneToMany listOfSon="", fatherAttr="">
    // ........<sonResultMapConfig />
    // ....</sonOneToMany>
    // </fatherResultMapConfig>
    //
    public void buildIntnlSelectOneTable(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig ancesResultMapConfig, OneToOneIdx fatherOtoIndex, ResultMapConfig fatherResultMapConfig,
            RelConfig sonOtmConfig) throws AppException {

        try {

            ResultMapConfig sonResultMapConfig = sonOtmConfig.getResultMapConfig();
            String sonTableName = sonResultMapConfig.getTableName();
            String sonTableAlias = sonResultMapConfig.getTableAlias();
            String listOfSon = sonOtmConfig.getListOfSon();

            // Populate the 'id' attribute for 'select'.
            String selectId = MapperFormatter.getSelIdOfIntnlOtm(null, mapperArtifact, sonResultMapConfig,
                    listOfSon, false);

            // Lookup 'select' element with id.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            logger.debug("INTERNAL SELECT: Begin to build internal select with id: " + selectId);

            // Initiate a blank 'select' and register it.
            select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate the 'resultMap' attribute for 'select'.
            select.setId(selectId);
            String resultMapId = MapperFormatter.getResultMapIdOfIntnlOtm(mapperProfile, mapperArtifact,
                    sonResultMapConfig, listOfSon);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            OrmTable sonTable = CtxCacheFacade.lookupOrmTable(sonTableName);
            if (sonTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + sonTableName);
                return;
            }

            // Compute the select clause.
            MapperSql mapperSql = new MapperSql();
            StringBuffer selectClause = mapperSql.getSelectClause();
            computeSelectClause(mapperSql, mapperProfile, null, sonResultMapConfig, sonTable);

            // Populate from clause.
            StringBuffer fromClause = mapperSql.getFromClause();
            MapperFormatter.beginFromStatement(fromClause);
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, sonTableName, sonTableAlias));

            // Create where clause.
            StringBuffer whereClause = mapperSql.getWhereClause();
            MapperFormatter.beginWhereStatement(whereClause);
            String sonAttr = sonOtmConfig.getSonAttr();
            String sonColumnName = JavaFormatter.getDbStyle(sonAttr);
            String fatherTableName = fatherResultMapConfig.getTableName();
            String fatherTableAlias = fatherResultMapConfig.getTableAlias();
            String fatherColumnName = JavaFormatter.getDbStyle(sonOtmConfig.getFatherAttr());
            whereClause.append(
                    MapperFormatter.getColumnFullName(mapperProfile, sonTableName, sonTableAlias, sonColumnName));
            whereClause.append(MapperElm.EQUAL);
            whereClause.append(MapperElm.POUND);
            whereClause.append(MapperElm.LEFT_BRACE);
            whereClause.append(MapperFormatter.getColumnAlias(mapperProfile, fatherTableName, fatherTableAlias,
                    fatherColumnName));
            whereClause.append(MapperElm.RIGHT_BRACE);

            // Append configured filter.
            populateFilterConfig(mapperProfile, whereClause, sonResultMapConfig, MapperElm.SQL_AND_SIMPLE);

            select.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                    + whereClause.toString() + MapperElm.CDATA_ANCHOR_END);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    /**
     * Construct select element with different parameter type.
     * 
     * @param mapper
     * @param mapperProfile
     * @param mapperArtifact
     * @param resultMapConfig
     * @param selectId
     * @param paramTypeName
     * @throws AppException
     */
    private void buildSelectRootTableByPKParamType(Mapper mapper, MapperProfile mapperProfile,
            MapperArtifact mapperArtifact, ResultMapConfig resultMapConfig, String selectId, String paramTypeName)
            throws AppException {

        try {

            // Initiate a new 'select' and register it.
            Select select = mapperObjFactory.createSelect();
            select.setId(selectId);
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate the 'parameterType' attribute for select.
            select.setParameterType(paramTypeName);

            // Populate the 'resultMap' attribute for select.
            String rootTableName = resultMapConfig.getTableName();
            // String rootTableAlias = resultMapConfig.getTableAlias();
            String resultMapId = MapperFormatter.getResultMapIdOfRootTab(resultMapConfig);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            OrmTable rootTable = CtxCacheFacade.lookupOrmTable(rootTableName);
            if (rootTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + rootTableName);
                return;
            }

            // Define separate select and from clause for easy to reuse.
            String sqlId = MapperFormatter.getSqlIdOfRootTabSel(resultMapConfig);
            MapperSql mapperSql = new MapperSql();
            defineReusableSelectFrom4RootTab(mapperSql, mapper, mapperProfile, mapperArtifact, resultMapConfig,
                    rootTable, sqlId);

            // Anyway, need to populate primary key clause.
            computeWhereClauseWithPK(mapperSql, mapperProfile, rootTable, resultMapConfig, paramTypeName);
            StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
            MapperFormatter.insertWhereStatement(primaryKeyClause);

            // Refer to common sql clause in 'select'.
            Include include = mapperObjFactory.createInclude();
            include.setRefid(sqlId);
            select.getInclude().add(include);
            select.setCDataBegin(
                    MapperElm.CDATA_ANCHOR_BEGIN + primaryKeyClause.toString() + MapperElm.CDATA_ANCHOR_END);

            // Register a DAO method.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(paramTypeName);
            String returnTypeName = resultMapConfig.getClassName();
            String comments = resultMapConfig.getComments() + JavaSrcElm.QUERY_ONE_TABLE;
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, rootTableName, selectId, paramTypeNameList,
                    returnTypeName, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    /**
     * Construct select element with different parameter type.
     * 
     * @param mapper
     * @param mapperProfile
     * @param mapperArtifact
     * @param ancesResultMapConfig
     * @param descOtoIdxList
     * @throws AppException
     */
    private void buildMultiTabSelectByPKParamType(Mapper mapper, MapperProfile mapperProfile,
            MapperArtifact mapperArtifact, ResultMapConfig ancesResultMapConfig, List<OneToOneIdx> descOtoIdxList,
            String selectId, String paramTypeName) throws AppException {

        try {

            // Initiate a blank 'select' and register it.
            Select select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate attributes of Select.
            select.setId(selectId);
            select.setParameterType(paramTypeName);
            String resultMapId = MapperFormatter.getResultMapIdOfMultiTab(ancesResultMapConfig, descOtoIdxList);
            select.setResultMap(resultMapId);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            String ancesTableName = ancesResultMapConfig.getTableName();
            OrmTable ancesTable = CtxCacheFacade.lookupOrmTable(ancesTableName);
            if (ancesTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + ancesTableName);
                return;
            }

            // Refer to common sql clause in 'select'.
            String sqlId = MapperFormatter.getSqlIdOfMultiTabSel(ancesResultMapConfig, descOtoIdxList, true);
            Include include = mapperObjFactory.createInclude();
            include.setRefid(sqlId);
            select.getInclude().add(include);

            // Populate primary key clause.
            MapperSql mapperSql = new MapperSql();
            computeWhereClauseWithPK(mapperSql, mapperProfile, ancesTable, ancesResultMapConfig, paramTypeName);
            StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();

            // Define join type according to the association.
            int joinType = -1;
            if (descOtoIdxList == null || descOtoIdxList.size() == 0) {
                joinType = MapperSql.JOIN_TYPE_NONE;
            } else if (descOtoIdxList != null && descOtoIdxList.size() != 0
                    && hasOuterJoin(descOtoIdxList) == true) {
                joinType = MapperSql.JOIN_TYPE_OUTER;
            } else {
                joinType = MapperSql.JOIN_TYPE_PUBLIC_INNER;
            }
            mapperSql.setJoinType(joinType);

            if (joinType == MapperSql.JOIN_TYPE_NONE) {
                computeSqlElmtForSingle(mapperSql, mapperProfile, ancesResultMapConfig);
                MapperFormatter.insertWhereStatement(primaryKeyClause);
            } else if (joinType == MapperSql.JOIN_TYPE_OUTER) {
                // Compute the select clause.
                computeSelectClause(mapperSql, mapperProfile, null, ancesResultMapConfig, ancesTable);
                // For outer join, join condition was included inside 'fromClause'.
                computeSqlElmtForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdxList);
                MapperFormatter.insertWhereStatement(primaryKeyClause);
            }

            else {
                // Compute the select clause.
                computeSelectClause(mapperSql, mapperProfile, null, ancesResultMapConfig, ancesTable);
                // For inner join, join condition was included inside separate 'joinClause'.
                computeSqlElmtForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdxList);
                StringBuffer joinClause = mapperSql.getJoinClause();
                if (StringUtils.isNotBlank(joinClause)) {
                    MapperFormatter.insertAndStatement(primaryKeyClause);
                } else {
                    MapperFormatter.insertWhereStatement(primaryKeyClause);
                }
            }

            // Append different kinds of clause as usable sql clause.
            defineReusableSelectFrom4MultiTab(mapperSql, mapper, mapperArtifact, sqlId);

            // Append where clause into mapper.
            StringBuffer whereClause = mapperSql.getWhereClause();
            select.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + primaryKeyClause.toString() + whereClause.toString()
                    + MapperElm.CDATA_ANCHOR_END);

            // Register a DAO method.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(paramTypeName);
            String ancesClassName = ancesResultMapConfig.getClassName();
            String comments = ancesResultMapConfig.getComments() + JavaSrcElm.QUERY_MULTI_TABLE;
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, ancesTableName, selectId, paramTypeNameList,
                    ancesClassName, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    private void computeSelectClause(MapperSql mapperSql, MapperProfile mapperProfile, OneToOneIdx oneToOneIndex,
            ResultMapConfig resultMapConfig, OrmTable ormTable) throws AppException {

        // Get table name and table alias.
        String tableName = null;
        String tableAlias = null;
        if (oneToOneIndex != null) {
            tableName = oneToOneIndex.getSonTableName();
            tableAlias = oneToOneIndex.getSonTableAlias();
        } else {
            tableName = resultMapConfig.getTableName();
            tableAlias = resultMapConfig.getTableAlias();
        }

        // Compute the select clause according to the the OrmClass definition.
        HashSet<String> includedAttr = ProfileHelper.getIncludedAttrName(resultMapConfig);
        HashSet<String> excludedAttr = ProfileHelper.getExcludedAttrName(resultMapConfig);
        List<OrmColumn> ormColumnList = ormTable.getColumnList();
        OrmColumn ormColumn = null;
        String columnName = null;
        String attrName = null;
        StringBuffer selectClause = mapperSql.getSelectClause();
        StringBuffer columnNameClause = mapperSql.getColumnNameClause();
        StringBuffer columnAliasClause = mapperSql.getColumnAliasClause();

        for (int i = 0; i < ormColumnList.size(); i++) {

            ormColumn = ormColumnList.get(i);
            columnName = ormColumn.getName();
            attrName = JavaFormatter.getJavaStyle(columnName, false);

            // Check inclusion and exclusion, inclusion take higher preference.
            if (includedAttr.size() != 0) {
                if (includedAttr.contains(attrName) == false) {
                    logger.debug(
                            "INCLUDE PROPERTY: Property '" + attrName + "' is NOT in the inclusion list, skipped.");
                    continue;
                }
            } else if (excludedAttr.size() != 0) {
                if (excludedAttr.contains(attrName) == true) {
                    logger.debug(
                            "EXCLUDE PROPERTY: Property '" + attrName + "' is in the exclusion list, skipped.");
                    continue;
                }
            }

            // Handle the select clause, considering the case of the first column.
            if (StringUtils.isBlank(selectClause)) {
                selectClause.append(MapperFormatter.getSelectStmtWithPrefix(resultMapConfig));
            } else {
                selectClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
            }
            selectClause
                    .append(MapperFormatter.getColumnNamePair(mapperProfile, tableName, tableAlias, columnName));
            MapperFormatter.checkWidth(selectClause);

            // Handle the column name clause
            if (StringUtils.isNotBlank(columnNameClause)) {
                columnNameClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
            }
            columnNameClause
                    .append(MapperFormatter.getColumnNamePair(mapperProfile, tableName, tableAlias, columnName));
            MapperFormatter.checkWidth(columnNameClause);

            // Handle the column alias clause.
            if (StringUtils.isNotBlank(columnAliasClause)) {
                columnAliasClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
            }
            columnAliasClause
                    .append(MapperFormatter.getColumnAlias(mapperProfile, tableName, tableAlias, columnName));
            MapperFormatter.checkWidth(columnAliasClause);

        }

    }

    private void computeFromClause(MapperSql mapperSql, MapperProfile mapperProfile,
            ResultMapConfig resultMapConfig) {
        String rootTableName = resultMapConfig.getTableName();
        String rootTableAlias = resultMapConfig.getTableAlias();
        StringBuffer fromClause = mapperSql.getFromClause();
        MapperFormatter.beginFromStatement(fromClause);
        fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, rootTableName, rootTableAlias));
    }

    private void computeWhereClauseWithPK(MapperSql mapperSql, MapperProfile mapperProfile, OrmTable ormTable,
            ResultMapConfig resultMapConfig, String paramTypeName) throws AppException {

        List<OrmColumn> ormColumnList = ormTable.getColumnList();
        OrmColumn ormColumn = null;
        String columnName = null;
        String attrName = null;
        String tableName = resultMapConfig.getTableName();
        String tableAlias = resultMapConfig.getTableAlias();
        String voName = JavaFormatter.getVoSimpleName(resultMapConfig, false);
        KeyWordsTransformer keyWordsTransformer = KeyWordsTransformer
                .getInstance(mapperProfile.getAllMapperProfile());

        // Populate sql according to the the OrmClass definition.
        StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
        for (int i = 0; i < ormColumnList.size(); i++) {

            ormColumn = ormColumnList.get(i);
            columnName = ormColumn.getName();
            attrName = JavaFormatter.getJavaStyle(columnName, false);

            // Look up corresponding Column with columnName.
            // if (StringUtils.isNotBlank(columnName) == true) {
            // ormColumn = ormTable.getColumnIdx().get(columnName);
            // } else {
            // ormColumn = null;
            // }

            if (ormColumn != null && ormColumn.isPrimaryKey() == true) {

                if (StringUtils.isNotBlank(primaryKeyClause)) {
                    primaryKeyClause.append(MapperElm.SQL_AND_FULL);
                }
                primaryKeyClause.append(MapperFormatter.getColumnFullName(mapperProfile, tableName, tableAlias,
                        keyWordsTransformer.getTransferredStr(columnName)));
                primaryKeyClause.append(MapperElm.EQUAL);
                primaryKeyClause.append(MapperElm.POUND);
                primaryKeyClause.append(MapperElm.LEFT_BRACE);
                if (paramTypeName.startsWith(JavaSrcElm.JAVA_LANG_PKG_PREFIX) == true) {
                    primaryKeyClause.append(MapperElm.MAPPER_PK_VAL_ID);
                } else {
                    primaryKeyClause.append(voName);
                    primaryKeyClause.append(MapperElm.DOT);
                    primaryKeyClause.append(attrName);
                }
                primaryKeyClause.append(MapperElm.RIGHT_BRACE);

                logger.info("FIND MAPPING: Find primary key mapping between property '" + attrName
                        + "' and column '" + columnName + "'");

            }

        }

    }

    /**
     * This method is used to generate separate <sql> element for 'resultMapConfig' without one to one join association.
     * 
     */
    private void computeSqlElmtForSingle(MapperSql mapperSql, MapperProfile mapperProfile,
            ResultMapConfig ancesResultMapConfig) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeSqlClauseForSingle'.");

        /******************************************************************************************
         * Handle the single 'resultMapConfig'.
         ******************************************************************************************/
        computeSelectClauseForSingle(mapperSql, mapperProfile, ancesResultMapConfig);

        /**********************************************************************************************
         * Handle 'filter' from 'ancesResultMapConfig' for higher performance.
         **********************************************************************************************/
        List<FilterConfig> filterList = ancesResultMapConfig.getFilterConfig();
        if (filterList != null) {
            logger.debug("FILTER: 'filterList' of current 'ancesResultMapConfig' is not null.");
            StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
            StringBuffer whereClause = mapperSql.getWhereClause();
            if (StringUtils.isNotBlank(primaryKeyClause) || StringUtils.isNotBlank(whereClause)) {
                populateFilterConfig(mapperProfile, whereClause, ancesResultMapConfig, MapperElm.SQL_AND_SIMPLE);
            } else {
                populateFilterConfig(mapperProfile, whereClause, ancesResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
            }
        } else {
            logger.debug("FILTER: 'filterList' of current 'ancesResultMapConfig' is null.");
        }

    }

    private void computeSelectClauseForSingle(MapperSql mapperSql, MapperProfile mapperProfile,
            ResultMapConfig ancesResultMapConfig) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeSelectClauseForSingle'.");

        try {

            /******************************************************************************************
             * Build select clause.
             ******************************************************************************************/
            // Get table name and table alias.
            String tableName = ancesResultMapConfig.getTableName();
            String tableAlias = ancesResultMapConfig.getTableAlias();

            // If no DB table exist in cache according to the right table name, then return.
            OrmTable rightOrmTable = CtxCacheFacade.lookupOrmTable(tableName);
            if (rightOrmTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + tableName);
                return;
            }

            // Compute the select clause.
            computeSelectClause(mapperSql, mapperProfile, null, ancesResultMapConfig, rightOrmTable);

            /******************************************************************************************
             * Build from clause.
             ******************************************************************************************/
            StringBuffer fromClause = mapperSql.getFromClause();
            if (StringUtils.isNotBlank(fromClause)) {
                StringHelper.newLine(fromClause, JavaSrcElm.UNIT_OF_INDENT, 3);
                fromClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
            } else {
                MapperFormatter.beginFromStatement(fromClause);
            }

            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, tableName, tableAlias));

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    /**
     * This method is used to generate separate <sql> element for join. For outer join, join condition was included inside 'fromClause'. For inner
     * join, join condition was included inside separate 'joinClause'.
     */
    private void computeSqlElmtForJoin(MapperSql mapperSql, MapperProfile mapperProfile,
            ResultMapConfig ancesResultMapConfig, List<OneToOneIdx> descOtoIdxList) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeSqlClauseForJoin'.");

        /**********************************************************************************************
         * Iterate from the last to the first for higher performance.
         **********************************************************************************************/
        OneToOneIdx descOtoIdx = null;
        OneToOneIdx fatherOtoIndex = null;
        boolean hasPeer = false;
        int breakpoint = 0;
        int fatherLoc = 0;
        boolean isFirst = true;
        // Get 'descOtoIdx' in the descendant order.
        for (int i = descOtoIdxList.size() - 1; i >= 0; i--) {

            /******************************************************************************************
             * Get current element and handle it.
             ******************************************************************************************/
            logger.debug("DESCENDANT: Get element at index '" + i + "'");
            descOtoIdx = descOtoIdxList.get(i);
            computeSelectClauseForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdx, isFirst, true);

            // Set the flat 'the first one to one association' to false.
            isFirst = false;

            // If no peer, than continue to loop.
            hasPeer = descOtoIdx.isHasPeer();
            if (hasPeer == false) {
                continue;
            }
            logger.debug("HAS PEER: Father table name '" + descOtoIdx.getFatherTableName() + "', son table name '"
                    + descOtoIdx.getSonTableName() + "'");

            // Set break point as current element.
            breakpoint = i;
            logger.debug("BREAK: Break at index '" + breakpoint + "'");

            // If 'fatherOtoIndex' is not null, then begin with next element of the 'fatherOtoIndex'.
            fatherOtoIndex = descOtoIdx.getFatherOtoIndex();
            if (fatherOtoIndex != null) {
                fatherLoc = descOtoIdx.getFatherOtoIndexLoc();
            } else {
                fatherLoc = -1;
            }
            logger.debug("LOC FATHER: Locate father at '" + fatherLoc + "'");

            // Get 'descOtoIdx' in the ascendant order.
            for (int j = fatherLoc + 1; j < breakpoint; j++) {

                /**********************************************************************************************
                 * Get current element and handle it.
                 **********************************************************************************************/
                logger.debug("ASCENDANT: Get element at index '" + j + "'");
                descOtoIdx = descOtoIdxList.get(j);
                computeSelectClauseForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdx, isFirst,
                        false);

            }

            // If 'fatherOtoIndex' is not null, then continue with the location of 'fatherOtoIndex'.
            if (fatherOtoIndex == null) {
                logger.debug("EXIT TREE: Exit because no father available.");
                break;
            } else {
                i = fatherLoc + 1;
                logger.debug("CONTINUE DESC: Continue descendant '" + fatherLoc + "'");
            }

        }

        /**********************************************************************************************
         * Handle 'filter' from 'ancesResultMapConfig' for higher performance.
         **********************************************************************************************/
        List<FilterConfig> filterList = ancesResultMapConfig.getFilterConfig();
        if (filterList != null) {
            StringBuffer joinClause = mapperSql.getJoinClause();
            StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
            StringBuffer whereClause = mapperSql.getWhereClause();
            logger.debug("FILTER: 'filterList' of current 'ancesResultMapConfig' is not null.");
            if (StringUtils.isNotBlank(joinClause) || StringUtils.isNotBlank(primaryKeyClause)
                    || StringUtils.isNotBlank(whereClause)) {
                populateFilterConfig(mapperProfile, whereClause, ancesResultMapConfig, MapperElm.SQL_AND_SIMPLE);
            } else {
                populateFilterConfig(mapperProfile, whereClause, ancesResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
            }
        } else {
            logger.debug("FILTER: 'filterList' of current 'ancesResultMapConfig' is null.");
        }

    }

    /**
     * ??? join  select ??
     * 
     * @param mapperSql
     * @param mapperProfile
     * @param ancesResultMapConfig
     * @param descOtoIdx
     * @param isFirst
     * @param reverse
     * @throws AppException
     */
    private void computeSelectClauseForJoin(MapperSql mapperSql, MapperProfile mapperProfile,
            ResultMapConfig ancesResultMapConfig, OneToOneIdx descOtoIdx, boolean isFirst, boolean reverse)
            throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeSelectClauseForJoin'.");

        try {

            /******************************************************************************************
             * Build select clause.
             ******************************************************************************************/
            // Left table and right table are used to describe join relationship in SQL.
            // And left table name is 'mediTableName' or 'fatherTableName', 'mediTableName' takes higher preference.
            String leftTableName = OneToOneIdxFacade.getRelLeftTableName(descOtoIdx);
            String leftTableAlias = OneToOneIdxFacade.getRelLeftTableAlias(descOtoIdx);
            String rightTableName = descOtoIdx.getSonTableName();
            String rightTableAlias = descOtoIdx.getSonTableAlias();

            // If no DB table exist in cache according to the right table name, then return.
            OrmTable rightOrmTable = CtxCacheFacade.lookupOrmTable(rightTableName);
            if (rightOrmTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + rightTableName);
                return;
            }

            // Compute the select clause.
            RelConfig descOtoConfig = descOtoIdx.getOneToOne();
            computeSelectClause(mapperSql, mapperProfile, descOtoIdx, descOtoConfig.getResultMapConfig(),
                    rightOrmTable);

            /******************************************************************************************
             * Build from clause.
             ******************************************************************************************/
            int joinType = mapperSql.getJoinType();
            StringBuffer fromClause = mapperSql.getFromClause();
            if (joinType == MapperSql.JOIN_TYPE_PUBLIC_INNER || joinType == MapperSql.JOIN_TYPE_PRIVATE_INNER) {

                if (StringUtils.isNotBlank(fromClause)) {
                    StringHelper.newLine(fromClause, JavaSrcElm.UNIT_OF_INDENT, 3);
                    fromClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
                } else {
                    MapperFormatter.beginFromStatement(fromClause);
                }

                // If it is the first one to one association for reverse, then append right table then left table.
                if (isFirst == true && reverse == true) {
                    fromClause.append(
                            MapperFormatter.getTableNamePair(mapperProfile, rightTableName, rightTableAlias));
                    StringHelper.newLine(fromClause, JavaSrcElm.UNIT_OF_INDENT, 3);
                    fromClause.append(MapperElm.COMMA + MapperElm.WHITE_SPACE);
                    fromClause
                            .append(MapperFormatter.getTableNamePair(mapperProfile, leftTableName, leftTableAlias));
                }
                // If it is not the first one to one association for reverse, then append left table only.
                else if (isFirst == false && reverse == true) {
                    fromClause
                            .append(MapperFormatter.getTableNamePair(mapperProfile, leftTableName, leftTableAlias));
                }
                // Otherwise, append right table.
                else {
                    fromClause.append(
                            MapperFormatter.getTableNamePair(mapperProfile, rightTableName, rightTableAlias));
                }

                if (joinType == MapperSql.JOIN_TYPE_PUBLIC_INNER) {
                    computeJoinClauseForPublicInnerJoin(mapperSql, mapperProfile, descOtoIdx, reverse);
                } else {
                    computeJoinClauseForIntnlInnerJoin(mapperSql, mapperProfile, descOtoIdx, reverse);
                }

            } else {
                computeJoinClauseForOuterJoin(mapperSql, mapperProfile, descOtoIdx, isFirst, reverse);
            }

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    /**
     * ?
     * 
     * @param mapperSql
     * @param mapperProfile
     * @param descOtoIdx
     * @param reverse
     * @throws AppException
     */
    private void computeJoinClauseForPublicInnerJoin(MapperSql mapperSql, MapperProfile mapperProfile,
            OneToOneIdx descOtoIdx, boolean reverse) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeJoinClauseForPublicInnerJoin'.");

        /******************************************************************************************
         * Build join clause.
         ******************************************************************************************/
        StringBuffer joinClause = mapperSql.getJoinClause();
        if (StringUtils.isNotBlank(joinClause)) {
            MapperFormatter.beginAndStatement(joinClause);
        } else {
            MapperFormatter.beginWhereStatement(joinClause);
        }

        // Attribute name of Java class, mapped to column name in DB table.
        RelConfig descOtoConfig = descOtoIdx.getOneToOne();
        String leftTableName = OneToOneIdxFacade.getRelLeftTableName(descOtoIdx);
        String leftTableAlias = OneToOneIdxFacade.getRelLeftTableAlias(descOtoIdx);
        String rightTableName = descOtoIdx.getSonTableName();
        String rightTableAlias = descOtoIdx.getSonTableAlias();
        String leftAttrName = OneToOneIdxFacade.getRelLeftAttrName(descOtoIdx);
        String rightAttrName = descOtoConfig.getSonAttr();
        String leftColumnName = JavaFormatter.getDbStyle(leftAttrName);
        String rightColumnName = JavaFormatter.getDbStyle(rightAttrName);

        // Change the column name into full name containing alias.
        leftColumnName = MapperFormatter.getColumnFullName(mapperProfile, leftTableName, leftTableAlias,
                leftColumnName);
        rightColumnName = MapperFormatter.getColumnFullName(mapperProfile, rightTableName, rightTableAlias,
                rightColumnName);

        // Reverse the order because of handling tables from the last to the first.
        if (reverse == true) {
            joinClause.append(rightColumnName);
            joinClause.append(MapperElm.EQUAL);
            joinClause.append(leftColumnName);
        } else {
            joinClause.append(leftColumnName);
            joinClause.append(MapperElm.EQUAL);
            joinClause.append(rightColumnName);
        }

        /**********************************************************************************************
         * Handle 'filter' from 'descResultMapConfig' in every one to one.
         **********************************************************************************************/
        ResultMapConfig descResultMapConfig = descOtoConfig.getResultMapConfig();
        List<FilterConfig> filterList = descResultMapConfig.getFilterConfig();

        StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
        StringBuffer whereClause = mapperSql.getWhereClause();
        if (filterList != null) {
            logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is not null.");
            if (StringUtils.isNotBlank(joinClause) || StringUtils.isNotBlank(primaryKeyClause)
                    || StringUtils.isNotBlank(whereClause)) {
                populateFilterConfig(mapperProfile, whereClause, descResultMapConfig, MapperElm.SQL_AND_SIMPLE);
            } else {
                populateFilterConfig(mapperProfile, whereClause, descResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
            }
        } else {
            logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is null.");
        }

    }

    /**
     * ?
     * 
     * @param mapperSql
     * @param mapperProfile
     * @param descOtoIdx
     * @param reverse
     * @throws AppException
     */
    private void computeJoinClauseForIntnlInnerJoin(MapperSql mapperSql, MapperProfile mapperProfile,
            OneToOneIdx descOtoIdx, boolean reverse) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeJoinClauseForPrivateInnerJoin'.");

        /******************************************************************************************
         * Build join clause.
         ******************************************************************************************/
        // Append join condition into where clause.
        StringBuffer whereClause = mapperSql.getWhereClause();
        if (StringUtils.isNotBlank(whereClause)) {
            MapperFormatter.beginAndStatement(whereClause);
        } else {
            MapperFormatter.beginWhereStatement(whereClause);
        }

        // Attribute name of Java class, mapped to column name in DB table.
        RelConfig descOtoConfig = descOtoIdx.getOneToOne();
        String leftTableName = OneToOneIdxFacade.getRelLeftTableName(descOtoIdx);
        String leftTableAlias = OneToOneIdxFacade.getRelLeftTableAlias(descOtoIdx);
        String rightTableName = descOtoIdx.getSonTableName();
        String rightTableAlias = descOtoIdx.getSonTableAlias();
        String leftAttrName = OneToOneIdxFacade.getRelLeftAttrName(descOtoIdx);
        String rightAttrName = descOtoConfig.getSonAttr();
        String leftColumnName = JavaFormatter.getDbStyle(leftAttrName);
        String rightColumnName = JavaFormatter.getDbStyle(rightAttrName);

        // Change the column name into full name containing alias.
        leftColumnName = MapperFormatter.getColumnFullName(mapperProfile, leftTableName, leftTableAlias,
                leftColumnName);
        rightColumnName = MapperFormatter.getColumnFullName(mapperProfile, rightTableName, rightTableAlias,
                rightColumnName);

        // Reverse the order because of handling tables from the last to the first.
        if (reverse == true) {
            whereClause.append(rightColumnName);
            whereClause.append(MapperElm.EQUAL);
            whereClause.append(leftColumnName);
        } else {
            whereClause.append(leftColumnName);
            whereClause.append(MapperElm.EQUAL);
            whereClause.append(rightColumnName);
        }

        /**********************************************************************************************
         * Handle 'filter' from 'descResultMapConfig' in every one to one.
         **********************************************************************************************/
        ResultMapConfig descResultMapConfig = descOtoConfig.getResultMapConfig();
        List<FilterConfig> filterList = descResultMapConfig.getFilterConfig();

        if (filterList != null) {
            logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is not null.");
            if (StringUtils.isNotBlank(whereClause)) {
                populateFilterConfig(mapperProfile, whereClause, descResultMapConfig, MapperElm.SQL_AND_SIMPLE);
            } else {
                populateFilterConfig(mapperProfile, whereClause, descResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
            }
        } else {
            logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is null.");
        }

    }

    // private void computeJoinClauseForOuterJoin(MapperProfile mapperProfile, OneToOneIdx descOtoIdx, StringBuffer fromClause,
    // StringBuffer primaryKeyClause, StringBuffer whereClause, boolean isFirst, boolean reverse) throws AppException {

    private void computeJoinClauseForOuterJoin(MapperSql mapperSql, MapperProfile mapperProfile,
            OneToOneIdx descOtoIdx, boolean isFirst, boolean reverse) throws AppException {

        logger.debug("ENTRY: Prepare to execute 'computeJoinClauseForOuterJoin'.");

        /******************************************************************************************
         * Build from clause.
         ******************************************************************************************/
        StringBuffer fromClause = mapperSql.getFromClause();
        if (StringUtils.isNotBlank(fromClause)) {
            StringHelper.newLine(fromClause, JavaSrcElm.UNIT_OF_INDENT, 3);
        } else {
            MapperFormatter.beginFromStatement(fromClause);
        }

        // If it is the first one to one association for reverse, then append right table then left table.
        String rightTableName = descOtoIdx.getSonTableName();
        String rightTableAlias = descOtoIdx.getSonTableAlias();
        if (isFirst == true && reverse == true) {
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, rightTableName, rightTableAlias));
            StringHelper.newLine(fromClause, JavaSrcElm.UNIT_OF_INDENT, 3);
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, descOtoIdx, true));
        }
        // If it is not the first one to one association for reverse, then append left table only.
        else if (isFirst == false && reverse == true) {
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, descOtoIdx, true));
        }
        // Otherwise, append right table.
        else {
            fromClause.append(MapperFormatter.getTableNamePair(mapperProfile, descOtoIdx, false));
        }

        /**********************************************************************************************
         * Handle 'filter' from 'descResultMapConfig' in every one to one.
         **********************************************************************************************/
        RelConfig descOtoConfig = descOtoIdx.getOneToOne();
        ResultMapConfig descResultMapConfig = descOtoConfig.getResultMapConfig();
        List<FilterConfig> filterList = descResultMapConfig.getFilterConfig();

        // StringBuffer primaryKeyClause = mapperSql.getPrimaryKeyClause();
        // StringBuffer whereClause = mapperSql.getWhereClause();

        // If the primaryKeyClause is not blank, then ignore the filter config.
        // if (primaryKeyClause == null || primaryKeyClause.length() == 0) {
        // populateFilterConfig(whereClause, descResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
        // }

        if (filterList != null) {
            // logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is not null.");
            // if (primaryKeyClause != null && primaryKeyClause.length() > 0 || whereClause.length() > 0) {

            populateFilterConfig(mapperProfile, fromClause, descResultMapConfig, MapperElm.SQL_AND_SIMPLE);

            // } else {
            // populateFilterConfig(mapperProfile, whereClause, descResultMapConfig, MapperElm.SQL_WHERE_SIMPLE);
            // }
        } else {
            logger.debug("FILTER: 'filterList' of current 'descResultMapConfig' is null.");
        }

    }

    private void populateFilterConfig(MapperProfile mapperProfile, StringBuffer filterConfition,
            ResultMapConfig resultMapConfig, String filterPrefix) throws AppException {

        try {

            // Get 'filter' from current resultMapConfig.
            List<FilterConfig> filterList = resultMapConfig.getFilterConfig();
            if (filterList == null) {
                return;
            }

            String tableName = resultMapConfig.getTableName();
            String tableAlias = resultMapConfig.getTableAlias();
            FilterConfig filterConfig = null;
            String begin = null;
            String attribute = null;
            String comparator = null;
            String value = null;
            String constant = null;
            String end = null;
            ClassAnalyzer classAnalyzer = new ClassAnalyzer();

            logger.debug("FILTER: The size of current 'filterList' is: " + filterList.size());

            for (int j = 0; j < filterList.size(); j++) {

                filterConfig = filterList.get(j);
                begin = filterConfig.getBegin();
                attribute = filterConfig.getAttribute();
                comparator = filterConfig.getComparator();
                value = filterConfig.getValue();
                constant = filterConfig.getConstant();
                end = filterConfig.getEnd();

                StringHelper.newLine(filterConfition, JavaSrcElm.UNIT_OF_INDENT, 3);
                // Automatically set prefix for where clause according to filter.
                if (j == 0) {
                    // whereClause.append(MapperElm.WHITE_SPACE);
                    filterConfition.append(filterPrefix);
                    if (StringUtils.isNotBlank(begin) == true) {
                        filterConfition.append(MapperElm.WHITE_SPACE);
                        filterConfition.append(begin);
                    }
                } else {
                    if (StringUtils.isNotBlank(begin) == true) {
                        // filterConfition.append(MapperElm.WHITE_SPACE);
                        filterConfition.append(begin);
                    }
                }
                if (StringUtils.isNotBlank(attribute) == true) {

                    String columnName = JavaFormatter.getDbStyle(attribute);
                    String columnFullName = MapperFormatter.getColumnFullName(mapperProfile, tableName, tableAlias,
                            columnName);
                    filterConfition.append(MapperElm.WHITE_SPACE);
                    filterConfition.append(columnFullName);

                }
                if (StringUtils.isNotBlank(comparator) == true) {
                    filterConfition.append(MapperElm.WHITE_SPACE);
                    filterConfition.append(comparator);
                }
                if (StringUtils.isNotBlank(value) == true) {
                    filterConfition.append(MapperElm.WHITE_SPACE);
                    filterConfition.append(value);
                } else if (StringUtils.isNotBlank(constant) == true) {

                    Object objValue = classAnalyzer.getConstValue(constant);
                    filterConfition.append(MapperElm.WHITE_SPACE);
                    if (objValue.getClass().getName().equals(JavaSrcElm.LANG_STRING_FULL) == true) {
                        filterConfition.append(JavaSrcElm.SINGLE_QUOTATION);
                        filterConfition.append(objValue.toString());
                        filterConfition.append(JavaSrcElm.SINGLE_QUOTATION);
                    } else {
                        filterConfition.append(objValue.toString());
                    }

                }
                if (StringUtils.isNotBlank(end) == true) {
                    filterConfition.append(MapperElm.WHITE_SPACE);
                    filterConfition.append(end);
                }

            }

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

    private void defineReusableSelectFrom4RootTab(MapperSql mapperSql, Mapper mapper, MapperProfile mapperProfile,
            MapperArtifact mapperArtifact, ResultMapConfig resultMapConfig, OrmTable rootTable, String sqlId)
            throws AppException {

        // Lookup 'sql' element with 'sqlId', if not found, then create one.
        Sql sql = CtxCacheFacade.lookupSql(mapperArtifact, sqlId);
        if (sql != null) {
            return;
        }

        // Initiate a blank 'sql'. And register the new 'sql' element.
        sql = mapperObjFactory.createSql();
        mapper.getSql().add(sql);
        sql.setId(sqlId);
        CtxCacheFacade.addSql(mapperArtifact, sqlId, sql);

        // Compute the select clause.
        computeSelectClause(mapperSql, mapperProfile, null, resultMapConfig, rootTable);

        // Populate from clause.
        computeFromClause(mapperSql, mapperProfile, resultMapConfig);

        // Set select clause and from clause into mapper.
        StringBuffer selectClause = mapperSql.getSelectClause();
        StringBuffer fromClause = mapperSql.getFromClause();
        sql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                + MapperElm.CDATA_ANCHOR_END);

        // Define separate column name clause for easy to reuse.
        String columnNameId = sqlId + MapperElm.MAPPER_COL_NM;
        StringBuffer columnNameClause = mapperSql.getColumnNameClause();
        Sql columnNameSql = mapperObjFactory.createSql();
        mapper.getSql().add(columnNameSql);
        columnNameSql.setId(columnNameId);
        columnNameSql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + columnNameClause + MapperElm.CDATA_ANCHOR_END);

        // Define separate column alias clause for easy to reuse.
        String columnAliasId = sqlId + MapperElm.MAPPER_COL_ALIAS;
        StringBuffer columnAliasClause = mapperSql.getColumnAliasClause();
        Sql columnAliasSql = mapperObjFactory.createSql();
        mapper.getSql().add(columnAliasSql);
        columnAliasSql.setId(columnAliasId);
        columnAliasSql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + columnAliasClause + MapperElm.CDATA_ANCHOR_END);

        // Define separate from clause for easy to reuse.
        String fromId = sqlId + MapperElm.MAPPER_FROM;
        Sql fromSql = mapperObjFactory.createSql();
        mapper.getSql().add(fromSql);
        fromSql.setId(fromId);
        fromSql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + fromClause + MapperElm.CDATA_ANCHOR_END);

    }

    private void defineReusableSelectFrom4MultiTab(MapperSql mapperSql, Mapper mapper,
            MapperArtifact mapperArtifact, String sqlId) {

        // Lookup 'sql' element with 'sqlId', if not found, then create one.
        Sql sql = CtxCacheFacade.lookupSql(mapperArtifact, sqlId);
        if (sql == null) {

            // Initiate a blank 'sql'. And register the new 'sql' element.
            sql = mapperObjFactory.createSql();
            mapper.getSql().add(sql);
            sql.setId(sqlId);
            CtxCacheFacade.addSql(mapperArtifact, sqlId, sql);

            // For outer join, join condition was included inside'fromClause'.
            StringBuffer selectClause = mapperSql.getSelectClause();
            StringBuffer fromClause = mapperSql.getFromClause();
            StringBuffer joinClause = mapperSql.getJoinClause();
            int joinType = mapperSql.getJoinType();
            if (joinType == MapperSql.JOIN_TYPE_OUTER) {
                sql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                        + MapperElm.CDATA_ANCHOR_END);
            }
            // For inner join, join condition was included inside 'joinClause'.
            else {
                sql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + selectClause.toString() + fromClause.toString()
                        + joinClause.toString() + MapperElm.CDATA_ANCHOR_END);
            }

            // Define separate column name clause for easy to reuse.
            String columnNameId = sqlId + MapperElm.MAPPER_COL_NM;
            StringBuffer columnNameClause = mapperSql.getColumnNameClause();
            // String columnClause = selectClause.substring((MapperElm.SQL_SELECT + MapperElm.WHITE_SPACE).length());
            Sql columnNameSql = mapperObjFactory.createSql();
            mapper.getSql().add(columnNameSql);
            columnNameSql.setId(columnNameId);
            columnNameSql
                    .setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + columnNameClause + MapperElm.CDATA_ANCHOR_END);

            // Define separate column alias clause for easy to reuse.
            String columnAliasId = sqlId + MapperElm.MAPPER_COL_ALIAS;
            StringBuffer columnAliasClause = mapperSql.getColumnAliasClause();
            Sql columnAliasSql = mapperObjFactory.createSql();
            mapper.getSql().add(columnAliasSql);
            columnAliasSql.setId(columnAliasId);
            columnAliasSql
                    .setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + columnAliasClause + MapperElm.CDATA_ANCHOR_END);

            // Define separate from clause for easy to reuse.
            String fromId = sqlId + MapperElm.MAPPER_FROM;
            Sql fromSql = mapperObjFactory.createSql();
            mapper.getSql().add(fromSql);
            fromSql.setId(fromId);
            // For outer join, join condition was included inside'fromClause'.
            if (joinType == MapperSql.JOIN_TYPE_OUTER) {
                fromSql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + fromClause + MapperElm.CDATA_ANCHOR_END);
            }
            // For inner join, join condition was included inside 'joinClause'.
            else {
                fromSql.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + fromClause + joinClause.toString()
                        + MapperElm.CDATA_ANCHOR_END);
            }

        }

    }

    /**
     * Whether or not the including join are all inner join.
     * 
     * @param descOtoIdxList
     * @return
     */
    private boolean hasOuterJoin(List<OneToOneIdx> otoIndexList) throws AppException {

        boolean result = false;

        try {

            if (otoIndexList == null || otoIndexList.size() == 0) {
                throw new AppException("The given 'otoIndexList' could not be null or blank.");
            }

            OneToOneIdx otoIndex = null;
            RelConfig otoConfig = null;
            String joinType = null;
            for (int i = 0; i < otoIndexList.size(); i++) {

                otoIndex = otoIndexList.get(i);
                otoConfig = otoIndex.getOneToOne();
                joinType = otoConfig.getJoinType();

                if (StringUtils.isNotBlank(joinType) == true
                        && (otoConfig.getJoinType().equalsIgnoreCase(MapperElm.SQL_JOIN_LEFT) == true
                                || otoConfig.getJoinType().equalsIgnoreCase(MapperElm.SQL_JOIN_RIGHT) == true
                                || otoConfig.getJoinType().equalsIgnoreCase(MapperElm.SQL_JOIN_FULL) == true)) {

                    result = true;

                }
            }

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

        return result;

    }

    /**
     * TODO ???
     * 
     * @param mapper
     * @param mapperProfile
     * @param mapperArtifact
     * @param ancesResultMapConfig
     * @param descOtoIdxList
     * @throws AppException
     */
    public void buildMultiTabCountBySql(Mapper mapper, MapperProfile mapperProfile, MapperArtifact mapperArtifact,
            ResultMapConfig ancesResultMapConfig, List<OneToOneIdx> descOtoIdxList) throws AppException {
        try {
            UserFilter userfilter = mapperProfile.getSingleMapperProfile().get(0).getUserFilter();
            // The expected 'id' of 'select'.
            String selectId = MapperFormatter.getSelIdOfMultiTabBySql(ancesResultMapConfig, descOtoIdxList);
            String selectId2 = MapperFormatter.getSelIdOfRootTabBySql(ancesResultMapConfig);
            if (selectId.equalsIgnoreCase(selectId2))
                return;

            selectId = MapperElm.SQL_COUNT + StringUtils.capitalize(selectId);
            logger.debug("SELECT: Prepare to build select with id '" + selectId + "'.");

            // Lookup 'select' element with id.
            Select select = CtxCacheFacade.lookupSelect(mapperArtifact, selectId);
            if (select != null) {
                return;
            }

            // Initiate a blank 'select' and register it.
            select = mapperObjFactory.createSelect();
            mapper.getSelect().add(select);
            CtxCacheFacade.addSelect(mapperArtifact, selectId, select);

            // Populate attributes of select.
            select.setId(selectId);
            select.setParameterType(JavaSrcElm.SQL_CLAUSE_FULL);
            // Populate the 'resultClass' attribute for Select.
            select.setResultType(JavaSrcElm.LANG_INTEGER_FULL);

            // Find Table corresponding to current Select, if no Table found, then return Select without elements.
            String ancesTableName = ancesResultMapConfig.getTableName();
            OrmTable ancesTable = CtxCacheFacade.lookupOrmTable(ancesTableName);
            if (ancesTable == null) {
                logger.error("!!! NO TABLE !!!: No table found with table name: " + ancesTableName);
                return;
            }

            // Compute the select clause.
            MapperSql mapperSql = new MapperSql();
            computeSelectClause(mapperSql, mapperProfile, null, ancesResultMapConfig, ancesTable);

            // Define join type according to the association.
            int joinType = -1;
            if (descOtoIdxList == null || descOtoIdxList.size() == 0) {
                joinType = MapperSql.JOIN_TYPE_NONE;
            } else if (descOtoIdxList != null && descOtoIdxList.size() != 0
                    && hasOuterJoin(descOtoIdxList) == true) {
                joinType = MapperSql.JOIN_TYPE_OUTER;
            } else {
                joinType = MapperSql.JOIN_TYPE_PUBLIC_INNER;
            }
            mapperSql.setJoinType(joinType);

            // Populate different kinds of clause according to join tyoe.
            computeSqlElmtForJoin(mapperSql, mapperProfile, ancesResultMapConfig, descOtoIdxList);

            String wherecause = mapperSql.getJoinClause() + mapperSql.getWhereClause().toString();
            if (wherecause.indexOf(MapperElm.SQL_WHERE_SIMPLE) == -1) {
                wherecause = wherecause.replaceFirst(MapperElm.SQL_AND_SIMPLE, MapperElm.SQL_WHERE_SIMPLE);
            }
            String fromcause = mapperSql.getFromClause().toString();

            if (StringUtils.isBlank(fromcause)) {
                fromcause = " from " + ancesResultMapConfig.getTableName() + " " + ancesResultMapConfig
                        .getTableName().replace(JavaSrcElm.DOT, JavaSrcElm.UNDER_LINE + JavaSrcElm.UNDER_LINE)
                        + " ";
            }
            select.setCDataBegin(MapperElm.CDATA_ANCHOR_BEGIN + "select count(1) " + fromcause + wherecause
                    + MapperElm.CDATA_ANCHOR_END);

            Trim overAllTrim = mapperObjFactory.createTrim();
            select.getTrim().add(overAllTrim);
            If trimIf = mapperObjFactory.createIf();
            trimIf.setTest(MapperElm.ATTR__WHERE_CLAUSE + JavaSrcElm.EXPR_OBJ_NOT_NULL);
            overAllTrim.getIf().add(trimIf);

            Trim whereTrim = mapperObjFactory.createTrim();
            trimIf.getTrim().add(whereTrim);
            // TODO Changed at 2015.05.27???
            if (joinType == MapperSql.JOIN_TYPE_OUTER || joinType == MapperSql.JOIN_TYPE_NONE) {
                if (wherecause.indexOf(MapperElm.SQL_WHERE_SIMPLE) == -1) {
                    whereTrim.setPrefix(MapperElm.SQL_WHERE_FULL);
                } else {
                    whereTrim.setPrefix(MapperElm.SQL_AND_FULL);
                }

            } else {
                whereTrim.setPrefix(MapperElm.SQL_AND_FULL);
            }
            whereTrim.setPrefixOverrides(MapperElm.SQL_AND_SIMPLE + MapperElm.WHITE_SPACE);
            whereTrim.setCDataBegin(
                    MapperElm.CDATA_ANCHOR_BEGIN + MapperElm.ANCHOR_WHERE_CLAUSE + MapperElm.CDATA_ANCHOR_END);

            if (userfilter != null) {
                if (whereTrim.getPrefix().equals(MapperElm.SQL_AND_FULL)) {
                    select.getChoose().add(
                            UserFilterBulider.buildFilter(MapperElm.SQL_AND_FULL, mapperObjFactory, userfilter));
                } else {
                    whereTrim.getChoose().add(
                            UserFilterBulider.buildFilter(MapperElm.SQL_AND_FULL, mapperObjFactory, userfilter));

                    If noWhereIf = mapperObjFactory.createIf();
                    noWhereIf.setTest(MapperElm.ATTR__WHERE_CLAUSE + JavaSrcElm.EXPR_OBJ_IS_NULL);
                    select.getIf().add(noWhereIf);
                    noWhereIf.getChoose().add(
                            UserFilterBulider.buildFilter(whereTrim.getPrefix(), mapperObjFactory, userfilter));
                }

            }

            // Register DAO methods.
            List<String> paramTypeNameList = new ArrayList<String>();
            paramTypeNameList.add(JavaSrcElm.SQL_CLAUSE_FULL);
            String comments = ancesResultMapConfig.getComments() + JavaSrcElm.COUNT_MULTI_TABLE;
            CtxCacheFacade.addDaoMethod(mapperProfile, mapperArtifact, ancesTableName, selectId, paramTypeNameList,
                    JavaSrcElm.LANG_INTEGER_FULL, comments);

        } catch (Throwable t) {
            ExceptionUtil.handleException(t, logger);
        }

    }

}