OSDN Git Service

"https://svn.sourceforge.jp/svnroot/ea2ddl" にプロジェクト "ea2ddl-dao" を共用
[ea2ddl/ea2ddl.git] / ea2ddl-dao / src / main / java / jp / sourceforge / ea2ddl / dao / allcommon / cbean / outsidesql / OutsideSqlContext.java
1 package jp.sourceforge.ea2ddl.dao.allcommon.cbean.outsidesql;\r
2 \r
3 import org.apache.commons.logging.Log;\r
4 import org.apache.commons.logging.LogFactory;\r
5 import org.seasar.framework.util.InputStreamReaderUtil;\r
6 import org.seasar.framework.util.ReaderUtil;\r
7 import org.seasar.framework.util.ResourceUtil;\r
8 \r
9 import jp.sourceforge.ea2ddl.dao.allcommon.DBFluteConfig;\r
10 import jp.sourceforge.ea2ddl.dao.allcommon.dbmeta.DBMeta;\r
11 import jp.sourceforge.ea2ddl.dao.allcommon.dbmeta.DBMetaInstanceHandler;\r
12 import jp.sourceforge.ea2ddl.dao.allcommon.jdbc.StatementConfig;\r
13 import jp.sourceforge.ea2ddl.dao.allcommon.util.SimpleStringUtil;\r
14 import jp.sourceforge.ea2ddl.dao.allcommon.util.SimpleSystemUtil;\r
15 \r
16 /**\r
17  * The context of outside-SQL.\r
18  * @author DBFlute(AutoGenerator)\r
19  */\r
20 public class OutsideSqlContext {\r
21 \r
22     /** Log instance. */\r
23     private static final Log _log = LogFactory.getLog(OutsideSqlContext.class);\r
24     \r
25     // ===================================================================================\r
26     //                                                                        Thread Local\r
27     //                                                                        ============\r
28     /** The thread-local for this. */\r
29     private static final ThreadLocal<OutsideSqlContext> _threadLocal = new ThreadLocal<OutsideSqlContext>();\r
30 \r
31     /**\r
32      * Get outside-SQL context on thread.\r
33      * @return Outside-SQL context. (Nullable)\r
34      */\r
35     public static OutsideSqlContext getOutsideSqlContextOnThread() {\r
36         return (OutsideSqlContext)_threadLocal.get();\r
37     }\r
38 \r
39     /**\r
40      * Set outside-SQL context on thread.\r
41      * @param outsideSqlContext Outside-SQL context. (NotNull)\r
42      */\r
43     public static void setOutsideSqlContextOnThread(OutsideSqlContext outsideSqlContext) {\r
44         if (outsideSqlContext == null) {\r
45             String msg = "The argument[outsideSqlContext] must not be null.";\r
46             throw new IllegalArgumentException(msg);\r
47         }\r
48         _threadLocal.set(outsideSqlContext);\r
49     }\r
50 \r
51     /**\r
52      * Is existing outside-SQL context on thread?\r
53      * \r
54      * @return Determination.\r
55      */\r
56     public static boolean isExistOutsideSqlContextOnThread() {\r
57         return (_threadLocal.get() != null);\r
58     }\r
59 \r
60     /**\r
61      * Clear outside-SQL context on thread.\r
62      */\r
63     public static void clearOutsideSqlContextOnThread() {\r
64         _threadLocal.set(null);\r
65     }\r
66 \r
67     // ===================================================================================\r
68     //                                                                          Unique Key\r
69     //                                                                          ==========\r
70     public static String generateSpecifiedOutsideSqlUniqueKey(String methodName, String path, Object pmb, OutsideSqlOption option, Object resultTypeSpecification) {\r
71         final String pmbKey = (pmb != null ? pmb.getClass().getName() : "null");\r
72         final String resultKey = (resultTypeSpecification != null ? ":" + resultTypeSpecification : "null");\r
73         final String tableDbName = option.getTableDbName();\r
74         final String generatedUniqueKey = option.generateUniqueKey();\r
75         return methodName + "():" + tableDbName + ":" + path + ":" + pmbKey + ":" + generatedUniqueKey + resultKey;\r
76     }\r
77 \r
78     // ===================================================================================\r
79     //                                                                  Exception Handling\r
80     //                                                                  ==================\r
81     public static void throwOutsideSqlNotFoundException(String path) {\r
82         String msg = "Look! Read the message below." + getLineSeparator();\r
83         msg = msg + "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + getLineSeparator();\r
84         msg = msg + "The outsideSql was Not Found!" + getLineSeparator();\r
85         msg = msg + getLineSeparator();\r
86         msg = msg + "[Advice]" + getLineSeparator();\r
87         msg = msg + "Please confirm the existence of your target file of outsideSql on your classpath." + getLineSeparator();\r
88         msg = msg + "And please confirm the file name and the file path STRICTLY!" + getLineSeparator();\r
89         msg = msg + getLineSeparator();\r
90         msg = msg + "[Specified OutsideSql Path]" + getLineSeparator() + path + getLineSeparator();\r
91         msg = msg + "* * * * * * * * * */" + getLineSeparator();\r
92         throw new jp.sourceforge.ea2ddl.dao.allcommon.exception.OutsideSqlNotFoundException(msg);\r
93     }\r
94 \r
95     // ===================================================================================\r
96     //                                                                           Attribute\r
97     //                                                                           =========\r
98     // -----------------------------------------------------\r
99     //                                  Common of OutsideSql\r
100     //                                  --------------------\r
101     protected boolean _dynamicBinding;\r
102 \r
103     protected boolean _offsetByCursorForcedly;\r
104 \r
105     protected boolean _limitByCursorForcedly;\r
106 \r
107     // -----------------------------------------------------\r
108     //                                  Specified OutsideSql\r
109     //                                  --------------------\r
110     /** The path of outside-sql. (The mark of Specified-OutsideSql) */\r
111     protected String _outsideSqlPath;\r
112 \r
113     protected Object _parameterBean;\r
114 \r
115     protected Object _resultTypeSpecification;\r
116 \r
117     protected String _methodName;\r
118     \r
119     /** The config of statement. (Nullable) */\r
120     protected StatementConfig _statementConfig;\r
121     \r
122     /** The DB name of table for using behavior-SQL-path. (Nullable) */\r
123     protected String _tableDbName;\r
124 \r
125     // ===================================================================================\r
126     //                                                                            Read SQL\r
127     //                                                                            ========\r
128     /**\r
129      * @param sqlFileEncoding The encoding of SQL file. (NotNull)\r
130      * @param dbmsSuffix The suffix of DBMS. (NotNull)\r
131      * @return The filtered outside-SQL. (NotNull)\r
132      * @exception jp.sourceforge.ea2ddl.dao.allcommon.exception.OutsideSqlNotFoundException When the SQL is not found.\r
133      */\r
134     public String readFilteredOutsideSql(String sqlFileEncoding, String dbmsSuffix) {\r
135         final String sql = readOutsideSql(sqlFileEncoding, dbmsSuffix);\r
136         return replaceOutsideSqlBindCharacterOnLineComment(sql);\r
137     }\r
138 \r
139     protected String replaceOutsideSqlBindCharacterOnLineComment(String sql) {\r
140         final String bindCharacter = "?";\r
141         if (sql.indexOf(bindCharacter) < 0) {\r
142             return sql;\r
143         }\r
144         final String lineSeparator = "\n";\r
145         if (sql.indexOf(lineSeparator) < 0) {\r
146             return sql;\r
147         }\r
148         final String lineCommentMark = "--";\r
149         if (sql.indexOf(lineCommentMark) < 0) {\r
150             return sql;\r
151         }\r
152         final StringBuilder sb = new StringBuilder();\r
153         final String[] lines = sql.split(lineSeparator);\r
154         for (String line : lines) {\r
155             final int lineCommentIndex = line.indexOf("--");\r
156             if (lineCommentIndex < 0) {\r
157                 sb.append(line).append(lineSeparator);\r
158                 continue;\r
159             }\r
160             final String lineComment = line.substring(lineCommentIndex);\r
161             if (lineComment.contains("ELSE") || !lineComment.contains(bindCharacter)) {\r
162                 sb.append(line).append(lineSeparator);\r
163                 continue;\r
164             }\r
165             \r
166             if (_log.isDebugEnabled()) {\r
167                 _log.debug("...Replacing bind character on line comment: " + lineComment);\r
168             }\r
169             final String filteredLineComment = replaceString(lineComment, bindCharacter, "Q");\r
170             sb.append(line.substring(0, lineCommentIndex)).append(filteredLineComment).append(lineSeparator);\r
171         }\r
172         return sb.toString();\r
173     }\r
174     \r
175     /**\r
176      * Read outside-sql path. Required attribute is 'outsideSqlPath'.\r
177      * @param sqlFileEncoding The encoding of SQL file. (NotNull)\r
178      * @param dbmsSuffix The suffix of DBMS. (NotNull)\r
179      * @return The text of SQL. (NotNull)\r
180      * @exception jp.sourceforge.ea2ddl.dao.allcommon.exception.OutsideSqlNotFoundException When the SQL is not found.\r
181      */\r
182     public String readOutsideSql(String sqlFileEncoding, String dbmsSuffix) {\r
183         final String standardPath = _outsideSqlPath;\r
184         final String dbmsPath = buildDbmsPath(standardPath, dbmsSuffix);\r
185         String sql;\r
186         if (isExistResource(dbmsPath)) {\r
187             sql = readText(dbmsPath, sqlFileEncoding);\r
188         } else if (isExistResource(standardPath)) {\r
189             sql = readText(standardPath, sqlFileEncoding);\r
190         } else {\r
191             throwOutsideSqlNotFoundException(standardPath);\r
192             return null; // Non Reachable.\r
193         }\r
194         return removeInitialUnicodeBomIfNeeds(sqlFileEncoding, sql);\r
195     }\r
196 \r
197     protected String buildDbmsPath(String standardPath, String dbmsSuffix) {\r
198         final String dbmsPath;\r
199         final int lastIndexOfDot = standardPath.lastIndexOf(".");\r
200         if (lastIndexOfDot >= 0 && !standardPath.substring(lastIndexOfDot).contains("/")) {\r
201             final String base = standardPath.substring(0, lastIndexOfDot);\r
202             dbmsPath = base + dbmsSuffix + standardPath.substring(lastIndexOfDot);\r
203         } else {\r
204             dbmsPath = standardPath + dbmsSuffix;\r
205         }\r
206         return dbmsPath;\r
207     }\r
208 \r
209     protected String removeInitialUnicodeBomIfNeeds(String sqlFileEncoding, String sql) {\r
210         if ("UTF-8".equalsIgnoreCase(sqlFileEncoding) && sql.length() > 0 && sql.charAt(0) == '\uFEFF') {\r
211             sql = sql.substring(1);\r
212         }\r
213         return sql;\r
214     }\r
215 \r
216     // ===================================================================================\r
217     //                                                                 Behavior Query Path\r
218     //                                                                 ===================\r
219     public void setupBehaviorQueryPathIfNeeds() {\r
220             if (!isBehaviorQueryPathEnabled()) {\r
221                     return;\r
222                 }\r
223                 if (_outsideSqlPath.contains(":")) {\r
224                     final String subDirectoryValue = _outsideSqlPath.substring(0, _outsideSqlPath.lastIndexOf(":"));\r
225                     final String subDirectoryPath = replaceString(subDirectoryValue, ":", "/");\r
226                         final String behaviorQueryPath = _outsideSqlPath.substring(_outsideSqlPath.lastIndexOf(":") + ":".length());\r
227                         final String behaviorClassPath = replaceString(buildBehaviorSqlPackageName(), ".", "/");\r
228                         final String behaviorPackagePath = behaviorClassPath.substring(0, behaviorClassPath.lastIndexOf("/"));\r
229                         final String behaviorClassName = behaviorClassPath.substring(behaviorClassPath.lastIndexOf("/") + "/".length());\r
230             _outsideSqlPath = behaviorPackagePath + "/" + subDirectoryPath + "/" + behaviorClassName + "_" + behaviorQueryPath + ".sql";\r
231                 } else {\r
232             _outsideSqlPath = replaceString(buildBehaviorSqlPackageName(), ".", "/") + "_" + _outsideSqlPath + ".sql";\r
233                 }\r
234     }\r
235 \r
236     protected String buildBehaviorSqlPackageName() {\r
237         final DBMeta dbmeta = DBMetaInstanceHandler.findDBMeta(_tableDbName);\r
238         final String behaviorTypeName = dbmeta.getBehaviorTypeName();\r
239         final String outsideSqlPackage = DBFluteConfig.getInstance().getOutsideSqlPackage();\r
240         if (outsideSqlPackage != null && outsideSqlPackage.trim().length() > 0) {\r
241             final String behaviorClassName = behaviorTypeName.substring(behaviorTypeName.lastIndexOf(".") + ".".length());\r
242             String tmp = behaviorTypeName.substring(0, behaviorTypeName.lastIndexOf("."));\r
243             final String exbhvName = tmp.contains(".") ? tmp.substring(tmp.lastIndexOf(".") + ".".length()) : tmp;\r
244             return outsideSqlPackage + "." + exbhvName + "." + behaviorClassName;\r
245         } else {\r
246             return behaviorTypeName;\r
247         }\r
248     }\r
249 \r
250     protected boolean isBehaviorQueryPathEnabled() {\r
251         if (isProcedure()) {// [DBFlute-0.7.5]\r
252             return false;\r
253         }\r
254         return _outsideSqlPath != null && !_outsideSqlPath.contains("/") && !_outsideSqlPath.contains(".") && _tableDbName != null;\r
255     }\r
256 \r
257     // ===================================================================================\r
258     //                                                                       Determination\r
259     //                                                                       =============\r
260     public boolean isSpecifiedOutsideSql() {\r
261         return _outsideSqlPath != null;\r
262     }\r
263 \r
264     // [DBFlute-0.7.5]\r
265     public boolean isProcedure() {\r
266         return _methodName != null && _methodName.startsWith("call");\r
267     }\r
268 \r
269     // ===================================================================================\r
270     //                                                                      General Helper\r
271     //                                                                      ==============\r
272     protected boolean isExistResource(String path) {\r
273         return ResourceUtil.isExist(path);\r
274     }\r
275 \r
276     protected String readText(final String path, String sqlFileEncoding) {\r
277         final java.io.InputStream is = ResourceUtil.getResourceAsStream(path);\r
278         final java.io.Reader reader = InputStreamReaderUtil.create(is, sqlFileEncoding);\r
279         return ReaderUtil.readText(reader);\r
280     }\r
281 \r
282     protected static String replaceString(String text, String fromText, String toText) {\r
283         return SimpleStringUtil.replace(text, fromText, toText);\r
284     }\r
285     \r
286     protected static String getLineSeparator() {\r
287         return SimpleSystemUtil.getLineSeparator();\r
288     }\r
289 \r
290     // ===================================================================================\r
291     //                                                                            Accessor\r
292     //                                                                            ========\r
293     // -----------------------------------------------------\r
294     //                                  Common of OutsideSql\r
295     //                                  --------------------\r
296     public boolean isDynamicBinding() {\r
297         return _dynamicBinding;\r
298     }\r
299 \r
300     public void setDynamicBinding(boolean dynamicBinding) {\r
301         this._dynamicBinding = dynamicBinding;\r
302     }\r
303 \r
304     public boolean isOffsetByCursorForcedly() {\r
305         return _offsetByCursorForcedly;\r
306     }\r
307 \r
308     public void setOffsetByCursorForcedly(boolean offsetByCursorForcedly) {\r
309         this._offsetByCursorForcedly = offsetByCursorForcedly;\r
310     }\r
311     \r
312     public boolean isLimitByCursorForcedly() {\r
313         return _limitByCursorForcedly;\r
314     }\r
315 \r
316     public void setLimitByCursorForcedly(boolean limitByCursorForcedly) {\r
317         this._limitByCursorForcedly = limitByCursorForcedly;\r
318     }\r
319 \r
320     // -----------------------------------------------------\r
321     //                                  Specified OutsideSql\r
322     //                                  --------------------\r
323     public String getOutsideSqlPath() {\r
324         return _outsideSqlPath;\r
325     }\r
326 \r
327     public void setOutsideSqlPath(String outsideSqlPath) {\r
328         this._outsideSqlPath = outsideSqlPath;\r
329     }\r
330 \r
331     public Object getParameterBean() {\r
332         return _parameterBean;\r
333     }\r
334 \r
335     public void setParameterBean(Object parameterBean) {\r
336         this._parameterBean = parameterBean;\r
337     }\r
338 \r
339     public Object getResultTypeSpecification() {\r
340         return _resultTypeSpecification;\r
341     }\r
342 \r
343     public void setResultTypeSpecification(Object resultTypeSpecification) {\r
344         this._resultTypeSpecification = resultTypeSpecification;\r
345     }\r
346 \r
347     public String getMethodName() {\r
348         return _methodName;\r
349     }\r
350 \r
351     public void setMethodName(String methodName) {\r
352         this._methodName = methodName;\r
353     }\r
354     \r
355     public StatementConfig getStatementConfig() {\r
356         return _statementConfig;\r
357     }\r
358 \r
359     public void setStatementConfig(StatementConfig statementConfig) {\r
360         this._statementConfig = statementConfig;\r
361     }\r
362 \r
363     public String getTableDbName() {\r
364         return _tableDbName;\r
365     }\r
366 \r
367     public void setTableDbName(String tableDbName) {\r
368         this._tableDbName = tableDbName;\r
369     }\r
370 }\r