Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright 2014-2015 the original author or authors.
    *
    * 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.
   */
  package org.dbflute.dbmeta;
  
  import java.sql.Time;
  import java.util.Arrays;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
The abstract class of DB meta.

Author(s):
jflute
  
  public abstract class AbstractDBMeta implements DBMeta {
  
      // ===================================================================================
      //                                                                          Definition
      //                                                                          ==========
      
The dummy value for internal map value.
  
      protected static final Object DUMMY_VALUE = new Object();
  
      // ===================================================================================
      //                                                                           Attribute
      //                                                                           =========
      // -----------------------------------------------------
      //                                  Information Resource
      //                                  --------------------
      // lazy-initialized at corresponding getters
      private volatile List<ColumnInfo_columnInfoList;
      private volatile StringKeyMap<ColumnInfo_columnInfoFlexibleMap;
      private volatile PrimaryInfo _primaryInfo;
      private volatile List<UniqueInfo_uniqueInfoList;
      private volatile List<ForeignInfo_foreignInfoList;
      private volatile Map<StringForeignInfo_foreignInfoFlexibleMap;
      private volatile Map<IntegerForeignInfo_foreignInfoRelationNoKeyMap;
      private volatile List<ReferrerInfo_referrerInfoList;
      private volatile Map<StringReferrerInfo_referrerInfoFlexibleMap;
  
      // ===================================================================================
      //                                                             Resource Initialization
      //                                                             =======================
     protected void initializeInformationResource() { // for instance initializer of subclass.
         getColumnInfoList(); // initialize the list of column information
         getColumnInfoFlexibleMap(); // initialize the flexible map of column information
         if (hasPrimaryKey()) {
             getPrimaryInfo(); // initialize the primary unique information
         }
 
         // these should not be initialized here
         // because the problem 'cyclic reference' occurred 
         // so these are initialized as lazy
         //getForeignInfoList();
         //getForeignInfoFlexibleMap();
         //getReferrerInfoList();
         //getReferrerInfoFlexibleMap();
     }
 
     // ===================================================================================
     //                                                                    Property Gateway
     //                                                                    ================
     // -----------------------------------------------------
     //                                       Column Property
     //                                       ---------------
     // old style for 1.0.x
     //protected void setupEpg(Map<String, PropertyGateway> propertyGatewayMap, PropertyGateway gateway, String propertyName) {
     //    propertyGatewayMap.put(propertyName, gateway); // the map should be plain map for performance
     //}
 
     protected void setupEpg(Map<StringPropertyGatewaypropertyGatewayMapPropertyReader readerPropertyWriter writer,
             String propertyName) {
         final DelegatingPropertyGateway gateway = new DelegatingPropertyGateway(readerwriter);
         propertyGatewayMap.put(propertyNamegateway); // the map should be plain map for performance
     }
 
     public PropertyGateway findPropertyGateway(String propertyName) {
         return null// should be overridden
     }
 
     protected <ENTITY extends EntityPropertyGateway doFindEpg(Map<StringPropertyGatewaypropertyGatewayMapString propertyName) {
         return propertyGatewayMap.get(propertyName);
     }
 
     // -----------------------------------------------------
     //                                      Foreign Property
     //                                      ----------------
     // old style for 1.0.x
     //protected void setupEfpg(Map<String, PropertyGateway> propertyGatewayMap, PropertyGateway gateway, String foreignPropertyName) {
     //    propertyGatewayMap.put(foreignPropertyName, gateway); // the map should be plain map for performance
     //}
 
     protected void setupEfpg(Map<StringPropertyGatewaypropertyGatewayMapPropertyReader readerPropertyWriter writer,
             String foreignPropertyName) {
         final DelegatingPropertyGateway gateway = new DelegatingPropertyGateway(readerwriter);
         propertyGatewayMap.put(foreignPropertyNamegateway); // the map should be plain map for performance
     }
 
     public PropertyGateway findForeignPropertyGateway(String propertyName) {
         return null// might be overridden
     }
 
     protected <ENTITY extends EntityPropertyGateway doFindEfpg(Map<StringPropertyGatewaypropertyGatewayMapString foreignPropertyName) {
         return propertyGatewayMap.get(foreignPropertyName);
     }
 
     // -----------------------------------------------------
     //                                       Write Converter
     //                                       ---------------
     // these are static to avoid the FindBugs headache
     // (implementations of PropertyGateway can be static class)
     protected static void ccls(Entity entityColumnInfo columnInfoObject code) { // checkClassification
         // old style, for compatibility, check only on entity after Java8
         if (code == null) {
             return// no check null value which means no existence on DB
         }
         final ClassificationMeta meta = columnInfo.getClassificationMeta();
         if (meta == null) { // no way (just in case)
             return;
         }
         final ClassificationUndefinedHandlingType undefinedHandlingType = meta.undefinedHandlingType();
         if (!undefinedHandlingType.isChecked()) { // basically no way (not called if no check)
             return;
         }
         final Classification classification = gcls(entitycolumnInfocode);
         if (classification == null) {
             final String tableDbName = columnInfo.getDBMeta().getTableDbName();
             final String columnDbName = columnInfo.getColumnDbName();
             final boolean allowedByOption = entity.myundefinedClassificationAccessAllowed();
             FunCustodial.handleUndefinedClassificationCode(tableDbNamecolumnDbNamemetacodeallowedByOption);
         }
     }
 
     protected static Classification gcls(Entity entityColumnInfo columnInfoObject code) { // getClassification
         if (code == null) {
             return null;
         }
         final ClassificationMeta meta = columnInfo.getClassificationMeta();
         if (meta == null) { // no way (just in case)
             return null;
         }
         return meta.codeOf(code);
     }
 
     protected static Integer cti(Object value) { // convertToInteger
         return DfTypeUtil.toInteger(value);
     }
 
     protected static Long ctl(Object value) { // convertToLong
         return DfTypeUtil.toLong(value);
     }
 
     protected static BigDecimal ctb(Object value) { // convertToBigDecimal
         return DfTypeUtil.toBigDecimal(value);
     }
 
     @SuppressWarnings("unchecked")
     protected static <NUMBER extends Number> NUMBER ctn(Object valueClass<NUMBER> type) { // convertToNumber
         return (NUMBER) DfTypeUtil.toNumber(valuetype);
     }
 
     protected static LocalDate ctld(Object value) { // convertToLocalDate
         return DfTypeUtil.toLocalDate(value);
     }
 
     protected static LocalDateTime ctldt(Object value) { // convertToLocalDateTime
         return DfTypeUtil.toLocalDateTime(value);
     }
 
     protected static LocalTime ctlt(Object value) { // convertToLocalTime
         return DfTypeUtil.toLocalTime(value);
     }
 
     protected static Date ctdt(Object value) { // convertToDate
         return DfTypeUtil.toDate(value);
     }
 
     protected static Timestamp cttp(Object value) { // convertToTimestamp
         return DfTypeUtil.toTimestamp(value);
     }
 
     protected static Time cttm(Object value) { // convertToTime
         return DfTypeUtil.toTime(value);
     }
 
     // ===================================================================================
     //                                                                          Table Info
     //                                                                          ==========
     // these methods is expected to override if it needs
     public String getTableAlias() {
         return null;
     }
 
     public String getTableComment() {
         return null;
     }
 
     // ===================================================================================
     //                                                                         Column Info
     //                                                                         ===========
     
 
     public boolean hasColumn(String columnFlexibleName) {
         assertStringNotNullAndNotTrimmedEmpty("columnFlexibleName"columnFlexibleName);
         return getColumnInfoFlexibleMap().containsKey(columnFlexibleName);
     }

    
 
     public ColumnInfo findColumnInfo(String columnFlexibleName) {
         assertStringNotNullAndNotTrimmedEmpty("columnFlexibleName"columnFlexibleName);
         final ColumnInfo columnInfo = getColumnInfoFlexibleMap().get(columnFlexibleName);
         if (columnInfo == null) {
             throwDBMetaNotFoundException("The column info was not found.""Column"columnFlexibleName);
         }
         return columnInfo;
     }
 
     protected ColumnInfo cci(String columnDbNameString columnSqlNameString columnSynonymString columnAlias // column name
             , Class<?> objectNativeTypeString propertyNameClass<?> propertyAccessType // property info
             , boolean primaryboolean autoIncrementboolean notNull // column basic check
             , String columnDbTypeInteger columnSizeInteger decimalDigitsString defaultValue // column type
             , boolean commonColumnOptimisticLockType optimisticLockTypeString columnComment // column others
             , String foreignListExpString referrerListExp // relation property
             , ClassificationMeta classificationMetaboolean canBeNullObject // various info
     ) { // createColumnInfo()
         final Class<?> realPt = chooseColumnPropertyAccessType(objectNativeTypepropertyNamepropertyAccessType);
         final String delimiter = ",";
         List<StringforeignPropList = null;
         if (foreignListExp != null && foreignListExp.trim().length() > 0) {
             foreignPropList = splitListTrimmed(foreignListExpdelimiter);
         }
         List<StringreferrerPropList = null;
         if (referrerListExp != null && referrerListExp.trim().length() > 0) {
             referrerPropList = splitListTrimmed(referrerListExpdelimiter);
         }
         final PropertyMethodFinder propertyMethodFinder = createColumnPropertyMethodFinder();
         return new ColumnInfo(thiscolumnDbNamecolumnSqlNamecolumnSynonymcolumnAliasobjectNativeTypepropertyNamerealPt,
                 primaryautoIncrementnotNullcolumnDbTypecolumnSizedecimalDigitsdefaultValuecommonColumnoptimisticLockType,
                 columnCommentforeignPropListreferrerPropListclassificationMetacanBeNullObjectpropertyMethodFinder);
     }
 
     protected Class<?> chooseColumnPropertyAccessType(Class<?> objectNativeTypeString propertyNameClass<?> propertyAccessType) {
         return propertyAccessType != null ? propertyAccessType : objectNativeType;
     }
 
         return new PropertyMethodFinder() {
             public Method findReadMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyReadMethod(beanTypepropertyNamepropertyAccessType);
             }
 
             public Method findWriteMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyWriteMethod(beanTypepropertyNamepropertyAccessType);
             }
         };
     }
 
     protected Method findPropertyReadMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
         final String methodName = buildPropertyGetterMethodName(propertyName);
         final Method method = doFindPropertyMethod(beanTypemethodNamenew Class<?>[] {});
         if (method == null) {
             String msg = "Not found the read method by the name:";
             msg = msg + " " + beanType.getName() + "#" + methodName + "()";
             throw new IllegalStateException(msg);
         }
         return method;
     }
 
     protected Method findPropertyWriteMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
         final String methodName = buildPropertySetterMethodName(propertyName);
         final Method method = doFindPropertyMethod(beanTypemethodNamenew Class<?>[] { propertyAccessType });
         if (method == null) {
             String msg = "Not found the write method by the name and type:";
             msg = msg + " " + beanType.getName() + "#" + methodName + "(" + propertyAccessType.getName() + ")";
             throw new IllegalStateException(msg);
         }
         return method;
     }
 
     protected String buildPropertyGetterMethodName(String propertyName) {
         return "get" + initCap(propertyName);
     }
 
     protected String buildPropertySetterMethodName(String propertyName) {
         return "set" + initCap(propertyName);
     }
 
     protected Method doFindPropertyMethod(Class<?> clazzString methodNameClass<?>[] argTypes) {
         return DfReflectionUtil.getAccessibleMethod(clazzmethodNameargTypes);
     }

    
 
     public List<ColumnInfogetColumnInfoList() {
         if ( != null) {
             return ;
         }
         synchronized (this) {
             if ( != null) {
                 return ;
             }
              = Collections.unmodifiableList(ccil());
             return ;
         }
     }
 
     protected abstract List<ColumnInfoccil(); // createColumnInfoList()
 
    
Get the flexible map of column information.

Returns:
The flexible map of column information. (NotNull, NotEmpty)
 
     protected Map<StringColumnInfogetColumnInfoFlexibleMap() {
         if ( != null) {
             return ;
         }
         final List<ColumnInfocolumnInfoList = getColumnInfoList();
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             for (ColumnInfo columnInfo : columnInfoList) {
                 columnInfo.diveIntoFlexibleMap();
             }
             return ;
         }
     }
 
     // ===================================================================================
     //                                                                         Unique Info
     //                                                                         ===========
     // -----------------------------------------------------
     //                                           Primary Key
     //                                           -----------
     
 
     public PrimaryInfo getPrimaryInfo() {
         if ( != null) {
             return ;
         }
         synchronized (this) {
             if ( != null) {
                 return ;
             }
              = new PrimaryInfo(cpui());
             return ;
         }
     }
 
     protected abstract UniqueInfo cpui(); // createPrimaryUniqueInfo()
 
    
 
     @SuppressWarnings("deprecation")
     public UniqueInfo getPrimaryUniqueInfo() { // old style
         return getPrimaryInfo().getUniqueInfo();
     }
 
     protected UniqueInfo hpcpui(ColumnInfo uniqueColumnInfo) { // helpCreatePrimaryUniqueInfo()
         return hpcpui(Arrays.asList(uniqueColumnInfo));
     }
 
     protected UniqueInfo hpcpui(List<ColumnInfouniqueColumnInfoList) { // helpCreatePrimaryUniqueInfo()
         return new UniqueInfo(thisuniqueColumnInfoListtrue);
     }

    
 
     public OptionalObject<PrimaryInfosearchPrimaryInfo(Collection<ColumnInfocolumnInfoList) {
         final PrimaryInfo primaryInfo = getPrimaryInfo(); // exception if no PK
         final Set<ColumnInfocolSet = new HashSet<ColumnInfo>(columnInfoList);
         final List<ColumnInfoprimaryColumnList = primaryInfo.getPrimaryColumnList();
         for (ColumnInfo pk : primaryColumnList) {
             if (!colSet.contains(pk)) {
                 return OptionalObject.ofNullable(null, () -> {
                     throwDBMetaNotFoundException("Not found the primary key by the columns""Specified Column"columnInfoList);
                 });
             }
         }
         return OptionalObject.of(primaryInfo);
     }
 
     // -----------------------------------------------------
     //                                        Natural Unique
     //                                        --------------
     
 
     public List<UniqueInfogetUniqueInfoList() {
         if ( != null) {
             return ;
         }
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final Method[] methods = this.getClass().getMethods();
             final List<UniqueInfoworkingList = newArrayListSized(4);
             final String prefix = "uniqueOf";
             final Class<UniqueInforeturnType = UniqueInfo.class;
             for (Method method : methods) {
                 if (method.getName().startsWith(prefix) && returnType.equals(method.getReturnType())) {
                     workingList.add((UniqueInfo) DfReflectionUtil.invoke(methodthisnull));
                 }
             }
              = Collections.unmodifiableList(workingList);
             return ;
         }
     }
 
     protected UniqueInfo hpcui(ColumnInfo uniqueColumnInfo) { // helpCreateUniqueInfo()
         return hpcui(Arrays.asList(uniqueColumnInfo));
     }
 
     protected UniqueInfo hpcui(java.util.List<ColumnInfouniqueColumnInfoList) { // helpCreateUniqueInfo()
         return new UniqueInfo(thisuniqueColumnInfoListfalse);
     }

    
 
     public List<UniqueInfosearchUniqueInfoList(Collection<ColumnInfocolumnInfoList) {
         return doSearchMetaInfoList(columnInfoListgetUniqueInfoList(), info -> {
             return info.getUniqueColumnList();
         });
     }
 
     protected <INFO> List<INFO> doSearchMetaInfoList(Collection<ColumnInfocolumnInfoListList<INFO> infoList,
             Function<INFO, Collection<ColumnInfo>> oneArgLambda) {
         if (infoList.isEmpty()) {
             return DfCollectionUtil.emptyList();
         }
         final Set<ColumnInfospecifiedColSet = new HashSet<ColumnInfo>(columnInfoList);
         final List<INFO> foundInfoList = newArrayListSized(infoList.size());
         for (INFO info : infoList) {
             final Collection<ColumnInfocolumnList = oneArgLambda.apply(info);
             boolean notFound = false;
             for (ColumnInfo metaCol : columnList) {
                 if (!specifiedColSet.contains(metaCol)) {
                     notFound = true;
                     break;
                 }
             }
             if (!notFound) {
                 foundInfoList.add(info);
             }
         }
         return Collections.unmodifiableList(foundInfoList);
     }
 
     // ===================================================================================
     //                                                                       Relation Info
     //                                                                       =============
     
 
     public RelationInfo findRelationInfo(String relationPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("relationPropertyName"relationPropertyName);
         return hasForeign(relationPropertyName) ? findForeignInfo(relationPropertyName) : findReferrerInfo(relationPropertyName);
     }
 
     // -----------------------------------------------------
     //                                       Foreign Element
     //                                       ---------------
     
 
     public boolean hasForeign(String foreignPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("foreignPropertyName"foreignPropertyName);
         return getForeignInfoFlexibleMap().containsKey(foreignPropertyName);
     }

    
 
     public DBMeta findForeignDBMeta(String foreignPropertyName) {
         return findForeignInfo(foreignPropertyName).getForeignDBMeta();
     }

    
 
     public ForeignInfo findForeignInfo(String foreignPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("foreignPropertyName"foreignPropertyName);
         final ForeignInfo foreignInfo = getForeignInfoFlexibleMap().get(foreignPropertyName);
         if (foreignInfo == null) {
             throwDBMetaNotFoundException("The foreign info was not found.""Foreign Property"foreignPropertyName);
         }
         return foreignInfo;
     }

    
 
     public ForeignInfo findForeignInfo(int relationNo) {
         final ForeignInfo foreignInfo = getForeignInfoRelationNoKeyMap().get(relationNo);
         if (foreignInfo == null) {
             throwDBMetaNotFoundException("The foreign info was not found.""Relation No"relationNo);
         }
         return foreignInfo;
     }
 
     protected ForeignInfo cfi(String constraintNameString foreignPropertyName // relation name
             , DBMeta localDbmDBMeta foreignDbm // DB meta
             , Map<ColumnInfoColumnInfolocalForeignColumnInfoMapint relationNoClass<?> propertyAccessType // relation attribute
             , boolean oneToOneboolean bizOneToOneboolean referrerAsOneboolean additionalFK // relation type
             , String fixedConditionList<StringdynamicParameterListboolean fixedInline // fixed condition
             , String reversePropertyNameboolean canBeNullObject // various info
     ) { // createForeignInfo()
         final Class<?> realPt = chooseForeignPropertyAccessType(foreignDbmpropertyAccessType);
         final PropertyMethodFinder propertyMethodFinder = createForeignPropertyMethodFinder();
         return new ForeignInfo(constraintNameforeignPropertyNamelocalDbmforeignDbmlocalForeignColumnInfoMaprelationNorealPt,
                 oneToOnebizOneToOnereferrerAsOneadditionalFKfixedConditiondynamicParameterListfixedInlinereversePropertyName,
                 canBeNullObjectpropertyMethodFinder);
     }
 
     protected Class<?> chooseForeignPropertyAccessType(DBMeta foreignDbmClass<?> specifiedType) {
         return specifiedType != null ? specifiedType : foreignDbm.getEntityType(); // basically default, or specified Optional
     }
 
         return new PropertyMethodFinder() {
             public Method findReadMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyReadMethod(beanTypepropertyNamepropertyAccessType);
             }
 
             public Method findWriteMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyWriteMethod(beanTypepropertyNamepropertyAccessType);
             }
         };
     }

    
 
     public List<ForeignInfogetForeignInfoList() {
         if ( != null) {
             return ;
         }
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final Method[] methods = this.getClass().getMethods();
             final List<ForeignInfoworkingList = newArrayList();
             final String prefix = "foreign";
             final Class<ForeignInforeturnType = ForeignInfo.class;
             for (Method method : methods) {
                 if (method.getName().startsWith(prefix) && returnType.equals(method.getReturnType())) {
                     workingList.add((ForeignInfo) DfReflectionUtil.invoke(methodthisnull));
                 }
             }
              = Collections.unmodifiableList(workingList);
             return ;
         }
     }

    
Get the flexible map of foreign information.

Returns:
The flexible map of foreign information. (NotNull, EmptyAllowed, ReadOnly)
 
     protected Map<StringForeignInfogetForeignInfoFlexibleMap() {
         if ( != null) {
             return ;
         }
         final List<ForeignInfoforeignInfoList = getForeignInfoList();
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final StringKeyMap<ForeignInfomap = createFlexibleConcurrentMap();
             for (ForeignInfo foreignInfo : foreignInfoList) {
                 map.put(foreignInfo.getForeignPropertyName(), foreignInfo);
             }
              = Collections.unmodifiableMap(map);
             return ;
         }
     }

    
Get the relation-no key map of foreign information.

Returns:
The unordered map of foreign information. (NotNull, EmptyAllowed, ReadOnly)
 
         if ( != null) {
             return ;
         }
         final List<ForeignInfoforeignInfoList = getForeignInfoList();
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final Map<IntegerForeignInfomap = newConcurrentHashMap();
             for (ForeignInfo foreignInfo : foreignInfoList) {
                 map.put(foreignInfo.getRelationNo(), foreignInfo);
             }
              = Collections.unmodifiableMap(map);
             return ;
         }
     }

    
 
     public List<ForeignInfosearchForeignInfoList(Collection<ColumnInfocolumnInfoList) {
         return doSearchMetaInfoList(columnInfoListgetForeignInfoList(), info -> {
             return info.getLocalForeignColumnInfoMap().keySet();
         });
     }
 
     // -----------------------------------------------------
     //                                      Referrer Element
     //                                      ----------------
     
 
     public boolean hasReferrer(String referrerPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("referrerPropertyName"referrerPropertyName);
         return getReferrerInfoFlexibleMap().containsKey(referrerPropertyName);
     }

    
 
     public DBMeta findReferrerDBMeta(String referrerPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("referrerPropertyName"referrerPropertyName);
         return findReferrerInfo(referrerPropertyName).getReferrerDBMeta();
     }

    
 
     public ReferrerInfo findReferrerInfo(String referrerPropertyName) {
         assertStringNotNullAndNotTrimmedEmpty("referrerPropertyName"referrerPropertyName);
         final ReferrerInfo referrerInfo = getReferrerInfoFlexibleMap().get(referrerPropertyName);
         if (referrerInfo == null) {
             throwDBMetaNotFoundException("The referrer info was not found.""Referrer Property"referrerPropertyName);
         }
         return referrerInfo;
     }
 
     protected ReferrerInfo cri(String constraintNameString referrerPropertyName // relation name
             , DBMeta localDbmDBMeta referrerDbm // DB meta
             , Map<ColumnInfoColumnInfolocalReferrerColumnInfoMap // relation attribute
             , boolean oneToOneString reversePropertyName // relation type and various info
     ) { // createReferrerInfo()
         final Class<?> propertyAccessType = chooseReferrerPropertyAccessType(referrerDbmoneToOne);
         final PropertyMethodFinder propertyMethodFinder = createReferrerPropertyMethodFinder();
         return new ReferrerInfo(constraintNamereferrerPropertyNamelocalDbmreferrerDbmlocalReferrerColumnInfoMap,
                 propertyAccessTypeoneToOnereversePropertyNamepropertyMethodFinder);
     }
 
     protected Class<?> chooseReferrerPropertyAccessType(DBMeta referrerDbmboolean oneToOne) {
         final Class<?> propertyType;
         if (oneToOne) { // basically no way
             propertyType = referrerDbm.getEntityType();
         } else {
             final Class<?> listType = getReferrerPropertyListType();
             propertyType = listType != null ? listType : List.class;
         }
         return propertyType;
     }

    
Get the list type of referrer property in entity.

Returns:
The class instance of list type. (NullAllowed: if null, Java's List used as default)
 
     protected Class<?> getReferrerPropertyListType() { // might be overridden
         return null// as default (List)
     }
 
         return new PropertyMethodFinder() {
             public Method findReadMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyReadMethod(beanTypepropertyNamepropertyAccessType);
             }
 
             public Method findWriteMethod(Class<?> beanTypeString propertyNameClass<?> propertyAccessType) {
                 return findPropertyWriteMethod(beanTypepropertyNamepropertyAccessType);
             }
         };
     }

    
 
     public List<ReferrerInfogetReferrerInfoList() {
         if ( != null) {
             return ;
         }
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final Method[] methods = this.getClass().getMethods();
             final List<ReferrerInfoworkingList = newArrayList();
             final String prefix = "referrer";
             final Class<ReferrerInforeturnType = ReferrerInfo.class;
             for (Method method : methods) {
                 if (method.getName().startsWith(prefix) && returnType.equals(method.getReturnType())) {
                     workingList.add((ReferrerInfo) DfReflectionUtil.invoke(methodthisnull));
                 }
             }
              = Collections.unmodifiableList(workingList);
             return ;
         }
     }

    
Get the flexible map of referrer information.

Returns:
The flexible map of referrer information. (NotNull, EmptyAllowed, ReadOnly)
 
         if ( != null) {
             return ;
         }
         final List<ReferrerInforeferrerInfoList = getReferrerInfoList();
         synchronized (this) {
             if ( != null) {
                 return ;
             }
             final StringKeyMap<ReferrerInfomap = createFlexibleConcurrentMap();
             for (ReferrerInfo referrerInfo : referrerInfoList) {
                 map.put(referrerInfo.getReferrerPropertyName(), referrerInfo);
             }
              = Collections.unmodifiableMap(map);
             return ;
         }
     }

    
 
     public List<ReferrerInfosearchReferrerInfoList(Collection<ColumnInfocolumnInfoList) {
         return doSearchMetaInfoList(columnInfoListgetReferrerInfoList(), info -> {
             return info.getLocalReferrerColumnInfoMap().keySet();
         });
     }
 
     // -----------------------------------------------------
     //                                          Common Logic
     //                                          ------------
     protected String buildRelationInfoGetterMethodNameInitCap(String targetNameString relationPropertyName) {
         return targetName + relationPropertyName.substring(0, 1).toUpperCase() + relationPropertyName.substring(1);
     }
 
     // ===================================================================================
     //                                                                        Various Info
     //                                                                        ============
     // These methods is expected to override if it needs.
     public boolean hasIdentity() {
         return false;
     }
 
     public boolean hasSequence() {
         return false;
     }
 
     public String getSequenceName() {
         return null;
     }
 
     public String getSequenceNextValSql() {
         if (!hasSequence()) {
             return null;
         }
     }
 
     public Integer getSequenceIncrementSize() {
         return null;
     }
 
     public Integer getSequenceCacheSize() {
         return null;
     }
 
     public boolean hasOptimisticLock() {
         return hasVersionNo() || hasUpdateDate();
     }
 
     public boolean hasVersionNo() {
         return false;
     }
 
     public ColumnInfo getVersionNoColumnInfo() {
         return null;
     }
 
     public boolean hasUpdateDate() {
         return false;
     }
 
     public ColumnInfo getUpdateDateColumnInfo() {
         return null;
     }
 
     public boolean hasCommonColumn() {
         return false;
     }
 
     public List<ColumnInfogetCommonColumnInfoList() {
         return DfCollectionUtil.emptyList();
     }
 
         return DfCollectionUtil.emptyList();
     }
 
         return DfCollectionUtil.emptyList();
     }
 
     // ===================================================================================
     //                                                                   Map Communication
     //                                                                   =================
     // -----------------------------------------------------
     //                                                Accept
     //                                                ------
     protected <ENTITY extends Entityvoid doAcceptPrimaryKeyMap(ENTITY entityMap<String, ? extends ObjectprimaryKeyMap) {
         assertObjectNotNull("entity"entity);
         if (primaryKeyMap == null || primaryKeyMap.isEmpty()) {
             String msg = "The argument 'primaryKeyMap' should not be null or empty: primaryKeyMap=" + primaryKeyMap;
             throw new IllegalArgumentException(msg);
         }
         doConvertToEntity(entityprimaryKeyMaptrue);
     }
 
     protected <ENTITY extends Entityvoid doAcceptAllColumnMap(ENTITY entityMap<String, ? extends ObjectallColumnMap) {
         assertObjectNotNull("entity"entity);
         if (allColumnMap == null || allColumnMap.isEmpty()) {
             String msg = "The argument 'allColumnMap' should not be null or empty: allColumnMap=" + allColumnMap;
             throw new IllegalArgumentException(msg);
         }
         doConvertToEntity(entityallColumnMapfalse);
     }
 
     protected <ENTITY extends Entityvoid doConvertToEntity(ENTITY entityMap<String, ? extends ObjectcolumnMapboolean pkOnly) {
         final List<ColumnInfocolumnInfoList = pkOnly ? getPrimaryInfo().getPrimaryColumnList() : getColumnInfoList();
         final MetaHandlingMapToEntityMapper mapper = createMetaHandlingMapToEntityMapper(columnMap);
         mapper.mappingToEntity(entitycolumnMapcolumnInfoList);
     }
 
     protected MetaHandlingMapToEntityMapper createMetaHandlingMapToEntityMapper(Map<String, ? extends ObjectcolumnMap) {
         return new MetaHandlingMapToEntityMapper(columnMap);
     }
 
     // -----------------------------------------------------
     //                                               Extract
     //                                               -------
     protected Map<StringObjectdoExtractPrimaryKeyMap(Entity entity) {
         assertObjectNotNull("entity"entity);
         return doConvertToColumnValueMap(entitytrue);
     }
 
     protected Map<StringObjectdoExtractAllColumnMap(Entity entity) {
         assertObjectNotNull("entity"entity);
         return doConvertToColumnValueMap(entityfalse);
     }
 
     protected Map<StringObjectdoConvertToColumnValueMap(Entity entityboolean pkOnly) {
         final List<ColumnInfocolumnInfoList = pkOnly ? getPrimaryInfo().getPrimaryColumnList() : getColumnInfoList();
         final MetaHandlingEntityToMapMapper mapper = createMetaHandlingEntityToMapMapper(entity);
         return mapper.mappingToColumnValueMap(columnInfoList);
     }
 
         return new MetaHandlingEntityToMapMapper(entity);
     }
 
     // ===================================================================================
     //                                                                       Assist Helper
     //                                                                       =============
     @SuppressWarnings("unchecked")
     protected <ENTITY> ENTITY downcast(Entity entity) {
         checkDowncast(entity);
         return (ENTITY) entity;
     }
 
     protected void checkDowncast(Entity entity) {
         assertObjectNotNull("entity"entity);
         final Class<?> entityType = getEntityType();
         final Class<?> targetType = entity.getClass();
         if (!entityType.isAssignableFrom(targetType)) {
             final String titleName = DfTypeUtil.toClassTitle(entityType);
             String msg = "The entity should be " + titleName + " but it was: " + targetType;
             throw new IllegalStateException(msg);
         }
     }
 
     protected Map<StringStringsetupKeyToLowerMap(boolean dbNameKey) {
         final Map<StringStringmap;
         if (dbNameKey) {
             map = newConcurrentHashMap(getTableDbName().toLowerCase(), getTablePropertyName());
         } else {
             map = newConcurrentHashMap(getTablePropertyName().toLowerCase(), getTableDbName());
         }
         final Method[] methods = this.getClass().getMethods();
         final String columnInfoMethodPrefix = "column";
         try {
             for (Method method : methods) {
                 final String name = method.getName();
                 if (!name.startsWith(columnInfoMethodPrefix)) {
                     continue;
                 }
                 final ColumnInfo columnInfo = (ColumnInfomethod.invoke(this);
                 final String dbName = columnInfo.getColumnDbName();
                 final String propertyName = columnInfo.getPropertyName();
                 if (dbNameKey) {
                     map.put(dbName.toLowerCase(), propertyName);
                 } else {
                     map.put(propertyName.toLowerCase(), dbName);
                 }
             }
             return Collections.unmodifiableMap(map);
         } catch (Exception e) {
             throw new IllegalStateException(e);
         }
     }
 
     protected void throwDBMetaNotFoundException(String noticeString keyNameObject value) {
         final ExceptionMessageBuilder br = new ExceptionMessageBuilder();
         br.addNotice(notice);
         br.addItem("Table");
         br.addElement(getTableDbName());
         br.addItem(keyName);
         br.addElement(value);
         final String msg = br.buildExceptionMessage();
         throw new DBMetaNotFoundException(msg);
     }
 
     // ===================================================================================
     //                                                                      General Helper
     //                                                                      ==============
     // -----------------------------------------------------
     //                                       String Handling
     //                                       ---------------
     protected final String replaceString(String textString fromTextString toText) {
         return Srl.replace(textfromTexttoText);
     }
 
     protected final List<StringsplitListTrimmed(String strString delimiter) {
         return Srl.splitListTrimmed(strdelimiter);
     }
 
     protected final String initCap(String str) {
         return Srl.initCap(str);
     }
 
     protected final String initUncap(String str) {
         return Srl.initUncap(str);
     }
 
     protected final String ln() {
         return DBFluteSystem.ln();
     }
 
     // -----------------------------------------------------
     //                                  Collection Generator
     //                                  --------------------
     protected <KEY, VALUE> HashMap<KEY, VALUE> newHashMap() {
         return DfCollectionUtil.newHashMap();
     }
 
     protected <KEY, VALUE> ConcurrentHashMap<KEY, VALUE> newConcurrentHashMap() {
         return DfCollectionUtil.newConcurrentHashMap();
     }
 
     protected <KEY, VALUE> ConcurrentHashMap<KEY, VALUE> newConcurrentHashMap(KEY key, VALUE value) {
         final ConcurrentHashMap<KEY, VALUE> map = newConcurrentHashMap();
         map.put(keyvalue);
        return map;
    }
    protected <KEY, VALUE> LinkedHashMap<KEY, VALUE> newLinkedHashMap() {
        return DfCollectionUtil.newLinkedHashMap();
    }
    protected <KEY, VALUE> LinkedHashMap<KEY, VALUE> newLinkedHashMap(KEY key, VALUE value) {
        final LinkedHashMap<KEY, VALUE> map = newLinkedHashMap();
        map.put(keyvalue);
        return map;
    }
    protected <KEY, VALUE> LinkedHashMap<KEY, VALUE> newLinkedHashMapSized(int size) {
        return DfCollectionUtil.newLinkedHashMapSized(size);
    }
    protected <ELEMENT> ArrayList<ELEMENT> newArrayList() {
        return DfCollectionUtil.newArrayList();
    }