001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.develop;
017
018import java.util.regex.Matcher;
019import java.util.regex.Pattern;
020import java.util.Locale;
021
022/**
023 * JSPの生成・データ取り込み処理で必要な列挙型をまとめたクラス。
024 *
025 * 主にキーワード管理とプログラム中のswitch文の削減を目的として作成。
026 *
027 *
028 * @author Takeshi.Takada
029 *
030 */
031public class JspEnumeration {
032        /**
033         * GROUP BY句を必要とする関数を列挙します。
034         *
035         * contains、searchと言った独自メソッドも実装しています。
036         *
037         */
038//      protected static enum GROUPING_FUNCTIONS { MAX , MIN , SUM , COUNT , max , min , sum , count ;
039        public static enum GROUPING_FUNCTIONS { MAX , MIN , SUM , COUNT  ;
040
041                /**
042                 * 与えられた文字が自身に列挙された値の何れかと一致するか検証する。
043                 * 一致する場合に真を返す。
044                 * 一致しない場合に偽を返す。
045                 *
046                 * @param arg   引数
047                 * @return      検証の結果
048                 */
049                public static boolean contains( final String arg ) {
050                        for( GROUPING_FUNCTIONS fnc : values() ){
051//                              if ( arg.equals( fnc.toString() ) ){
052                                if ( arg.equalsIgnoreCase( fnc.toString() ) ){
053                                        return true;
054                                }
055                        }
056                        return false;
057                }
058
059                /**
060                 * 自身に列挙されている値が与えられた文字列に含まれているか検証する。
061                 * 含まれている場合は真を返す。
062                 * 含まれていない場合は偽を返す。
063                 *
064                 * @param arg   引数
065                 * @return      検証の結果
066                 */
067                public static boolean search( final String arg ) {
068                        String argU = arg.toUpperCase(Locale.JAPAN);
069
070                        for( GROUPING_FUNCTIONS fnc : values() ){
071//                              if( arg.indexOf( fnc.toString() ) > -1 ) {
072                                if( argU.indexOf( fnc.toString() ) > -1 ) {
073                                        return true;
074                                }
075                        }
076                        return false;
077                }
078        }
079
080        /**
081         * データ上はただの文字列として扱う関数を列挙します。
082         * (注:現在、列挙中の関数はOracleの内容です。)
083         *
084         */
085        public static enum TREATS_STRING_FUNCTIONS {
086                CASE ,
087                CEIL , ROUND , FLOOR , TRUNC , MOD , CHR , CONCAT , SUBSTR , INITCAP ,
088                SUBSTRB , LOWER , TRIM , LPAD   , LTRIM , UPPER , REPLACE , USER , RPAD ,
089                ASCII , LENGTH , LENGTHB , INSTR , POSITION , INSTRB  , ADD_MONTHS , DAYOFMONTH ,
090                MONTHNAME , TIMESTAMPADD , CURDATE , DAYOFWEEK , MONTHS_BETWEEN  , TIMESTAMPDIFF ,
091                CURRENT_DATE  , DAYOFYEAR , NEXT_DAY  , CURRENT_TIME  , HOUR , NOW , WEEK , CURRENT_TIMESTAMP  ,
092                LAST_DAY  , YEAR , CURTIME , MINUTE , SECOND , DAYNAME , MONTH , SYSDATE  , CAST , AVG   ,
093                CONVERT , DATABASE  , TO_CHAR  , DECODE , TO_NUMBER  , EXTRACT , TO_DATE  , GREATEST , STDDEV ,
094                INTERVAL , VARIANCE , LEAST , LOCATE , NVL  ;
095
096                /**
097                 * 関数の内容に第二引数の内容を付加する処理を実装します
098                 * 第二引数の内容
099                 * 0:カラムへ付与するテーブル名(テーブル別名)
100                 *
101                 * @param column String
102                 * @param args String[]
103                 * @return      関数を更新した結果
104                 */
105                public String update( final String column , final String[] args ) {
106                        return column;
107                }
108
109        }
110
111        /**
112         * 演算子を列挙する。
113         *
114         * ●使用例
115         * WHERE_OPERATORS op = WHERE_OPERATORS.valueOf("eq");
116         * System.out.println(op.apply("GF92.CLM","{@CLM}",false));
117         *
118         * ●上記処理結果
119         * GF92.CLM     =       '{@CLM}'
120         *
121         */
122        public static enum WHERE_OPERATORS {
123                eq() {
124                        public String apply(final String left , final String right, final boolean is_num) {
125                                if ( is_num ){
126                                        return leftVal(left) + "=\t " + right ;
127                                }else {
128                                        return leftVal(left) + "=\t '" + right + "'";
129                                }
130                        }
131                        public String[] symbol(){
132                                return new String[] {"="};
133                        }
134                }  ,
135                lk1() {
136                        public String apply(final String left , final String right, final boolean is_num) {
137                                return leftVal(left) + "like '" + right + "%'";
138                        }
139                        public String[] symbol(){
140                                return new String[] {"like","","%"};
141                        }
142                }  ,
143                lk2() {
144                        public String apply(final String left , final String right, final boolean is_num) {
145                                return leftVal(left) + "like '%" + right + "'";
146                        }
147                        public String[] symbol(){
148                                return new String[] {"like","%",""};
149                        }
150                }  ,
151                lk3() {
152                        public String apply(final String left , final String right, final boolean is_num) {
153                                return leftVal(left) + "like '%" + right + "%'";
154                        }
155                        public String[] symbol(){
156                                return new String[] {"like","%","%"};
157                        }
158                }  ,
159                gt() {
160                        public String apply(final String left , final String right, final boolean is_num) {
161                                if ( is_num ) {
162                                        return leftVal(left) + ">\t " + right + "";
163                                }else{
164                                        return leftVal(left) + ">\t '" + right + "'";
165                                }
166                        }
167                        public String[] symbol(){
168                                return new String[] {">"};
169                        }
170                }  ,
171                ge() {
172                        public String apply(final String left , final String right, final boolean is_num) {
173                                if ( is_num ) {
174                                        return leftVal(left) + ">=\t " + right + "";
175                                }else{
176                                        return leftVal(left) + ">=\t '" + right + "'";
177                                }
178                        }
179                        public String[] symbol(){
180                                return new String[] {">="};
181                        }
182                }  ,
183                lt()  {
184                        public String apply(final String left , final String right, final boolean is_num) {
185                                if ( is_num ) {
186                                        return leftVal(left) + "<\t " + right + "";
187                                }else {
188                                        return leftVal(left) + "<\t '" + right + "'";
189                                }
190                        }
191                        public String[] symbol(){
192                                return new String[] {"<"};
193                        }
194                }  ,
195                le()  {
196                        public String apply(final String left , final String right, final boolean is_num) {
197                                if ( is_num ){
198                                        return leftVal(left) + "<=\t " + right + "";
199                                }else{
200                                        return leftVal(left) + "<=\t '" + right + "'";
201                                }
202                        }
203                        public String[] symbol(){
204                                return new String[] {"<="};
205                        }
206                }  ,
207                not() {
208                        public String apply(final String left , final String right, final boolean is_num) {
209                                if ( is_num ) {
210                                        return leftVal(left) + "!=\t " + right + "";
211                                } else {
212                                        return leftVal(left) + "!=\t '" + right + "'";
213                                }
214                        }
215                        public String[] symbol(){
216                                return new String[] {"!="};
217                        }
218                } ,
219                bw()  {
220                        public String apply(final String left , final String right, final boolean is_num) {
221                                if ( is_num ) {
222                                        return leftVal(left) + "between " + betweenFormat( right , "_FROM" ) + " and " + betweenFormat( right , "_TO" ) + "";
223                                }else {
224                                        return leftVal(left) + "between '" + betweenFormat( right , "_FROM" ) + "' and '" + betweenFormat( right , "_TO" ) + "'";
225                                }
226                        }
227                        public String[] symbol(){
228                                return new String[] {"between"};
229                        }
230                } ,
231                in() {
232                        public String apply(final String left , final String right, final boolean is_num) {
233                                return leftVal(left) + "in\t (" +inFormat( right , is_num ) + ")";
234                        }
235                        public String[] symbol(){
236                                return new String[] {"in"};
237                        }
238                } ,
239                ;
240
241//              static final String[] TABS = new String[] { "\t\t\t" , "\t\t" , "\t" };
242                static final String[] TABS = new String[] { "\t\t\t\t" , "\t\t\t" , "\t\t" , "\t" };            // 5.6.4.4 (2013/05/31)
243
244                /**
245                 * 演算子の記号を略語に変換する。
246                 *
247                 * @og.rev 5.6.4.4 (2013/05/31) タブによる位置合わせの計算方法修正。
248                 *
249                 * @param left  引数
250                 * @return      演算子の記号の略語
251                 */
252                static String leftVal( final String left ) {
253//                      return left + TABS[Math.max( left.length()/4, TABS.length-1 )] ;                // 4タブを想定。
254
255                        int adrs = ((left.length()-1)/4 > 3 ) ? 3 : (left.length()-1)/4 ;
256                        return left + TABS[adrs] ;                                                                                              // 4タブを想定。
257                }
258
259                /**
260                 * 与えられた左辺と右辺を元に演算子付きの文字列を作成する。
261                 * 第3引数のbooleanは、trueの時に値が数値であることを意味する。
262                 *
263                 * @param left String
264                 * @param right String
265                 * @param is_num boolean
266                 * @return      演算子を加えた結果
267                 */
268                abstract public String apply(final String left , final String right , final boolean is_num);
269
270                /**
271                 * 演算子を返却する。
272                 *
273                 * @return String[] 演算子
274                 */
275                abstract public String[] symbol();
276
277                /**
278                 * IN句の値を組み立てなおします。
279                 *
280                 * @param str String
281                 * @param is_number boolean
282                 * @return      IN句のフォーマット
283                 */
284                static String inFormat(final String str , final boolean is_number){
285                        StringBuilder formated = new StringBuilder("");
286                        String[] ins = str.split( "," );
287                        for (String in :ins ){
288                                if (formated.length() > 0 ){
289                                        formated.append( "," );
290                                }
291                                if ( is_number ) {
292                                        formated.append( in );
293                                }else{
294                                        formated.append( "'" ).append( in ).append( "'" );
295                                }
296                        }
297
298                        return formated.toString();
299
300                }
301
302                /**
303                 * BETWEENを組み立てなおす。
304                 *
305                 * @param str String
306                 * @param suffix String
307                 * @return      BETWEENのフォーマット
308                 */
309                static String betweenFormat(final String str , final String suffix){
310                        StringBuilder sb = new StringBuilder(str);
311                        if ( str.indexOf("{@") == 0 ){
312                                sb.insert( sb.length() - 1 , suffix );
313                        }else{
314                                sb.append( suffix );
315                        }
316                        return sb.toString();
317                }
318
319                static Pattern LK1_PTN = Pattern.compile("like\\s+\\'\\{@(\\w*?)\\}%\\'");
320                static Pattern LK2_PTN = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}\\'");
321                static Pattern LK3_PTN = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}%\\'");
322
323                /**
324                 * 演算子の記号を略語に変換する。
325                 *
326                 * @param arg   引数
327                 * @return      演算子の記号の略語
328                 */
329                static String convert(final String arg){
330                        for( WHERE_OPERATORS fnc : values() ){
331                                if ( fnc.symbol().length == 1 && arg.trim().indexOf( fnc.symbol()[0] ) == 0 ){
332                                        return fnc.toString();
333                                }
334                                if( fnc.symbol().length == 3){
335//                                      Matcher matcher = Pattern.compile("like\\s+\\'\\{@(\\w*?)\\}%\\'").matcher( arg );
336                                        Matcher matcher = LK1_PTN.matcher( arg );
337                                        if (matcher.find()){
338                                                return lk1.toString();
339                                        }
340//                                      matcher = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}\\'").matcher( arg );
341                                        matcher = LK2_PTN.matcher( arg );
342                                        if (matcher.find()){
343                                                return lk2.toString();
344                                        }
345//                                      matcher = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}%\\'").matcher( arg );
346                                        matcher = LK3_PTN.matcher( arg );
347                                        if (matcher.find()){
348                                                return lk3.toString();
349                                        }
350                                }
351                        }
352                        return "";
353                }
354        }
355
356}