OSDN Git Service

e8e2bd03361f1079a084655025db2abe535aaaf5
[ea2ddl/ea2ddl.git] / ea2ddl-gen / dbflute / templates / om / java / allcommon / cbean / AbstractConditionQuery.vm
1 ${database.allClassCopyright}package ${glPackageBaseCommonCBean};\r
2 \r
3 #set ($myClassName = "${glConditionQueryAbstractName}")\r
4 import java.util.Collection;\r
5 import java.util.List;\r
6 import java.util.ArrayList;\r
7 import java.util.Map;\r
8 import java.util.LinkedHashMap;\r
9 import java.util.Iterator;\r
10 import java.lang.reflect.Method;\r
11 import java.lang.reflect.InvocationTargetException;\r
12 \r
13 import ${glPackageBaseCommonCKey}.${glConditionKeyName};\r
14 import ${glPackageBaseCommonCOption}.${glConditionOptionInterfaceName};\r
15 import ${glPackageBaseCommonCOption}.${glConditionOptionFromToName};\r
16 import ${glPackageBaseCommonCOption}.${glConditionOptionLikeSearchName};\r
17 import ${glPackageBaseCommonCOption}.${glConditionOptionInScopeName};\r
18 import ${glPackageBaseCommonCValue}.${glConditionValueName};\r
19 import ${glPackageBaseCommonDBMeta}.${glDBMetaInterfaceName};\r
20 import ${glPackageBaseCommonDBMeta}.${glDBMetaInstanceHandlerName};\r
21 import ${glPackageBaseCommonSqlClause}.${glSqlClauseName};\r
22 import ${glPackageBaseCommonException}.${glRequiredOptionNotFoundException};\r
23 import ${glPackageBaseCommonUtil}.${glSimpleStringUtil};\r
24 import ${glPackageBaseCommonUtil}.${glSimpleSystemUtil};\r
25 import ${glPackageBaseCommonUtil}.${glTraceViewUtilName};\r
26 \r
27 /**\r
28  * The abstract class of condition-query.\r
29  * @author ${database.ClassAuthor}\r
30  */\r
31 public abstract class ${myClassName} implements ${glConditionQueryInterfaceName} {\r
32 \r
33     // ===================================================================================\r
34     //                                                                          Definition\r
35     //                                                                          ==========\r
36     protected static final ${glConditionKeyName} CK_EQ = ${glConditionKeyName}.CK_EQUAL;\r
37     protected static final ${glConditionKeyName} CK_NE = ${glConditionKeyName}.CK_NOT_EQUAL;\r
38     protected static final ${glConditionKeyName} CK_GE = ${glConditionKeyName}.CK_GREATER_EQUAL;\r
39     protected static final ${glConditionKeyName} CK_GT = ${glConditionKeyName}.CK_GREATER_THAN;\r
40     protected static final ${glConditionKeyName} CK_LE = ${glConditionKeyName}.CK_LESS_EQUAL;\r
41     protected static final ${glConditionKeyName} CK_LT = ${glConditionKeyName}.CK_LESS_THAN;\r
42     protected static final ${glConditionKeyName} CK_PS = ${glConditionKeyName}.CK_PREFIX_SEARCH;\r
43     protected static final ${glConditionKeyName} CK_LS = ${glConditionKeyName}.CK_LIKE_SEARCH;\r
44     protected static final ${glConditionKeyName} CK_INS = ${glConditionKeyName}.CK_IN_SCOPE;\r
45     protected static final ${glConditionKeyName} CK_NINS = ${glConditionKeyName}.CK_NOT_IN_SCOPE;\r
46     protected static final ${glConditionKeyName} CK_ISN = ${glConditionKeyName}.CK_IS_NULL;\r
47     protected static final ${glConditionKeyName} CK_ISNN = ${glConditionKeyName}.CK_IS_NOT_NULL;\r
48 \r
49     /** Condition value for DUMMY. */\r
50     protected static final ${glConditionValueName} DUMMY_CONDITION_VALUE = new ${glConditionValueName}();\r
51 \r
52     /** Object for DUMMY. */\r
53     protected static final Object DUMMY_OBJECT = new Object();\r
54     \r
55     /** The property of condition-query. */\r
56     protected static final String CQ_PROPERTY = "conditionQuery";\r
57 \r
58     // ===================================================================================\r
59     //                                                                           Attribute\r
60     //                                                                           =========\r
61     /** SQL clause. */\r
62     protected final ${glSqlClauseName} _sqlClause;\r
63 \r
64     /** My alias name. */\r
65     protected final String _aliasName;\r
66 \r
67     /** The level of nest. */\r
68     protected final int _nestLevel;\r
69     \r
70     /** The level of subQuery. */\r
71     protected int _subQueryLevel;\r
72 \r
73     // -----------------------------------------------------\r
74     //                                          Foreign Info\r
75     //                                          ------------\r
76     /** The property name of foreign. */\r
77     protected String _foreignPropertyName;\r
78 \r
79     /** The path of relation. */\r
80     protected String _relationPath;\r
81 \r
82     /** The query of child. */\r
83     protected final ${glConditionQueryInterfaceName} _childQuery;\r
84 \r
85     // -----------------------------------------------------\r
86     //                                                Inline\r
87     //                                                ------\r
88     /** Is it the inline for on-clause. (Property for Inline Only) */\r
89     protected boolean _onClauseInline;\r
90     \r
91     // ===================================================================================\r
92     //                                                                         Constructor\r
93     //                                                                         ===========\r
94     /**\r
95      * Constructor.\r
96      * @param childQuery Child query. (Nullable: If null, this is base instance.)\r
97      * @param sqlClause SQL clause instance. (NotNull)\r
98      * @param aliasName My alias name. (NotNull)\r
99      * @param nestLevel Nest level.\r
100      */\r
101     public ${myClassName}(${glConditionQueryInterfaceName} childQuery, ${glSqlClauseName} sqlClause, String aliasName, int nestLevel) {\r
102         _childQuery = childQuery;\r
103         _sqlClause = sqlClause;\r
104         _aliasName = aliasName;\r
105         _nestLevel = nestLevel;\r
106     }\r
107 \r
108     // ===================================================================================\r
109     //                                                                  Important Accessor\r
110     //                                                                  ==================\r
111     /**\r
112      * Get child query.\r
113      * @return Child query. (Nullable)\r
114      */\r
115     public ${glConditionQueryInterfaceName} getChildQuery() {\r
116         return _childQuery;\r
117     }\r
118 \r
119     /**\r
120      * Get sql clause.\r
121      * @return Sql clause. (NotNull)\r
122      */\r
123     public ${glSqlClauseName} getSqlClause() {\r
124         return _sqlClause;\r
125     }\r
126 \r
127     /**\r
128      * Get alias name.\r
129      * @return Alias name. (NotNull)\r
130      */\r
131     public String getAliasName() {\r
132         return _aliasName;\r
133     }\r
134 \r
135     /**\r
136      * Get nest level.\r
137      * @return Nest level.\r
138      */\r
139     public int getNestLevel() {\r
140         return _nestLevel;\r
141     }\r
142 \r
143     /**\r
144      * Get next nest level.\r
145      * @return Next nest level.\r
146      */\r
147     public int getNextNestLevel() {\r
148         return _nestLevel+1;\r
149     }\r
150 \r
151     /**\r
152      * Is base query?\r
153      * @param query Condition query. (NotNull)\r
154      * @return Determination.\r
155      */\r
156     public boolean isBaseQuery(${glConditionQueryInterfaceName} query) {\r
157         return (query.getChildQuery() == null);\r
158     }\r
159 \r
160     /**\r
161      * Get the level of subQuery.\r
162      * @return The level of subQuery.\r
163      */\r
164     public int getSubQueryLevel() {\r
165         return _subQueryLevel;\r
166     }\r
167     \r
168     // -----------------------------------------------------\r
169     //                                             Real Name\r
170     //                                             ---------\r
171     /**\r
172      * Get real alias name(that has nest level mark).\r
173      * @return Real alias name.\r
174      */\r
175     public String getRealAliasName() {\r
176         return getAliasName();\r
177     }\r
178 \r
179     /**\r
180      * Get real column name(with real alias name).\r
181      * @param columnName Column name without alias name. This should not contain comma. (NotNull)\r
182      * @return Real column name.\r
183      */\r
184     public String getRealColumnName(String columnName) {\r
185         assertColumnName(columnName);\r
186         return buildRealColumnName(getRealAliasName(), columnName);\r
187     }\r
188 \r
189     /**\r
190      * Build real column name.\r
191      * @param aliasName Alias name. (NotNull)\r
192      * @param columnName Column name. (NotNull)\r
193      * @return Real column name. (NotNull)\r
194      */\r
195     protected String buildRealColumnName(String aliasName, String columnName) {\r
196         return aliasName + "." + columnName;\r
197     }\r
198 \r
199     // -----------------------------------------------------\r
200     //                                          Foreign Info\r
201     //                                          ------------\r
202     public String getForeignPropertyName() {\r
203         return _foreignPropertyName;\r
204     }\r
205 \r
206     public void xsetForeignPropertyName(String foreignPropertyName) {\r
207         this._foreignPropertyName = foreignPropertyName;\r
208     }\r
209 \r
210     public String getRelationPath() {\r
211         return _relationPath;\r
212     }\r
213 \r
214     public void xsetRelationPath(String relationPath) {\r
215         this._relationPath = relationPath;\r
216     }\r
217 \r
218     // -----------------------------------------------------\r
219     //                                                Inline\r
220     //                                                ------\r
221     public void xsetOnClauseInline(boolean onClauseInline) {\r
222         _onClauseInline = onClauseInline;\r
223     }\r
224     \r
225     // ===================================================================================\r
226     //                                                                            Location\r
227     //                                                                            ========\r
228     /**\r
229      * Get location.\r
230      * @param columnPropertyName Column property name.\r
231      * @param key Condition key.\r
232      * @return Next nest level.\r
233      */\r
234     protected String getLocation(String columnPropertyName, ${glConditionKeyName} key) {\r
235         return getLocationBase(columnPropertyName) + "." + key.getConditionKey();\r
236     }\r
237 \r
238     protected String getLocationBase() {\r
239         final StringBuffer sb = new StringBuffer();\r
240         ${glConditionQueryInterfaceName} query = this;\r
241         while (true) {\r
242             if (query.isBaseQuery(query)) {\r
243                 sb.insert(0, CQ_PROPERTY + ".");\r
244                 break;\r
245             } else {\r
246                 final String foreignPropertyName = query.getForeignPropertyName();\r
247                 if (foreignPropertyName == null) {\r
248                     String msg = "The foreignPropertyName of the query should not be null:";\r
249                     msg = msg + " query=" + query;\r
250                     throw new IllegalStateException(msg);\r
251                 }\r
252                 sb.insert(0, CQ_PROPERTY + initCap(foreignPropertyName) + ".");\r
253             }\r
254             query = query.getChildQuery();\r
255         }\r
256         return sb.toString();\r
257     }\r
258 \r
259     protected String getLocationBase(String columnPropertyName) {\r
260         return getLocationBase() + columnPropertyName;\r
261     }\r
262 \r
263     // ===================================================================================\r
264     //                                                                         Union Query\r
265     //                                                                         ===========\r
266     /** The map of union query. */\r
267     protected Map<String, ${glConditionQueryInterfaceName}> _unionQueryMap;\r
268 \r
269     /**\r
270      * Get the map of union query.\r
271      * @return The map of union query. (NotNull)\r
272      */\r
273     public Map<String, ${glConditionQueryInterfaceName}> getUnionQueryMap() {// for Internal\r
274         if (_unionQueryMap == null) {\r
275             _unionQueryMap = new LinkedHashMap<String, ${glConditionQueryInterfaceName}>();\r
276         }\r
277         return _unionQueryMap;\r
278     }\r
279 \r
280     /**\r
281      * Set union query. {Internal}\r
282      * @param unionQuery Union query. (NotNull)\r
283      */\r
284     public void xsetUnionQuery(${glConditionQueryInterfaceName} unionQuery) {\r
285         xsetupUnion(unionQuery, false, getUnionQueryMap());\r
286     }\r
287 \r
288     /** The map of union all query. */\r
289     protected Map<String, ${glConditionQueryInterfaceName}> _unionAllQueryMap;\r
290 \r
291     /**\r
292      * Get the map of union all query.\r
293      * @return The map of union all query. (NotNull)\r
294      */\r
295     public Map<String, ${glConditionQueryInterfaceName}> getUnionAllQueryMap() {// for Internal\r
296         if (_unionAllQueryMap == null) {\r
297             _unionAllQueryMap = new LinkedHashMap<String, ${glConditionQueryInterfaceName}>();\r
298         }\r
299         return _unionAllQueryMap;\r
300     }\r
301 \r
302     /**\r
303      * Set union all query. {Internal}\r
304      * @param unionAllQuery Union all query. (NotNull)\r
305      */\r
306     public void xsetUnionAllQuery(${glConditionQueryInterfaceName} unionAllQuery) {\r
307         xsetupUnion(unionAllQuery, true, getUnionAllQueryMap());\r
308     }\r
309 \r
310     protected void xsetupUnion(${glConditionQueryInterfaceName} unionQuery, boolean unionAll, Map<String, ${glConditionQueryInterfaceName}> unionQueryMap) {\r
311         if (unionQuery == null) {\r
312             String msg = "The argument[unionQuery] should not be null.";\r
313             throw new IllegalArgumentException(msg);\r
314         }\r
315         reflectRelationOnUnionQuery(this, unionQuery);// Reflect Relation!\r
316         getSqlClause().copyIncludedSelectColumn(unionQuery.getSqlClause());// Reflect IncludedSelectColumn!\r
317         if (getSqlClause().isFormatClauseEffective()) {\r
318             unionQuery.getSqlClause().makeFormatClauseEffective();// Reflect FormatClause!\r
319         }\r
320         String key = (unionAll ? "unionAllQuery" : "unionQuery") + unionQueryMap.size();\r
321         unionQueryMap.put(key, unionQuery);\r
322         registerUnionQuery(unionQuery, unionAll, (unionAll ? "unionAllQueryMap" : "unionQueryMap") + "." + key);\r
323     }\r
324 \r
325     /**\r
326      * Reflect relation on union query.\r
327      * @param baseQueryAsSuper Base query as super. (NotNull)\r
328      * @param unionQueryAsSuper Union query as super. (NotNull)\r
329      */\r
330     abstract protected void reflectRelationOnUnionQuery(${glConditionQueryInterfaceName} baseQueryAsSuper, ${glConditionQueryInterfaceName} unionQueryAsSuper);\r
331 \r
332     /**\r
333      * Has union query or union all query?\r
334      * @return Determination.\r
335      */\r
336     public boolean hasUnionQueryOrUnionAllQuery() {\r
337         return (_unionQueryMap != null && !_unionQueryMap.isEmpty()) || (_unionAllQueryMap != null && !_unionAllQueryMap.isEmpty());\r
338     }\r
339 \r
340     /**\r
341      * Get the list of union query.\r
342      * @return The list of union query. (NotNull)\r
343      */\r
344     public List<${glConditionQueryInterfaceName}> getUnionQueryList() {\r
345         if (_unionQueryMap == null) { return new ArrayList<${glConditionQueryInterfaceName}>(); }\r
346         return new ArrayList<${glConditionQueryInterfaceName}>(_unionQueryMap.values());\r
347     }\r
348 \r
349     /**\r
350      * Get the list of union all query.\r
351      * @return The list of union all query. (NotNull)\r
352      */\r
353     public List<${glConditionQueryInterfaceName}> getUnionAllQueryList() {\r
354         if (_unionAllQueryMap == null) { return new ArrayList<${glConditionQueryInterfaceName}>(); }\r
355         return new ArrayList<${glConditionQueryInterfaceName}>(_unionAllQueryMap.values());\r
356     }\r
357 \r
358     // ===================================================================================\r
359     //                                                                            Register\r
360     //                                                                            ========\r
361     // -----------------------------------------------------\r
362     //                                       Include-As-Mine\r
363     //                                       ---------------\r
364     /**\r
365      * Register included-select-column.\r
366      * @param aliasName Alias name. This should not contain comma. (NotNull)\r
367      * @param realColumnName Real column name. This should not contain comma. (NotNull)\r
368      * @deprecated Unsupported!\r
369      */\r
370     protected void registerIncludedSelectColumn(String aliasName, String realColumnName) {\r
371         throw new UnsupportedOperationException();\r
372     }\r
373 \r
374     // -----------------------------------------------------\r
375     //                                                 Query\r
376     //                                                 -----\r
377     protected void registerQuery(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
378                                  , String colName, String capPropName, String uncapPropName) {\r
379         if (key.isValidRegistration(cvalue, value, key.getConditionKey() + " of " + getRealAliasName() + "." + colName)) {\r
380             setupConditionValueAndRegisterWhereClause(key, value, cvalue, colName, capPropName, uncapPropName);\r
381         }\r
382     }\r
383 \r
384     protected void registerQuery(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
385                                  , String colName, String capPropName, String uncapPropName, ${glConditionOptionInterfaceName} option) {\r
386         if (key.isValidRegistration(cvalue, value, key.getConditionKey() + " of " + getRealAliasName() + "." + colName)) {\r
387             setupConditionValueAndRegisterWhereClause(key, value, cvalue, colName, capPropName, uncapPropName, option);\r
388         }\r
389     }\r
390 \r
391     // -----------------------------------------------------\r
392     //                                          FromTo Query\r
393     //                                          ------------\r
394     protected void registerFromToQuery(java.util.Date fromDate, java.util.Date toDate, ${glConditionValueName} cvalue\r
395                                  , String colName, String capPropName, String uncapPropName, ${glConditionOptionFromToName} option) {\r
396         {\r
397             final java.util.Date filteredFromDate = option.filterFromDate(fromDate);\r
398             final ${glConditionKeyName} fromKey = option.getFromDateConditionKey();\r
399             if (fromKey.isValidRegistration(cvalue, filteredFromDate, fromKey.getConditionKey() + " of " + getRealAliasName() + "." + uncapPropName)) {\r
400                 setupConditionValueAndRegisterWhereClause(fromKey, filteredFromDate, cvalue, colName, capPropName, uncapPropName);\r
401             }\r
402         }\r
403         {\r
404             final java.util.Date filteredToDate = option.filterToDate(toDate);\r
405             final ${glConditionKeyName} toKey = option.getToDateConditionKey();\r
406             if (toKey.isValidRegistration(cvalue, filteredToDate, toKey.getConditionKey() + " of " + getRealAliasName() + "." + uncapPropName)) {\r
407                 setupConditionValueAndRegisterWhereClause(toKey, filteredToDate, cvalue, colName, capPropName, uncapPropName);\r
408             }\r
409         }\r
410     }\r
411 \r
412     // -----------------------------------------------------\r
413     //                                      LikeSearch Query\r
414     //                                      ----------------\r
415     @SuppressWarnings("deprecation")\r
416     protected void registerLikeSearchQuery(${glConditionKeyName} key\r
417                                          , String value\r
418                                          , ${glConditionValueName} cvalue\r
419                                          , String colName\r
420                                          , String capPropName\r
421                                          , String uncapPropName\r
422                                          , ${glConditionOptionLikeSearchName} option) {\r
423         final String validationMsg = key.getConditionKey() + " of " + getRealAliasName() + "." + colName;\r
424         if (!key.isValidRegistration(cvalue, value, validationMsg)) {\r
425             return;\r
426         }\r
427         if (option == null) {\r
428             throwLikeSearchOptionNotFoundException(capPropName, value);\r
429             return;// Unreachable!\r
430         }\r
431         if (value == null || !option.isSplit()) {\r
432             // As Normal Condition.\r
433             setupConditionValueAndRegisterWhereClause(key, value, cvalue, colName, capPropName, uncapPropName, option);\r
434             return;\r
435         }\r
436         // - - - - - - - - -\r
437         // Use splitByXxx().\r
438         // - - - - - - - - -\r
439         final String[] strArray = option.generateSplitValueArray(value);\r
440         if (!option.isAsOrSplit()) {\r
441             // As 'and' Condition\r
442             for (int i = 0; i < strArray.length; i++) {\r
443                 final String currentValue = strArray[i];\r
444                 setupConditionValueAndRegisterWhereClause(key, currentValue, cvalue, colName, capPropName, uncapPropName, option);\r
445                 \r
446                 // Callback for LikeAsOr!\r
447                 final List<${glConditionOptionLikeSearchName}.LikeAsOrCallback> callbackList = option.getLikeAsOrCallbackList();\r
448                 if (!callbackList.isEmpty()) {\r
449                     getSqlClause().makeAdditionalConditionAsOrEffective();\r
450                     for (Iterator<${glConditionOptionLikeSearchName}.LikeAsOrCallback> ite = callbackList.iterator(); ite.hasNext();) {\r
451                         final ${glConditionOptionLikeSearchName}.LikeAsOrCallback likeAsOrCallback = (${glConditionOptionLikeSearchName}.LikeAsOrCallback) ite.next();\r
452                         final String additionalTargetPropertyName = likeAsOrCallback.getAdditionalTargetPropertyName();\r
453                         final String filteredValue = likeAsOrCallback.filterValue(currentValue);\r
454                         final ${glConditionOptionLikeSearchName} optionDeepCopy = (${glConditionOptionLikeSearchName}) option.createDeepCopy();\r
455                         optionDeepCopy.clearLikeAsOrCallback();\r
456                         final ${glConditionOptionLikeSearchName} filteredOption = likeAsOrCallback.filterOption(optionDeepCopy);\r
457                         invokeSetterLikeSearch(additionalTargetPropertyName, filteredValue, filteredOption);\r
458                     }\r
459                     getSqlClause().ignoreAdditionalConditionAsOr();\r
460                 }\r
461             }\r
462         } else {\r
463             // As 'or' Condition\r
464             for (int i = 0; i < strArray.length; i++) {\r
465                 final String currentValue = strArray[i];\r
466                 if (i == 0) {\r
467                     setupConditionValueAndRegisterWhereClause(key, currentValue, cvalue, colName, capPropName, uncapPropName, option);\r
468                 } else {\r
469                     getSqlClause().makeAdditionalConditionAsOrEffective();\r
470                     invokeSetterLikeSearch(uncapPropName, currentValue, option);\r
471                 }\r
472             }\r
473             \r
474             // @jflute -- Callback for LikeAsOr!\r
475             // final List<${glConditionOptionLikeSearchName}.LikeAsOrCallback> callbackList = option.getLikeAsOrCallbackList();\r
476             // ...\r
477             \r
478             getSqlClause().ignoreAdditionalConditionAsOr();\r
479         }\r
480     }\r
481 \r
482     protected void throwLikeSearchOptionNotFoundException(String capPropName, String value) {\r
483         String msg = "Look! Read the message below." + getLineSeparator();\r
484         msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();\r
485         msg = msg + "The likeSearchOption was Not Found! (Should not be null!)" + getLineSeparator();\r
486         msg = msg + getLineSeparator();\r
487         msg = msg + "[Advice]" + getLineSeparator();\r
488         msg = msg + "Please confirm your method call:"  + getLineSeparator();\r
489         final String beanName = getClass().getSimpleName();\r
490         final String methodName = "set" + capPropName + "_LikeSearch('" + value + "', likeSearchOption);";\r
491         msg = msg + "    " + beanName + "." + methodName + getLineSeparator();\r
492         msg = msg + "* * * * * * * * * */" + getLineSeparator();\r
493         throw new ${glRequiredOptionNotFoundException}(msg);\r
494     }\r
495         \r
496     protected void invokeSetterLikeSearch(String columnFlexibleName, Object value, ${glConditionOptionLikeSearchName} option) {\r
497         if (value == null) {\r
498             return;\r
499         }\r
500         final ${glDBMetaInterfaceName} dbmeta = ${glDBMetaInstanceHandlerName}.findDBMeta(getTableDbName());\r
501         final String columnCapPropName = initCap(dbmeta.findPropertyName(columnFlexibleName));\r
502         final String methodName = "set" + columnCapPropName + "_LikeSearch";\r
503         Method method = null;\r
504         try {\r
505             method = this.getClass().getMethod(methodName, new Class[]{value.getClass(), ${glConditionOptionLikeSearchName}.class});\r
506         } catch (NoSuchMethodException e) {\r
507             String msg = "The columnFlexibleName is not existing in this table: columnFlexibleName=" + columnFlexibleName;\r
508             msg = msg + " tableName=" + getTableDbName() + " methodName=" + methodName;\r
509             throw new RuntimeException(msg, e);\r
510         }\r
511         try {\r
512             method.invoke(this, new Object[]{value, option});\r
513         } catch (IllegalAccessException e) {\r
514             throw new RuntimeException(e);\r
515         } catch (InvocationTargetException e) {\r
516             throw new RuntimeException(e.getCause());\r
517         }\r
518     }\r
519 \r
520     // -----------------------------------------------------\r
521     //                                         InScope Query\r
522     //                                         -------------\r
523     protected void registerInScopeQuery(${glConditionKeyName} key, String value, ${glConditionValueName} cvalue\r
524                                      , String colName, String capPropName, String uncapPropName, ${glConditionOptionInScopeName} option) {\r
525         if (key.isValidRegistration(cvalue, value, key.getConditionKey() + " of " + getRealAliasName() + "." + colName)) {\r
526             if (value != null && option.isSplit()) {\r
527                 final String[] strArray = option.generateSplitValueArray(value);\r
528                 final List<String> realValueList = new ArrayList<String>();\r
529                 for (int i=0; i < strArray.length; i++) {\r
530                     final String currentValue = strArray[i];\r
531                     realValueList.add(currentValue);\r
532                 }\r
533                 setupConditionValueAndRegisterWhereClause(key, realValueList, cvalue, colName, capPropName, uncapPropName, option);\r
534             } else {\r
535                 setupConditionValueAndRegisterWhereClause(key, value, cvalue, colName, capPropName, uncapPropName, option);\r
536             }\r
537         }\r
538     }\r
539 \r
540     // -----------------------------------------------------\r
541     //                                          Inline Query\r
542     //                                          ------------\r
543     protected void registerInlineQuery(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
544                                        , String colName, String capPropName, String uncapPropName) {\r
545         if (key.isValidRegistration(cvalue, value, key.getConditionKey() + " of " + getRealAliasName() + "." + colName)) {\r
546             key.setupConditionValue(cvalue, value, getLocation(uncapPropName, key));// If Java, it is necessary to use uncapPropName!\r
547             if (isBaseQuery(this)) {\r
548                 getSqlClause().registerBaseTableInlineWhereClause(colName, key, cvalue);\r
549             } else {\r
550                 getSqlClause().registerOuterJoinInlineWhereClause(getRealAliasName(), colName, key, cvalue, _onClauseInline);\r
551             }\r
552         }\r
553     }\r
554 \r
555     protected void registerInlineQuery(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
556                                        , String colName, String capPropName, String uncapPropName, ${glConditionOptionInterfaceName} option) {\r
557         if (key.isValidRegistration(cvalue, value, key.getConditionKey() + " of " + getRealAliasName() + "." + colName)) {\r
558             key.setupConditionValue(cvalue, value, getLocation(uncapPropName, key), option);// If Java, it is necessary to use uncapPropName!\r
559             if (isBaseQuery(this)) {\r
560                 getSqlClause().registerBaseTableInlineWhereClause(colName, key, cvalue, option);\r
561             } else {\r
562                 getSqlClause().registerOuterJoinInlineWhereClause(getRealAliasName(), colName, key, cvalue, option, _onClauseInline);\r
563             }\r
564         }\r
565     }\r
566 \r
567     // -----------------------------------------------------\r
568     //                                       InScopeSubQuery\r
569     //                                       ---------------\r
570     // {Modified at DBFlute-0.7.5}\r
571     protected void registerInScopeSubQuery(${glConditionQueryInterfaceName} subQuery\r
572                                  , String columnName, String relatedColumnName, String propertyName) {\r
573         registerInScopeSubQuery(subQuery, columnName, relatedColumnName, propertyName, null);\r
574     }\r
575 \r
576     protected void registerNotInScopeSubQuery(${glConditionQueryInterfaceName} subQuery\r
577                                  , String columnName, String relatedColumnName, String propertyName) {\r
578         registerInScopeSubQuery(subQuery, columnName, relatedColumnName, propertyName, "not");\r
579     }\r
580 \r
581     protected void registerInScopeSubQuery(${glConditionQueryInterfaceName} subQuery\r
582                                  , String columnName, String relatedColumnName, String propertyName\r
583                                  , String inScopeOption) {\r
584         assertObjectNotNull("InScopeSubQyery(" + columnName + ")", subQuery);\r
585         inScopeOption = inScopeOption != null ? inScopeOption + " " : "";\r
586         String realColumnName = getInScopeSubQueryRealColumnName(columnName);\r
587         String subQueryClause = getInScopeSubQuerySql(subQuery, relatedColumnName, propertyName);\r
588         String clause = null;\r
589         if (getSqlClause().isFormatClauseEffective()) {\r
590             String ln = getLineSeparator();\r
591             int subQueryLevel = subQuery.getSubQueryLevel();\r
592             String subQueryIdentity = propertyName + "[" + subQueryLevel + "]";\r
593             String beginMark = getSqlClause().resolveSubQueryBeginMark(subQueryIdentity) + ln;\r
594             String endMark = getSqlClause().resolveSubQueryEndMark(subQueryIdentity);\r
595             String endIndent = "       ";\r
596             clause = realColumnName + " " + inScopeOption + "in (" + beginMark + subQueryClause + ln + endIndent + ")" + endMark;\r
597         } else {\r
598             clause = realColumnName + " " + inScopeOption + "in (" + subQueryClause + ")";\r
599         }\r
600         registerWhereClause(clause);\r
601     }\r
602 \r
603     protected String getInScopeSubQueryRealColumnName(String columnName) {\r
604         return getRealColumnName(columnName);\r
605     }\r
606 \r
607     protected String getInScopeSubQuerySql(${glConditionQueryInterfaceName} subQuery\r
608                                  , String relatedColumnName, String propertyName) {\r
609         String selectClause = "select " + getSqlClause().getLocalTableAliasName() + "." + relatedColumnName;\r
610         String fromWhereClause = subQuery.getSqlClause().getClauseFromWhereWithUnionTemplate();\r
611         fromWhereClause = replaceString(fromWhereClause, ".conditionQuery.", "." + getLocationBase(propertyName) + ".");// Very Important!\r
612         \r
613         // Replace template marks. These are very important!\r
614         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionSelectClauseMark(), selectClause);\r
615         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereClauseMark(), "");\r
616         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereFirstConditionMark(), "");\r
617         \r
618         return selectClause + " " + fromWhereClause;\r
619     }\r
620 \r
621     // -----------------------------------------------------\r
622     //                                        ExistsSubQuery\r
623     //                                        --------------\r
624     // {Modified at DBFlute-0.7.5}\r
625     protected void registerExistsSubQuery(${glConditionQueryInterfaceName} subQuery\r
626                                  , String columnName, String relatedColumnName, String propertyName) {\r
627         registerExistsSubQuery(subQuery, columnName, relatedColumnName, propertyName, null);\r
628     }\r
629 \r
630     protected void registerNotExistsSubQuery(${glConditionQueryInterfaceName} subQuery\r
631                                  , String columnName, String relatedColumnName, String propertyName) {\r
632         registerExistsSubQuery(subQuery, columnName, relatedColumnName, propertyName, "not");\r
633     }\r
634 \r
635     protected void registerExistsSubQuery(${glConditionQueryInterfaceName} subQuery\r
636                                  , String columnName, String relatedColumnName, String propertyName\r
637                                  , String existsOption) {\r
638         assertObjectNotNull("ExistsSubQyery(" + columnName + ")", subQuery);\r
639         existsOption = existsOption != null ? existsOption + " " : "";\r
640         String realColumnName = getExistsSubQueryRealColumnName(columnName);\r
641         String subQueryClause = getExistsSubQuerySql(subQuery, realColumnName, relatedColumnName, propertyName);\r
642         String clause = null;\r
643         if (getSqlClause().isFormatClauseEffective()) {\r
644             String ln = getLineSeparator();\r
645             int subQueryLevel = subQuery.getSubQueryLevel();\r
646             String subQueryIdentity = propertyName + "[" + subQueryLevel + "]";\r
647             String beginMark = getSqlClause().resolveSubQueryBeginMark(subQueryIdentity) + ln;\r
648             String endMark = getSqlClause().resolveSubQueryEndMark(subQueryIdentity);\r
649             String endIndent = "       ";\r
650             clause = existsOption + "exists (" + beginMark + subQueryClause + ln + endIndent + ")" + endMark;\r
651         } else {\r
652             clause = existsOption + "exists (" + subQueryClause + ")";\r
653         }\r
654         registerWhereClause(clause);\r
655     }\r
656 \r
657     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \r
658     // *Unsupport ExistsSubQuery as inline because it's so dangerous.\r
659     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \r
660 \r
661     protected String getExistsSubQueryRealColumnName(String columnName) {\r
662         return getRealColumnName(columnName);\r
663     }\r
664 \r
665     protected String getExistsSubQuerySql(${glConditionQueryInterfaceName} subQuery\r
666                                  , String realColumnName, String relatedColumnName, String propertyName) {\r
667         int subQueryLevel = subQuery.getSubQueryLevel();\r
668         if (_subQueryLevel <= subQueryLevel) {\r
669             _subQueryLevel = subQueryLevel + 1;\r
670         }\r
671         String tableAliasName = "dfsublocal_" + subQueryLevel;\r
672         String selectClause = "select " + tableAliasName + "." + relatedColumnName;\r
673         String fromWhereClause = subQuery.getSqlClause().getClauseFromWhereWithWhereUnionTemplate();\r
674         fromWhereClause = replaceString(fromWhereClause, "dflocal", tableAliasName);// Very Important!\r
675         fromWhereClause = replaceString(fromWhereClause, ".conditionQuery.", "." + getLocationBase(propertyName) + ".");// Very Important!\r
676         \r
677         String joinCondition = tableAliasName + "." + relatedColumnName + " = " + realColumnName;\r
678         String firstConditionAfter = " and ";\r
679         if (getSqlClause().isFormatClauseEffective()) {\r
680             firstConditionAfter = getLineSeparator() + "   and ";\r
681         }\r
682         \r
683         // Replace template marks. These are very important!\r
684         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getWhereClauseMark(), "where " + joinCondition);\r
685         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getWhereFirstConditionMark(), joinCondition + firstConditionAfter);\r
686         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionSelectClauseMark(), selectClause);\r
687         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereClauseMark(), "where " + joinCondition);\r
688         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereFirstConditionMark(), joinCondition + firstConditionAfter);\r
689         \r
690         return selectClause + " " + fromWhereClause;\r
691     }\r
692 \r
693     // [DBFlute-0.7.4]\r
694     // -----------------------------------------------------\r
695     //                                        DeriveSubQuery\r
696     //                                        --------------\r
697     protected void registerDeriveSubQuery(String function, ${glConditionQueryInterfaceName} subQuery\r
698                                         , String columnName, String relatedColumnName\r
699                                         , String propertyName, String aliasName) {\r
700         assertObjectNotNull("DeriveSubQuery(" + columnName + ")", subQuery);\r
701         final String realColumnName = getDeriveSubQueryRealColumnName(columnName);\r
702         final String subQueryClause = getDeriveSubQuerySql(function, subQuery, realColumnName, relatedColumnName, propertyName, aliasName);\r
703         final String clause;\r
704         if (getSqlClause().isFormatClauseEffective()) {\r
705             final String ln = getLineSeparator();\r
706             final int subQueryLevel = subQuery.getSubQueryLevel();\r
707             final String subQueryIdentity = propertyName + "[" + subQueryLevel + "]";\r
708             final String beginMark = getSqlClause().resolveSubQueryBeginMark(subQueryIdentity) + ln;\r
709             final String endMark = getSqlClause().resolveSubQueryEndMark(subQueryIdentity);\r
710             final String endIndent = "       ";\r
711             clause = "(" + beginMark + subQueryClause + ln + endIndent + ") as " + aliasName + endMark;\r
712         } else {\r
713             clause = "(" + subQueryClause + ") as " + aliasName;\r
714         }\r
715         getSqlClause().specifyDeriveSubQuery(aliasName, clause);\r
716     }\r
717 \r
718     protected String getDeriveSubQueryRealColumnName(String columnName) {\r
719         return getRealColumnName(columnName);\r
720     }\r
721 \r
722     protected String getDeriveSubQuerySql(String function, ${glConditionQueryInterfaceName} subQuery\r
723                                         , String realColumnName, String relatedColumnName\r
724                                         , String propertyName, String aliasName) {\r
725         final int subQueryLevel = subQuery.getSubQueryLevel();\r
726         if (_subQueryLevel <= subQueryLevel) {\r
727             _subQueryLevel = subQueryLevel + 1;\r
728         }\r
729         final String tableAliasName = "dfsublocal_" + subQueryLevel;\r
730         final String deriveColumnName = subQuery.getSqlClause().getSpecifiedColumnNameAsOne();\r
731         if (deriveColumnName == null || deriveColumnName.trim().length() == 0) {\r
732             throwDeriveReferrerInvalidColumnSpecificationException(function, aliasName);\r
733         }\r
734         assertDeriveReferrerColumnType(function, subQuery, deriveColumnName);\r
735         subQuery.getSqlClause().clearSpecifiedSelectColumn();\r
736         final String selectClause = "select " + function + "(" + tableAliasName + "." + deriveColumnName + ")";\r
737         String fromWhereClause = subQuery.getSqlClause().getClauseFromWhereWithWhereUnionTemplate();\r
738         fromWhereClause = replaceString(fromWhereClause, "dflocal", tableAliasName);// Very Important!\r
739         fromWhereClause = replaceString(fromWhereClause, ".conditionQuery.", "." + getLocationBase(propertyName) + ".");// Very Important!\r
740         \r
741         final String joinCondition = tableAliasName + "." + relatedColumnName + " = " + realColumnName;\r
742         String firstConditionAfter = " and ";\r
743         if (getSqlClause().isFormatClauseEffective()) {\r
744             firstConditionAfter = getLineSeparator() + "   and ";\r
745         }\r
746         \r
747         // Replace template marks. These are very important!\r
748         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getWhereClauseMark(), "where " + joinCondition);\r
749         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getWhereFirstConditionMark(), joinCondition + firstConditionAfter);\r
750         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionSelectClauseMark(), selectClause);\r
751         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereClauseMark(), "where " + joinCondition);\r
752         fromWhereClause = replaceString(fromWhereClause, getSqlClause().getUnionWhereFirstConditionMark(), joinCondition + firstConditionAfter);\r
753         \r
754         return selectClause + " " + fromWhereClause;\r
755     }\r
756 \r
757     protected void throwDeriveReferrerInvalidColumnSpecificationException(String function, String aliasName) {\r
758         String msg = "Look! Read the message below." + getLineSeparator();\r
759         msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();\r
760         msg = msg + "The specified the column for derive-referrer was Invalid!" + getLineSeparator();\r
761         msg = msg + getLineSeparator();\r
762         msg = msg + "[Advice]" + getLineSeparator();\r
763         msg = msg + " You should call specify().column[TargetColumn]() only once." + getLineSeparator();\r
764         msg = msg + "  For example:" + getLineSeparator();\r
765         msg = msg + "    " + getLineSeparator();\r
766         msg = msg + "    [Wrong]" + getLineSeparator();\r
767         msg = msg + "    /- - - - - - - - - - - - - - - - - - - - " + getLineSeparator();\r
768         msg = msg + "    MemberCB cb = new MemberCB();" + getLineSeparator();\r
769         msg = msg + "    cb.specify().derivePurchaseList()." + function + "(new SubQuery<PurchaseCB>() {" + getLineSeparator();\r
770         msg = msg + "        public void query(PurchaseCB subCB) {" + getLineSeparator();\r
771         msg = msg + "            // *No! It's empty!" + getLineSeparator();\r
772         msg = msg + "        }" + getLineSeparator();\r
773         msg = msg + "    }, \"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
774         msg = msg + "    - - - - - - - - - -/" + getLineSeparator();\r
775         msg = msg + "    " + getLineSeparator();\r
776         msg = msg + "    [Wrong]" + getLineSeparator();\r
777         msg = msg + "    /- - - - - - - - - - - - - - - - - - - - " + getLineSeparator();\r
778         msg = msg + "    MemberCB cb = new MemberCB();" + getLineSeparator();\r
779         msg = msg + "    cb.specify().derivePurchaseList()." + function + "(new SubQuery<PurchaseCB>() {" + getLineSeparator();\r
780         msg = msg + "        public void query(PurchaseCB subCB) {" + getLineSeparator();\r
781         msg = msg + "            subCB.specify().columnPurchaseDatetime();" + getLineSeparator();\r
782         msg = msg + "            subCB.specify().columnPurchaseCount(); // *No! It's duplicated!" + getLineSeparator();\r
783         msg = msg + "        }" + getLineSeparator();\r
784         msg = msg + "    }, \"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
785         msg = msg + "    - - - - - - - - - -/" + getLineSeparator();\r
786         msg = msg + "    " + getLineSeparator();\r
787         msg = msg + "    [Good!]" + getLineSeparator();\r
788         msg = msg + "    /- - - - - - - - - - - - - - - - - - - - " + getLineSeparator();\r
789         msg = msg + "    MemberCB cb = new MemberCB();" + getLineSeparator();\r
790         msg = msg + "    cb.specify().derivePurchaseList()." + function + "(new SubQuery<PurchaseCB>() {" + getLineSeparator();\r
791         msg = msg + "        public void query(PurchaseCB subCB) {" + getLineSeparator();\r
792         msg = msg + "            subCB.specify().columnPurchaseDatetime(); // *Point!" + getLineSeparator();\r
793         msg = msg + "        }" + getLineSeparator();\r
794         msg = msg + "    }, \"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
795         msg = msg + "    - - - - - - - - - -/" + getLineSeparator();\r
796         msg = msg + getLineSeparator();\r
797         msg = msg + "[Alias Name]" + getLineSeparator() + aliasName + getLineSeparator();\r
798         msg = msg + "* * * * * * * * * */";\r
799         throw new DeriveReferrerInvalidColumnSpecificationException(msg);\r
800     }\r
801 \r
802     public static class DeriveReferrerInvalidColumnSpecificationException extends RuntimeException {\r
803         private static final long serialVersionUID = 1L;\r
804         public DeriveReferrerInvalidColumnSpecificationException(String msg) {\r
805             super(msg);\r
806         }\r
807     }\r
808     \r
809     protected void assertDeriveReferrerColumnType(String function, ${glConditionQueryInterfaceName} subQuery, String deriveColumnName) {\r
810         final ${glDBMetaInterfaceName} dbmeta = ${glDBMetaInstanceHandlerName}.findDBMeta(subQuery.getTableDbName());\r
811         final Class<?> deriveColumnType = dbmeta.findColumnInfo(deriveColumnName).getPropertyType();\r
812         if ("sum".equalsIgnoreCase(function) || "avg".equalsIgnoreCase(function)) {\r
813             if (!Number.class.isAssignableFrom(deriveColumnType)) {\r
814                 throwDeriveReferrerUnmatchedColumnTypeException(function, deriveColumnName, deriveColumnType);\r
815             }\r
816         }\r
817     }\r
818 \r
819     protected void throwDeriveReferrerUnmatchedColumnTypeException(String function, String deriveColumnName, Class<?> deriveColumnType) {\r
820         String msg = "Look! Read the message below." + getLineSeparator();\r
821         msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();\r
822         msg = msg + "The type of the specified the column unmatched with the function!" + getLineSeparator();\r
823         msg = msg + getLineSeparator();\r
824         msg = msg + "[Advice]" + getLineSeparator();\r
825         msg = msg + "You should confirm the list as follow:" + getLineSeparator();\r
826         msg = msg + "    max()   : String, Number, Date" + getLineSeparator();\r
827         msg = msg + "    min()   : String, Number, Date" + getLineSeparator();\r
828         msg = msg + "    sum()   : Number" + getLineSeparator();\r
829         msg = msg + "    avg()   : Number" + getLineSeparator();\r
830         msg = msg + "    count() : String, Number, Date" + getLineSeparator();\r
831         msg = msg + getLineSeparator();\r
832         msg = msg + "[Function]" + getLineSeparator() + function + getLineSeparator();\r
833         msg = msg + getLineSeparator();\r
834         msg = msg + "[Derive Column]" + getLineSeparator() + deriveColumnName + "(" + deriveColumnType.getName() + ")" + getLineSeparator();\r
835         msg = msg + "* * * * * * * * * */";\r
836         throw new DeriveReferrerUnmatchedColumnTypeException(msg);\r
837     }\r
838 \r
839     public static class DeriveReferrerUnmatchedColumnTypeException extends RuntimeException {\r
840         private static final long serialVersionUID = 1L;\r
841         public DeriveReferrerUnmatchedColumnTypeException(String msg) {\r
842             super(msg);\r
843         }\r
844     }\r
845     \r
846     // -----------------------------------------------------\r
847     //                                          Where Clause\r
848     //                                          ------------\r
849     protected void setupConditionValueAndRegisterWhereClause(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
850                                                              , String colName, String capPropName, String uncapPropName) {\r
851         key.setupConditionValue(cvalue, value, getLocation(uncapPropName, key));// If Java, it is necessary to use uncapPropName!\r
852         getSqlClause().registerWhereClause(getRealColumnName(colName), key, cvalue);\r
853     }\r
854 \r
855     protected void setupConditionValueAndRegisterWhereClause(${glConditionKeyName} key, Object value, ${glConditionValueName} cvalue\r
856                                                              , String colName, String capPropName, String uncapPropName, ${glConditionOptionInterfaceName} option) {\r
857         key.setupConditionValue(cvalue, value, getLocation(uncapPropName, key), option);// If Java, it is necessary to use uncapPropName!\r
858         getSqlClause().registerWhereClause(getRealColumnName(colName), key, cvalue, option);\r
859     }\r
860 \r
861     protected void registerWhereClause(String whereClause) {\r
862         getSqlClause().registerWhereClause(whereClause);\r
863     }\r
864 \r
865     protected void registerInlineWhereClause(String whereClause) {\r
866         if (isBaseQuery(this)) {\r
867             getSqlClause().registerBaseTableInlineWhereClause(whereClause);\r
868         } else {\r
869             getSqlClause().registerOuterJoinInlineWhereClause(getRealAliasName(), whereClause, _onClauseInline);\r
870         }\r
871     }\r
872 \r
873     // -----------------------------------------------------\r
874     //                                           Union Query\r
875     //                                           -----------\r
876     public void registerUnionQuery(${glConditionQueryInterfaceName} unionQuery, boolean unionAll, String unionQueryPropertyName) {\r
877         final String unionQueryClause = getUnionQuerySql(unionQuery, unionQueryPropertyName);\r
878         \r
879         // At the future, building SQL will be moved to sqlClause.\r
880         getSqlClause().registerUnionQuery(unionQueryClause, unionAll);\r
881     }\r
882 \r
883     protected String getUnionQuerySql(${glConditionQueryInterfaceName} unionQuery, String unionQueryPropertyName) {\r
884         final String fromClause = unionQuery.getSqlClause().getFromClause();\r
885         final String whereClause = unionQuery.getSqlClause().getWhereClause();\r
886         final String unionQueryClause;\r
887         if (whereClause.trim().length() <= 0) {\r
888             unionQueryClause = fromClause + " " + getSqlClause().getUnionWhereClauseMark();\r
889         } else {\r
890             final int whereIndex = whereClause.indexOf("where ");\r
891             if (whereIndex < 0) {\r
892                 String msg = "The whereClause should have 'where' string: " + whereClause;\r
893                 throw new IllegalStateException(msg);\r
894             }\r
895             final int clauseIndex = whereIndex + "where ".length();\r
896             final String mark = getSqlClause().getUnionWhereFirstConditionMark();\r
897             unionQueryClause = fromClause + " " + whereClause.substring(0, clauseIndex) + mark + whereClause.substring(clauseIndex);\r
898         }\r
899         final String oldStr = ".conditionQuery.";\r
900         final String newStr = ".conditionQuery." + unionQueryPropertyName + ".";\r
901         return replaceString(unionQueryClause, oldStr, newStr);// Very Important!\r
902     }\r
903 \r
904     // -----------------------------------------------------\r
905     //                                               OrderBy\r
906     //                                               -------\r
907     public void withNullsFirst() {// is User Public!\r
908         getSqlClause().addNullsFirstToPreviousOrderBy();\r
909     }\r
910     \r
911     public void withNullsLast() {// is User Public!\r
912         getSqlClause().addNullsLastToPreviousOrderBy();\r
913     }\r
914 \r
915     protected void registerSpecifiedDerivedOrderBy_Asc(String aliasName) {\r
916         if (!getSqlClause().hasSpecifiedDeriveSubQuery(aliasName)) {\r
917             throwSpecifiedDerivedOrderByAliasNameNotFoundException(aliasName);\r
918         }\r
919         getSqlClause().registerOrderBy(aliasName, null, true);\r
920     }\r
921 \r
922     protected void registerSpecifiedDerivedOrderBy_Desc(String aliasName) {\r
923         if (!getSqlClause().hasSpecifiedDeriveSubQuery(aliasName)) {\r
924             throwSpecifiedDerivedOrderByAliasNameNotFoundException(aliasName);\r
925         }\r
926         getSqlClause().registerOrderBy(aliasName, null, false);\r
927     }\r
928 \r
929     protected void throwSpecifiedDerivedOrderByAliasNameNotFoundException(String aliasName) {\r
930         String msg = "Look! Read the message below." + getLineSeparator();\r
931         msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();\r
932         msg = msg + "The aliasName was Not Found in specified alias names." + getLineSeparator();\r
933         msg = msg + getLineSeparator();\r
934         msg = msg + "[Advice]" + getLineSeparator();\r
935         msg = msg + "You should specified an alias name that is the same as one in specify-derived-referrer." + getLineSeparator();\r
936         msg = msg + "  For example:" + getLineSeparator();\r
937         msg = msg + "    " + getLineSeparator();\r
938         msg = msg + "    [Wrong]" + getLineSeparator();\r
939         msg = msg + "    /- - - - - - - - - - - - - - - - - - - - " + getLineSeparator();\r
940         msg = msg + "    MemberCB cb = new MemberCB();" + getLineSeparator();\r
941         msg = msg + "    cb.specify().derivePurchaseList().max(new SubQuery<PurchaseCB>() {" + getLineSeparator();\r
942         msg = msg + "        public void query(PurchaseCB subCB) {" + getLineSeparator();\r
943         msg = msg + "            subCB.specify().specifyProduct().columnProductName(); // *No!" + getLineSeparator();\r
944         msg = msg + "        }" + getLineSeparator();\r
945         msg = msg + "    }, \"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
946         msg = msg + "    cb.query().addSpecifiedDerivedOrderBy_Desc(\"WRONG_NAME_DATETIME\");" + getLineSeparator();\r
947         msg = msg + "    - - - - - - - - - -/" + getLineSeparator();\r
948         msg = msg + "    " + getLineSeparator();\r
949         msg = msg + "    [Good!]" + getLineSeparator();\r
950         msg = msg + "    /- - - - - - - - - - - - - - - - - - - - " + getLineSeparator();\r
951         msg = msg + "    MemberCB cb = new MemberCB();" + getLineSeparator();\r
952         msg = msg + "    cb.specify().derivePurchaseList().max(new SubQuery<PurchaseCB>() {" + getLineSeparator();\r
953         msg = msg + "        public void query(PurchaseCB subCB) {" + getLineSeparator();\r
954         msg = msg + "            subCB.specify().columnPurchaseDatetime();// *Point!" + getLineSeparator();\r
955         msg = msg + "        }" + getLineSeparator();\r
956         msg = msg + "    }, \"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
957         msg = msg + "    cb.query().addSpecifiedDerivedOrderBy_Desc(\"LATEST_PURCHASE_DATETIME\");" + getLineSeparator();\r
958         msg = msg + "    - - - - - - - - - -/" + getLineSeparator();\r
959         msg = msg + getLineSeparator();\r
960         msg = msg + "[Not Found Alias Name]" + getLineSeparator() + aliasName + getLineSeparator();\r
961         msg = msg + "* * * * * * * * * */";\r
962         throw new SpecifiedDerivedOrderByAliasNameNotFoundException(msg);\r
963     }\r
964 \r
965     public static class SpecifiedDerivedOrderByAliasNameNotFoundException extends RuntimeException {\r
966         private static final long serialVersionUID = 1L;\r
967         public SpecifiedDerivedOrderByAliasNameNotFoundException(String msg) {\r
968             super(msg);\r
969         }\r
970     }\r
971 \r
972     protected void registerOrderBy(String columnName, boolean ascOrDesc) {\r
973         getSqlClause().registerOrderBy(getRealColumnName(columnName), null, ascOrDesc);\r
974     }\r
975 \r
976     protected void regOBA(String columnName) {\r
977         registerOrderBy(columnName, true);\r
978     }\r
979 \r
980     protected void regOBD(String columnName) {\r
981         registerOrderBy(columnName, false);\r
982     }\r
983     \r
984     // ===================================================================================\r
985     //                                                                       Name Resolver\r
986     //                                                                       =============\r
987     /**\r
988      * Resolve join alias name.\r
989      * @param relationPath Relation path. (NotNull)\r
990      * @param nestLevel Nest level.\r
991      * @return Resolved join alias name. (NotNull)\r
992      */\r
993     protected String resolveJoinAliasName(String relationPath, int nestLevel) {\r
994         return getSqlClause().resolveJoinAliasName(relationPath, nestLevel);\r
995     }\r
996 \r
997     protected String resolveNestLevelExpression(String name) {\r
998         return getSqlClause().resolveNestLevelExpression(name, getNestLevel());\r
999     }\r
1000 \r
1001     protected String resolveNextRelationPath(String tableName, String relationPropertyName) {\r
1002         final int relationNo = getSqlClause().resolveRelationNo(tableName, relationPropertyName);\r
1003         String nextRelationPath = "_" + relationNo;\r
1004         if (_relationPath != null) {\r
1005             nextRelationPath = _relationPath + nextRelationPath;\r
1006         }\r
1007         return nextRelationPath;\r
1008     }\r
1009     \r
1010     // ===================================================================================\r
1011     //                                                                     Fixed Condition\r
1012     //                                                                     ===============\r
1013     protected String prepareFixedCondition(String fixedCondition, String localAliasName, String foreignAliasName) {\r
1014         fixedCondition = replaceString(fixedCondition, "$$alias$$", foreignAliasName);\r
1015         fixedCondition = replaceString(fixedCondition, "$$foreignAlias$$", foreignAliasName);\r
1016         fixedCondition = replaceString(fixedCondition, "$$localAlias$$", localAliasName);\r
1017         return fixedCondition;\r
1018     }\r
1019 \r
1020     // ===================================================================================\r
1021     //                                                                 Reflection Invoking\r
1022     //                                                                 ===================\r
1023     /**\r
1024      * ${database.ImplementComment}\r
1025      * @param columnFlexibleName The flexible name of the column. (NotNull and NotEmpty)\r
1026      * @return The conditionValue. (NotNull)\r
1027      */\r
1028     public ${glConditionValueName} invokeValue(String columnFlexibleName) {\r
1029         assertStringNotNullAndNotTrimmedEmpty("columnFlexibleName", columnFlexibleName);\r
1030         final ${glDBMetaInterfaceName} dbmeta = ${glDBMetaInstanceHandlerName}.findDBMeta(getTableDbName());\r
1031         final String columnCapPropName = initCap(dbmeta.findPropertyName(columnFlexibleName));\r
1032         final String methodName = "get" + columnCapPropName;\r
1033         final Method method = helpGettingCQMethod(this, methodName, new Class<?>[]{}, columnFlexibleName);\r
1034         return (${glConditionValueName})helpInvokingCQMethod(this, method, new Object[]{});\r
1035     }\r
1036 \r
1037     /**\r
1038      * ${database.ImplementComment}\r
1039      * @param columnFlexibleName The flexible name of the column allowed to contain relations. (NotNull and NotEmpty)\r
1040      * @param conditionKeyName The name of the conditionKey. (NotNull)\r
1041      * @param value The value of the condition. (NotNull)\r
1042      */\r
1043     public void invokeQuery(String columnFlexibleName, String conditionKeyName, Object value) {\r
1044         assertStringNotNullAndNotTrimmedEmpty("columnFlexibleName", columnFlexibleName);\r
1045         assertStringNotNullAndNotTrimmedEmpty("conditionKeyName", conditionKeyName);\r
1046         if (value == null) {\r
1047             return;\r
1048         }\r
1049         final PropertyNameCQContainer container = helpExtractingPropertyNameCQContainer(columnFlexibleName);\r
1050         final String propertyName = container.getPropertyName();\r
1051         final ${glConditionQueryInterfaceName} cq = container.getConditionQuery();\r
1052         final ${glDBMetaInterfaceName} dbmeta = ${glDBMetaInstanceHandlerName}.findDBMeta(cq.getTableDbName());\r
1053         final String columnCapPropName = initCap(dbmeta.findPropertyName(propertyName));\r
1054         final String methodName = "set" + columnCapPropName + "_" + initCap(conditionKeyName);\r
1055         final Method method = helpGettingCQMethod(cq, methodName, new Class<?>[]{value.getClass()}, propertyName);\r
1056         helpInvokingCQMethod(cq, method, new Object[]{value});\r
1057     }\r
1058 \r
1059     /**\r
1060      * ${database.ImplementComment}\r
1061      * @param columnFlexibleName The flexible name of a column allowed to contain relations. (NotNull and NotEmpty)\r
1062      * @param isAsc Is it ascend?\r
1063      */\r
1064     public void invokeOrderBy(String columnFlexibleName, boolean isAsc) {\r
1065         assertStringNotNullAndNotTrimmedEmpty("columnFlexibleName", columnFlexibleName);\r
1066         final PropertyNameCQContainer container = helpExtractingPropertyNameCQContainer(columnFlexibleName);\r
1067         final String propertyName = container.getPropertyName();\r
1068         final ${glConditionQueryInterfaceName} cq = container.getConditionQuery();\r
1069         final String ascDesc = isAsc ? "Asc" : "Desc";\r
1070         final ${glDBMetaInterfaceName} dbmeta = ${glDBMetaInstanceHandlerName}.findDBMeta(cq.getTableDbName());\r
1071         final String columnCapPropName = initCap(dbmeta.findPropertyName(propertyName));\r
1072         final String methodName = "addOrderBy_" + columnCapPropName + "_" + ascDesc;\r
1073         final Method method = helpGettingCQMethod(cq, methodName, new Class<?>[]{}, propertyName);\r
1074         helpInvokingCQMethod(cq, method, new Object[]{});\r
1075     }\r
1076 \r
1077     /**\r
1078      * ${database.ImplementComment}\r
1079      * @param foreignPropertyName The property name of foreign. (NotNull and NotEmpty)\r
1080      * @return The conditionQuery of foreign as interface. (NotNull)\r
1081      */\r
1082     public ${glConditionQueryInterfaceName} invokeForeignCQ(String foreignPropertyName) {\r
1083         assertStringNotNullAndNotTrimmedEmpty("foreignPropertyName", foreignPropertyName);\r
1084         final String methodName = "query" + initCap(foreignPropertyName);\r
1085         final Method method = helpGettingCQMethod(this, methodName, new Class<?>[]{}, foreignPropertyName);\r
1086         return (${glConditionQueryInterfaceName})helpInvokingCQMethod(this, method, new Object[]{});\r
1087     }\r
1088 \r
1089     private PropertyNameCQContainer helpExtractingPropertyNameCQContainer(String name) {\r
1090         final String[] strings = name.split("\\.");\r
1091         final int length = strings.length;\r
1092         String propertyName = null;\r
1093         ${glConditionQueryInterfaceName} cq = this;\r
1094         int index = 0;\r
1095         for (String element : strings) {\r
1096             if (length == (index+1)) {// at last loop!\r
1097                 propertyName = element;\r
1098                 break;\r
1099             }\r
1100             cq = cq.invokeForeignCQ(element);\r
1101             ++index;\r
1102         }\r
1103         return new PropertyNameCQContainer(propertyName, cq);\r
1104     }\r
1105 \r
1106     private static class PropertyNameCQContainer {\r
1107         protected String _propertyName;\r
1108         protected ${glConditionQueryInterfaceName} _cq;\r
1109         public PropertyNameCQContainer(String propertyName, ${glConditionQueryInterfaceName} cq) {\r
1110             this._propertyName = propertyName;\r
1111             this._cq = cq;\r
1112         }\r
1113         public String getPropertyName() {\r
1114             return _propertyName;\r
1115         }\r
1116         public ${glConditionQueryInterfaceName} getConditionQuery() {\r
1117             return _cq;\r
1118         }\r
1119     }\r
1120 \r
1121     private Method helpGettingCQMethod(${glConditionQueryInterfaceName} cq, String methodName, Class<?>[] argTypes, String property) {\r
1122         try {\r
1123             return cq.getClass().getMethod(methodName, argTypes);\r
1124         } catch (NoSuchMethodException e) {\r
1125             String msg = "The method is not existing:";\r
1126             msg = msg + " methodName=" + methodName;\r
1127             msg = msg + " argTypes=" + convertObjectArrayToStringView(argTypes);\r
1128             msg = msg + " tableName=" + cq.getTableDbName();\r
1129             msg = msg + " property=" + property;\r
1130             throw new IllegalStateException(msg, e);\r
1131         }\r
1132     }\r
1133 \r
1134     private Object helpInvokingCQMethod(${glConditionQueryInterfaceName} cq, Method method, Object[] args) {\r
1135         try {\r
1136             return method.invoke(cq, args);\r
1137         } catch (IllegalAccessException e) {\r
1138             throw new IllegalStateException(e);\r
1139         } catch (InvocationTargetException e) {\r
1140             throw new IllegalStateException(e.getCause());\r
1141         }\r
1142     }\r
1143 \r
1144     // ===================================================================================\r
1145     //                                                                       Assist Helper\r
1146     //                                                                       =============\r
1147     /**\r
1148      * @param value Query-value-string. (Nullable)\r
1149      * @return Filtered value. (Nullable)\r
1150      */\r
1151     protected String fRES(String value) {\r
1152         return filterRemoveEmptyString(value);\r
1153     }\r
1154 \r
1155     /**\r
1156      * @param value Query-value-string. (Nullable)\r
1157      * @return Filtered value. (Nullable)\r
1158      */\r
1159     private String filterRemoveEmptyString(String value) {\r
1160         return ((value != null && !"".equals(value)) ? value : null);\r
1161     }\r
1162     \r
1163     /**\r
1164      * @param col Target collection. (Nullable)\r
1165      * @param <PROPERTY_TYPE> The type of property.\r
1166      * @return List. (Nullable: If the argument is null, returns null.)\r
1167      */\r
1168     protected <PROPERTY_TYPE> List<PROPERTY_TYPE> cTL(Collection<PROPERTY_TYPE> col) {\r
1169         return convertToList(col);\r
1170     }\r
1171     \r
1172     /**\r
1173      * @param col Target collection. (Nullable)\r
1174      * @param <PROPERTY_TYPE> The type of property.\r
1175      * @return List. (Nullable: If the argument is null, returns null.)\r
1176      */\r
1177     private <PROPERTY_TYPE> List<PROPERTY_TYPE> convertToList(Collection<PROPERTY_TYPE> col) {\r
1178         if (col == null) {\r
1179             return null;\r
1180         }\r
1181         if (col instanceof List) {\r
1182             return filterRemoveNullOrEmptyValueFromList((List<PROPERTY_TYPE>)col);\r
1183         }\r
1184         return filterRemoveNullOrEmptyValueFromList(new ArrayList<PROPERTY_TYPE>(col));\r
1185     }\r
1186 \r
1187     private <PROPERTY_TYPE> List<PROPERTY_TYPE> filterRemoveNullOrEmptyValueFromList(List<PROPERTY_TYPE> ls) {\r
1188         if (ls == null) {\r
1189             return null;\r
1190         }\r
1191         List<PROPERTY_TYPE> newList = new ArrayList<PROPERTY_TYPE>();\r
1192         for (Iterator<PROPERTY_TYPE> ite = ls.iterator(); ite.hasNext(); ) {\r
1193             final PROPERTY_TYPE element = ite.next();\r
1194             if (element == null) {\r
1195                 continue;\r
1196             }\r
1197             if (element instanceof String) {\r
1198                 if (((String)element).length() == 0) {\r
1199                     continue;\r
1200                 }\r
1201             }\r
1202             newList.add(element);\r
1203         }\r
1204         return newList;\r
1205     }\r
1206     \r
1207     public void doNss(NssCall callback) {// Very Internal\r
1208         String foreignPropertyName = callback.qf().getForeignPropertyName();\r
1209         String foreignTableAliasName = callback.qf().getRealAliasName();\r
1210         getSqlClause().registerSelectedSelectColumn(foreignTableAliasName, getTableDbName(), foreignPropertyName, getRelationPath());\r
1211         getSqlClause().registerSelectedForeignInfo(callback.qf().getRelationPath(), foreignPropertyName);\r
1212     }\r
1213     \r
1214     public static interface NssCall {// Very Internal\r
1215         public ${glConditionQueryInterfaceName} qf();\r
1216     }\r
1217 \r
1218     protected void registerOuterJoin(${glConditionQueryInterfaceName} cq, Map<String, String> joinOnMap) {\r
1219         getSqlClause().registerOuterJoin(cq.getTableSqlName(), cq.getRealAliasName(), joinOnMap);\r
1220     }\r
1221     \r
1222     // ===================================================================================\r
1223     //                                                                      General Helper\r
1224     //                                                                      ==============\r
1225     protected final String replaceString(String text, String fromText, String toText) {\r
1226         return ${glSimpleStringUtil}.replace(text, fromText, toText);\r
1227     }\r
1228 \r
1229     protected String initCap(String str) {\r
1230         return ${glSimpleStringUtil}.initCap(str);\r
1231     }\r
1232 \r
1233     protected String getLineSeparator() {\r
1234         return ${glSimpleSystemUtil}.getLineSeparator();\r
1235     }\r
1236 \r
1237     protected String convertObjectArrayToStringView(Object[] objArray) {\r
1238             return ${glTraceViewUtilName}.convertObjectArrayToStringView(objArray);\r
1239     }\r
1240 \r
1241     // -----------------------------------------------------\r
1242     //                                  Collection Generator\r
1243     //                                  --------------------\r
1244     protected <KEY, VALUE> LinkedHashMap<KEY, VALUE> newLinkedHashMap() {\r
1245         return new LinkedHashMap<KEY, VALUE>();\r
1246     }\r
1247 \r
1248     // -----------------------------------------------------\r
1249     //                                         Assert Object\r
1250     //                                         -------------\r
1251     /**\r
1252      * Assert that the object is not null.\r
1253      * @param variableName Variable name. (NotNull)\r
1254      * @param value Value. (NotNull)\r
1255      * @exception IllegalArgumentException\r
1256      */\r
1257     protected void assertObjectNotNull(String variableName, Object value) {\r
1258         if (variableName == null) {\r
1259             String msg = "The value should not be null: variableName=" + variableName + " value=" + value;\r
1260             throw new IllegalArgumentException(msg);\r
1261         }\r
1262         if (value == null) {\r
1263             String msg = "The value should not be null: variableName=" + variableName;\r
1264             throw new IllegalArgumentException(msg);\r
1265         }\r
1266     }\r
1267 \r
1268     /**\r
1269      * Assert that the column-name is not null and is not empty and does not contain comma.\r
1270      * @param columnName Column-name. (NotNull)\r
1271      * @exception IllegalArgumentException\r
1272      */\r
1273     protected void assertColumnName(String columnName) {\r
1274         if (columnName == null) {\r
1275             String msg = "The columnName should not be null.";\r
1276             throw new IllegalArgumentException(msg);\r
1277         }\r
1278         if (columnName.trim().length() == 0) {\r
1279             String msg = "The columnName should not be empty-string.";\r
1280             throw new IllegalArgumentException(msg);\r
1281         }\r
1282         if (columnName.indexOf(",") >= 0) {\r
1283             String msg = "The columnName should not contain comma ',': " + columnName;\r
1284             throw new IllegalArgumentException(msg);\r
1285         }\r
1286     }\r
1287 \r
1288     /**\r
1289      * Assert that the alias-name is not null and is not empty and does not contain comma.\r
1290      * @param aliasName Alias-name. (NotNull)\r
1291      * @exception IllegalArgumentException\r
1292      */\r
1293     protected void assertAliasName(String aliasName) {\r
1294         if (aliasName == null) {\r
1295             String msg = "The aliasName should not be null.";\r
1296             throw new IllegalArgumentException(msg);\r
1297         }\r
1298         if (aliasName.trim().length() == 0) {\r
1299             String msg = "The aliasName should not be empty-string.";\r
1300             throw new IllegalArgumentException(msg);\r
1301         }\r
1302         if (aliasName.indexOf(",") >= 0) {\r
1303             String msg = "The aliasName should not contain comma ',': " + aliasName;\r
1304             throw new IllegalArgumentException(msg);\r
1305         }\r
1306     }\r
1307 \r
1308     // -----------------------------------------------------\r
1309     //                                         Assert String\r
1310     //                                         -------------\r
1311     /**\r
1312      * Assert that the entity is not null and not trimmed empty.\r
1313      * @param variableName Variable name. (NotNull)\r
1314      * @param value Value. (NotNull)\r
1315      */\r
1316     protected void assertStringNotNullAndNotTrimmedEmpty(String variableName, String value) {\r
1317         assertObjectNotNull("variableName", variableName);\r
1318         assertObjectNotNull("value", value);\r
1319         if (value.trim().length() ==0) {\r
1320             String msg = "The value should not be empty: variableName=" + variableName + " value=" + value;\r
1321             throw new IllegalArgumentException(msg);\r
1322         }\r
1323     }\r
1324     \r
1325     // ===================================================================================\r
1326     //                                                                      Basic Override\r
1327     //                                                                      ==============\r
1328     @Override\r
1329     public String toString() {\r
1330         return getClass().getSimpleName() + ":{aliasName=" + _aliasName + ", nestLevel=" + _nestLevel\r
1331              + ", subQueryLevel=" + _subQueryLevel + ", foreignPropertyName=" + _foreignPropertyName\r
1332              + ", relationPath=" + _relationPath + ", onClauseInline=" + _onClauseInline + "}";\r
1333     }\r
1334 }\r