protected void assertDuplicateParameterBean(String pmbName, File currentSqlFile) {
   final DfPmbMetaData metaData = _sql2entityMeta.getPmbMetaDataMap().get(pmbName);
   if (metaData == null) {
     return;
   }
   final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
   br.addNotice("The same-name parameter-beans were found.");
   br.addItem("ParameterBean");
   br.addElement(pmbName);
   br.addItem("SQL Files");
   br.addElement(metaData.getOutsideSqlFile());
   br.addElement(currentSqlFile);
   final String msg = br.buildExceptionMessage();
   throw new DfParameterBeanDuplicateException(msg);
 }
 protected void resolveSuperClassSimplePagingBean(DfPmbMetaData pmbMetaData) {
   final String superClassName = pmbMetaData.getSuperClassName();
   if (Srl.endsWithIgnoreCase(superClassName, "Paging") // main
       || Srl.equalsIgnoreCase(
           superClassName, "SPB")) { // an old style for compatibility before 0.9.7.5
     pmbMetaData.setSuperClassName("SimplePagingBean");
     if (Srl.equalsIgnoreCase(superClassName, "ManualPaging")) {
       pmbMetaData.setPagingType(DfPagingType.MANUAL);
     } else if (Srl.equalsIgnoreCase(superClassName, "AutoPaging")) {
       pmbMetaData.setPagingType(DfPagingType.AUTO);
     } else {
       pmbMetaData.setPagingType(DfPagingType.UNKNOWN);
     }
   }
 }
 // ===================================================================================
 //                                                                        Class Header
 //                                                                        ============
 protected void processClassHeader(
     String sql, String parameterBeanName, DfPmbMetaData pmbMetaData) {
   final String delimiter = "extends";
   final int idx = parameterBeanName.indexOf(delimiter);
   {
     String className = (idx >= 0) ? parameterBeanName.substring(0, idx) : parameterBeanName;
     className = className.trim();
     className = resolvePmbNameIfNeeds(className, _outsideSqlFile);
     pmbMetaData.setClassName(className);
   }
   if (idx >= 0) {
     final String superClassName = parameterBeanName.substring(idx + delimiter.length()).trim();
     pmbMetaData.setSuperClassName(superClassName);
     resolveSuperClassSimplePagingBean(pmbMetaData);
   }
 }
  /**
   * Extract the meta data of parameter bean.
   *
   * @param sql Target SQL. (NotNull and NotEmpty)
   * @return the meta data of parameter bean. (NullAllowed: If it returns null, it means 'not
   *     found'.)
   */
  public DfPmbMetaData extractPmbMetaData(String sql) {
    final String parameterBeanName = getParameterBeanName(sql);
    if (parameterBeanName == null) {
      return null;
    }
    final DfPmbMetaData pmbMetaData = new DfPmbMetaData();
    processClassHeader(sql, parameterBeanName, pmbMetaData);
    processParameterProperty(sql, parameterBeanName, pmbMetaData);
    pmbMetaData.setOutsideSqlFile(_outsideSqlFile);
    pmbMetaData.adjustPropertyMetaFinally(_schemaData);

    filterAlternateBooleanMethod(pmbMetaData);
    if (!_alternateBooleanMethodNameSet.isEmpty()) {
      // copy and clear the collection just in case
      final Set<String> set = new LinkedHashSet<String>(_alternateBooleanMethodNameSet);
      pmbMetaData.setAlternateMethodBooleanNameSet(set);
      _alternateBooleanMethodNameSet.clear();
    }
    return pmbMetaData;
  }
 protected void filterAlternateBooleanMethod(DfPmbMetaData pmbMetaData) {
   if (_alternateBooleanMethodNameSet.isEmpty()) {
     return;
   }
   for (String reservBooleanMethod : _reservBooleanMethodList) {
     if (_alternateBooleanMethodNameSet.contains(reservBooleanMethod)) {
       _alternateBooleanMethodNameSet.remove(reservBooleanMethod);
     }
   }
   final Map<String, String> propertyNameTypeMap = pmbMetaData.getPropertyNameTypeMap();
   for (String propertyName : propertyNameTypeMap.keySet()) {
     final String getterName = "get" + Srl.initCap(propertyName);
     if (_alternateBooleanMethodNameSet.contains(getterName)) {
       _alternateBooleanMethodNameSet.remove(getterName);
     }
     final String isName = "is" + Srl.initCap(propertyName);
     if (_alternateBooleanMethodNameSet.contains(isName)) {
       _alternateBooleanMethodNameSet.remove(isName);
     }
   }
 }
 protected void showParameterBean() {
   _log.info("* * * * * * * * *");
   _log.info("* ParameterBean *");
   _log.info("* * * * * * * * *");
   final StringBuilder logSb = new StringBuilder();
   final Map<String, DfPmbMetaData> pmbMetaDataMap = _sql2entityMeta.getPmbMetaDataMap();
   for (Entry<String, DfPmbMetaData> pmbEntry : pmbMetaDataMap.entrySet()) {
     final DfPmbMetaData pmbMetaData = pmbEntry.getValue();
     logSb.append(pmbMetaData.getClassName());
     if (pmbMetaData.hasSuperClassDefinition()) {
       logSb.append(" extends ").append(pmbMetaData.getSuperClassName());
     }
     if (pmbMetaData.isRelatedToProcedure()) {
       logSb.append(" (procedure");
       if (pmbMetaData.isProcedureRefCustomizeEntity()) {
         logSb.append(" with customize-entity");
       }
       logSb.append(")").append(ln());
       final Map<String, DfProcedureColumnMeta> propertyNameColumnInfoMap =
           pmbMetaData.getPropertyNameColumnInfoMap();
       for (Entry<String, DfProcedureColumnMeta> columnEntry :
           propertyNameColumnInfoMap.entrySet()) {
         final DfProcedureColumnMeta columnInfo = columnEntry.getValue();
         logSb.append("  ").append(columnInfo.getColumnNameDisp());
         logSb.append(ln());
       }
     } else {
       if (pmbMetaData.isTypedParameterBean()) {
         logSb.append(" ").append(pmbMetaData.buildTypedDisp());
       }
       logSb.append(ln());
       final Map<String, String> propertyNameTypeMap = pmbMetaData.getPropertyNameTypeMap();
       final Map<String, String> propertyOptionMap = pmbMetaData.getPropertyNameOptionMap();
       for (Entry<String, String> propEntry : propertyNameTypeMap.entrySet()) {
         final String propertyName = propEntry.getKey();
         final String propertyType = propEntry.getValue();
         logSb.append("  ").append(propertyType).append(" ").append(propertyName);
         final String optionDef = propertyOptionMap.get(propertyName);
         if (Srl.is_NotNull_and_NotTrimmedEmpty(optionDef)) {
           logSb.append(":").append(optionDef);
         }
         logSb.append(ln());
       }
     }
     logSb.append(ln());
   }
   if (logSb.length() > 0) {
     _log.info(ln() + logSb.toString().trim());
   }
 }
 protected void processScalarHandling(DfCustomizeEntityInfo entityInfo, Table tbl) {
   final DfPmbMetaData pmbMetaData = entityInfo.getPmbMetaData(); // for check only
   if (pmbMetaData == null || !pmbMetaData.isTypedSelectPmb()) { // not pinpoint (but enough)
     final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
     br.addNotice("The 'scalar' option was not related to a typed parameter-bean.");
     br.addItem("Advice");
     br.addElement("A 'scalar' option should be defined with a typed parameter-bean");
     br.addElement("that is typed to things returning an scalar value.");
     br.addElement("For example:");
     br.addElement("  (x): selectMemberName.sql");
     br.addElement("  (o): MemberBhv_selectMemberName.sql");
     br.addElement("  (x):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +scalar+");
     br.addElement("");
     br.addElement("    select MEMBER_NAME from MEMBER");
     br.addElement("  (o):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +scalar+");
     br.addElement("");
     br.addElement("    -- !df:pmb!");
     br.addElement("");
     br.addElement("    select MEMBER_NAME from MEMBER");
     br.addItem("SQL File");
     br.addElement(entityInfo.getSqlFile());
     final String msg = br.buildExceptionMessage();
     throw new DfCustomizeEntityMarkInvalidException(msg);
   }
   final List<Column> columnList = tbl.getColumnList();
   if (columnList.size() != 1) {
     final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
     br.addNotice("The 'scalar' option was related to non-only-one-column SQL.");
     br.addItem("Advice");
     br.addElement("A 'scalar' option should be defined on only-one-column SQL.");
     br.addElement("For example:");
     br.addElement("  (x):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +scalar+");
     br.addElement("  ");
     br.addElement("    -- !df:pmb!");
     br.addElement("  ");
     br.addElement("    select MEMBER_NAME, BIRTHDATE from MEMBER");
     br.addElement("  (o):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +scalar+");
     br.addElement("");
     br.addElement("    -- !df:pmb!");
     br.addElement("");
     br.addElement("    select BIRTHDATE from MEMBER");
     br.addItem("SQL File");
     br.addElement(entityInfo.getSqlFile());
     br.addItem("Selected Column");
     if (!columnList.isEmpty()) {
       for (Column column : columnList) {
         br.addElement(column.getName());
       }
     } else {
       br.addElement("(empty)");
     }
     final String msg = br.buildExceptionMessage();
     throw new DfCustomizeEntityMarkInvalidException(msg);
   }
   final Column column = columnList.get(0);
   entityInfo.setScalarJavaNative(column.getJavaNative());
   entityInfo.setScalarColumnDisp(column.getColumnDefinitionLineDisp());
 }
 // -----------------------------------------------------
 //                                       Result Handling
 //                                       ---------------
 protected void processDomainHandling(DfCustomizeEntityInfo entityInfo, Table tbl) {
   final DfPmbMetaData pmbMetaData = entityInfo.getPmbMetaData();
   if (pmbMetaData == null || !pmbMetaData.isTypedReturnEntityPmb()) {
     final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
     br.addNotice("The 'domain' option was not related to a typed parameter-bean.");
     br.addItem("Advice");
     br.addElement("A 'domain' option should be defined with a typed parameter-bean");
     br.addElement("that is typed to things returning an entity.");
     br.addElement("For example:");
     br.addElement("  (x): selectDomainMember.sql");
     br.addElement("  (o): MemberBhv_selectDomainMember.sql");
     br.addElement("  (x):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +domain+");
     br.addElement("");
     br.addElement("    select MEMBER_ID, MEMBER_NAME, ... from MEMBER");
     br.addElement("  (o):");
     br.addElement("    -- #df:entity#");
     br.addElement("    -- +domain+");
     br.addElement("");
     br.addElement("    -- !df:pmb!");
     br.addElement("");
     br.addElement("    select MEMBER_ID, MEMBER_NAME, ... from MEMBER");
     br.addItem("SQL File");
     br.addElement(entityInfo.getSqlFile());
     final String msg = br.buildExceptionMessage();
     throw new DfCustomizeEntityMarkInvalidException(msg);
   }
   final String entityClassName = pmbMetaData.getEntityClassName();
   if (Srl.is_Null_or_TrimmedEmpty(entityClassName)) {
     String msg = "The entity class name should not be null: " + entityInfo.getSqlFile();
     throw new IllegalStateException(msg); // no way
   }
   final Database database = _schemaData.getDatabase();
   Table domainTable = database.getTable(entityClassName);
   if (domainTable == null) { // retry without project-prefix for a class name
     final String projectPrefix = getBasicProperties().getProjectPrefix();
     domainTable = database.getTable(Srl.substringFirstFront(entityClassName, projectPrefix));
   }
   if (domainTable == null) {
     final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
     br.addNotice("The table of the behavior query was not found.");
     br.addItem("Advice");
     br.addElement("A 'domain' option should be defined under behavior query.");
     br.addElement("And behavior query should have an existing table.");
     br.addElement("For example:");
     br.addElement("  (x): MembooBhv_selectDomainMember.sql");
     br.addElement("  (o): MemberBhv_selectDomainMember.sql");
     br.addItem("SQL File");
     br.addElement(entityInfo.getSqlFile());
     final String msg = br.buildExceptionMessage();
     throw new DfCustomizeEntityMarkInvalidException(msg); // basically no way
   }
   final List<Column> columnList = tbl.getColumnList();
   for (Column column : columnList) {
     final Column found = domainTable.getColumn(column.getName());
     if (found == null) {
       final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
       br.addNotice("The selected column was not a column of domain table.");
       br.addItem("Advice");
       br.addElement("A selected column with a 'domain' option");
       br.addElement("should be one of domain table.");
       br.addElement("For example:");
       br.addElement("  (x):");
       br.addElement("    select MEMBER_ID, 'noexist' as NO_EXIST from MEMBER");
       br.addElement("  (o):");
       br.addElement("    select MEMBER_ID, MEMBER_NAME from MEMBER");
       br.addElement("  (o):");
       br.addElement("    select member.* from MEMBER member");
       br.addItem("SQL File");
       br.addElement(entityInfo.getSqlFile());
       br.addItem("Unknown Column");
       br.addElement(column.getName());
       br.addItem("Domain Table");
       br.addElement(domainTable.getTableDbName());
       final String msg = br.buildExceptionMessage();
       throw new DfCustomizeEntityMarkInvalidException(msg);
     }
   }
   entityInfo.setEntityClassName(domainTable.getExtendedEntityClassName());
   entityInfo.setEntityClassName(domainTable.getImmutableExtendedEntityClassName());
 }
 // ===================================================================================
 //                                                                  Parameter Property
 //                                                                  ==================
 protected void processParameterProperty(
     String sql, String parameterBeanName, DfPmbMetaData pmbMetaData) {
   final Map<String, String> propertyNameTypeMap = new LinkedHashMap<String, String>();
   final Map<String, String> propertyNameOptionMap = new LinkedHashMap<String, String>();
   final Set<String> autoDetectedPropertyNameSet = new LinkedHashSet<String>();
   pmbMetaData.setPropertyNameTypeMap(propertyNameTypeMap);
   pmbMetaData.setPropertyNameOptionMap(propertyNameOptionMap);
   pmbMetaData.setAutoDetectedPropertyNameSet(autoDetectedPropertyNameSet);
   final List<DfSql2EntityMark> parameterBeanElement = getParameterBeanPropertyTypeList(sql);
   final String autoDetectMark = "AutoDetect";
   for (DfSql2EntityMark mark : parameterBeanElement) {
     final String element = mark.getContent().trim();
     if (element.equalsIgnoreCase(autoDetectMark)) {
       processAutoDetect(
           sql, propertyNameTypeMap, propertyNameOptionMap, autoDetectedPropertyNameSet);
       break;
     }
   }
   for (DfSql2EntityMark mark : parameterBeanElement) {
     final String element = mark.getContent().trim();
     final String nameDelimiter = " ";
     final String optionDelimiter = ":";
     if (autoDetectMark.equals(element)) {
       continue; // because of already resolved
     }
     final int delimiterIndex = element.indexOf(optionDelimiter);
     final String slaslaOption;
     {
       final String optionPrefix = DfPmbPropertyOptionComment.OPTION_PREFIX;
       final String optionSuffix = DfPmbPropertyOptionComment.OPTION_SUFFIX;
       final String comment = mark.getComment();
       if (Srl.is_NotNull_and_NotTrimmedEmpty(comment)) {
         final String filtered = Srl.replace(comment, "|", "/").trim();
         slaslaOption = optionPrefix + filtered + optionSuffix;
       } else {
         slaslaOption = null;
       }
     }
     final String propertyDef;
     final String optionDef;
     if (delimiterIndex > 0) {
       propertyDef = element.substring(0, delimiterIndex).trim();
       final int optionIndex = delimiterIndex + optionDelimiter.length();
       final String basicOption = element.substring(optionIndex).trim();
       optionDef = basicOption + (slaslaOption != null ? "|" + slaslaOption : "");
     } else {
       propertyDef = element;
       optionDef = (slaslaOption != null ? slaslaOption : null);
     }
     final int nameIndex = propertyDef.lastIndexOf(nameDelimiter);
     if (nameIndex <= 0) {
       String msg = "The parameter bean element should be [typeName propertyName].";
       msg = msg + " But: element=" + element + " srcFile=" + _outsideSqlFile;
       throw new IllegalStateException(msg);
     }
     // ParameterBean has the "import" clause of language-embedded utility
     final String typeName = prepareDefinedPropertyType(propertyDef, nameIndex);
     final String propertyName = propertyDef.substring(nameIndex + nameDelimiter.length()).trim();
     if (propertyNameTypeMap.containsKey(propertyName)) {
       // means the auto-detected property is found,
       // and it should be overridden
       propertyNameTypeMap.remove(propertyName);
       propertyNameOptionMap.remove(propertyName);
     }
     propertyNameTypeMap.put(propertyName, typeName);
     if (optionDef != null) {
       propertyNameOptionMap.put(propertyName, optionDef);
     }
   }
   final Map<String, Map<String, String>> bqpMap =
       _bqpSetupper.extractBasicBqpMap(createOutsideSqlPackAsOne());
   if (!bqpMap.isEmpty()) {
     final Map<String, String> bqpElementMap = bqpMap.values().iterator().next();
     pmbMetaData.setBqpElementMap(bqpElementMap);
   }
 }