    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        public static enum GROUPING_FUNCTIONS { MAX , MIN , SUM , COUNT  ;
    039
    040                /**
    041                 * 与えられた文字が自身に列挙された値の何れかと一致するか検証する。
    042                 * 一致する場合に真を返す。
    043                 * 一致しない場合に偽を返す。
    044                 *
    045                 * @param arg   引数
    046                 * @return      検証の結果
    047                 */
    048                public static boolean contains( final String arg ) {
    049                        for( GROUPING_FUNCTIONS fnc : values() ){
    050                                if ( arg.equalsIgnoreCase( fnc.toString() ) ){
    051                                        return true;
    052                                }
    053                        }
    054                        return false;
    055                }
    056
    057                /**
    058                 * 自身に列挙されている値が与えられた文字列に含まれているか検証する。
    059                 * 含まれている場合は真を返す。
    060                 * 含まれていない場合は偽を返す。
    061                 *
    062                 * @param arg   引数
    063                 * @return      検証の結果
    064                 */
    065                public static boolean search( final String arg ) {
    066                        String argU = arg.toUpperCase(Locale.JAPAN);
    067
    068                        for( GROUPING_FUNCTIONS fnc : values() ){
    069                                if( argU.indexOf( fnc.toString() ) > -1 ) {
    070                                        return true;
    071                                }
    072                        }
    073                        return false;
    074                }
    075        }
    076
    077        /**
    078         * データ上はただの文字列として扱う関数を列挙します。
    079         * (注：現在、列挙中の関数はOracleの内容です。)
    080         *
    081         */
    082        public static enum TREATS_STRING_FUNCTIONS {
    083                CASE ,
    084                CEIL , ROUND , FLOOR , TRUNC , MOD , CHR , CONCAT , SUBSTR , INITCAP ,
    085                SUBSTRB , LOWER , TRIM , LPAD   , LTRIM , UPPER , REPLACE , USER , RPAD ,
    086                ASCII , LENGTH , LENGTHB , INSTR , POSITION , INSTRB  , ADD_MONTHS , DAYOFMONTH ,
    087                MONTHNAME , TIMESTAMPADD , CURDATE , DAYOFWEEK , MONTHS_BETWEEN  , TIMESTAMPDIFF ,
    088                CURRENT_DATE  , DAYOFYEAR , NEXT_DAY  , CURRENT_TIME  , HOUR , NOW , WEEK , CURRENT_TIMESTAMP  ,
    089                LAST_DAY  , YEAR , CURTIME , MINUTE , SECOND , DAYNAME , MONTH , SYSDATE  , CAST , AVG   ,
    090                CONVERT , DATABASE  , TO_CHAR  , DECODE , TO_NUMBER  , EXTRACT , TO_DATE  , GREATEST , STDDEV ,
    091                INTERVAL , VARIANCE , LEAST , LOCATE , NVL  ;
    092
    093                /**
    094                 * 関数の内容に第二引数の内容を付加する処理を実装します
    095                 * 第二引数の内容
    096                 * 0:カラムへ付与するテーブル名(テーブル別名)
    097                 *
    098                 * @param column String
    099                 * @param args String[]
    100                 * @return      関数を更新した結果
    101                 */
    102                public String update( final String column , final String[] args ) {
    103                        return column;
    104                }
    105
    106        }
    107
    108        /**
    109         * 演算子を列挙する。
    110         *
    111         * ●使用例
    112         * WHERE_OPERATORS op = WHERE_OPERATORS.valueOf("eq");
    113         * System.out.println(op.apply("GF92.CLM","{&#064;CLM}",false));
    114         *
    115         * ●上記処理結果
    116         * GF92.CLM     =       '{&#064;CLM}'
    117         *
    118         */
    119        public static enum WHERE_OPERATORS {
    120                eq() {
    121                        public String apply(final String left , final String right, final boolean is_num) {
    122                                if ( is_num ){
    123                                        return leftVal(left) + "=\t " + right ;
    124                                }else {
    125                                        return leftVal(left) + "=\t '" + right + "'";
    126                                }
    127                        }
    128                        public String[] symbol(){
    129                                return new String[] {"="};
    130                        }
    131                }  ,
    132                lk1() {
    133                        public String apply(final String left , final String right, final boolean is_num) {
    134                                return leftVal(left) + "like '" + right + "%'";
    135                        }
    136                        public String[] symbol(){
    137                                return new String[] {"like","","%"};
    138                        }
    139                }  ,
    140                lk2() {
    141                        public String apply(final String left , final String right, final boolean is_num) {
    142                                return leftVal(left) + "like '%" + right + "'";
    143                        }
    144                        public String[] symbol(){
    145                                return new String[] {"like","%",""};
    146                        }
    147                }  ,
    148                lk3() {
    149                        public String apply(final String left , final String right, final boolean is_num) {
    150                                return leftVal(left) + "like '%" + right + "%'";
    151                        }
    152                        public String[] symbol(){
    153                                return new String[] {"like","%","%"};
    154                        }
    155                }  ,
    156                gt() {
    157                        public String apply(final String left , final String right, final boolean is_num) {
    158                                if ( is_num ) {
    159                                        return leftVal(left) + ">\t " + right + "";
    160                                }else{
    161                                        return leftVal(left) + ">\t '" + right + "'";
    162                                }
    163                        }
    164                        public String[] symbol(){
    165                                return new String[] {">"};
    166                        }
    167                }  ,
    168                ge() {
    169                        public String apply(final String left , final String right, final boolean is_num) {
    170                                if ( is_num ) {
    171                                        return leftVal(left) + ">=\t " + right + "";
    172                                }else{
    173                                        return leftVal(left) + ">=\t '" + right + "'";
    174                                }
    175                        }
    176                        public String[] symbol(){
    177                                return new String[] {">="};
    178                        }
    179                }  ,
    180                lt()  {
    181                        public String apply(final String left , final String right, final boolean is_num) {
    182                                if ( is_num ) {
    183                                        return leftVal(left) + "<\t " + right + "";
    184                                }else {
    185                                        return leftVal(left) + "<\t '" + right + "'";
    186                                }
    187                        }
    188                        public String[] symbol(){
    189                                return new String[] {"<"};
    190                        }
    191                }  ,
    192                le()  {
    193                        public String apply(final String left , final String right, final boolean is_num) {
    194                                if ( is_num ){
    195                                        return leftVal(left) + "<=\t " + right + "";
    196                                }else{
    197                                        return leftVal(left) + "<=\t '" + right + "'";
    198                                }
    199                        }
    200                        public String[] symbol(){
    201                                return new String[] {"<="};
    202                        }
    203                }  ,
    204                not() {
    205                        public String apply(final String left , final String right, final boolean is_num) {
    206                                if ( is_num ) {
    207                                        return leftVal(left) + "!=\t " + right + "";
    208                                } else {
    209                                        return leftVal(left) + "!=\t '" + right + "'";
    210                                }
    211                        }
    212                        public String[] symbol(){
    213                                return new String[] {"!="};
    214                        }
    215                } ,
    216                bw()  {
    217                        public String apply(final String left , final String right, final boolean is_num) {
    218                                if ( is_num ) {
    219                                        return leftVal(left) + "between " + betweenFormat( right , "_FROM" ) + " and " + betweenFormat( right , "_TO" ) + "";
    220                                }else {
    221                                        return leftVal(left) + "between '" + betweenFormat( right , "_FROM" ) + "' and '" + betweenFormat( right , "_TO" ) + "'";
    222                                }
    223                        }
    224                        public String[] symbol(){
    225                                return new String[] {"between"};
    226                        }
    227                } ,
    228                in() {
    229                        public String apply(final String left , final String right, final boolean is_num) {
    230                                return leftVal(left) + "in\t (" +inFormat( right , is_num ) + ")";
    231                        }
    232                        public String[] symbol(){
    233                                return new String[] {"in"};
    234                        }
    235                } ,
    236                ;
    237
    238                static final String[] TABS = new String[] { "\t\t\t\t" , "\t\t\t" , "\t\t" , "\t" };            // 5.6.4.4 (2013/05/31)
    239
    240                /**
    241                 * 演算子の記号を略語に変換する。
    242                 *
    243                 * @og.rev 5.6.4.4 (2013/05/31) タブによる位置合わせの計算方法修正。
    244                 *
    245                 * @param left  引数
    246                 * @return      演算子の記号の略語
    247                 */
    248                static String leftVal( final String left ) {
    249                        int adrs = ((left.length()-1)/4 > 3 ) ? 3 : (left.length()-1)/4 ;
    250                        return left + TABS[adrs] ;                                                                                              // ４タブを想定。
    251                }
    252
    253                /**
    254                 * 与えられた左辺と右辺を元に演算子付きの文字列を作成する。
    255                 * 第３引数のbooleanは、trueの時に値が数値であることを意味する。
    256                 *
    257                 * @param left String
    258                 * @param right String
    259                 * @param is_num boolean
    260                 * @return      演算子を加えた結果
    261                 */
    262                abstract public String apply(final String left , final String right , final boolean is_num);
    263
    264                /**
    265                 * 演算子を返却する。
    266                 *
    267                 * @return String[] 演算子
    268                 */
    269                abstract public String[] symbol();
    270
    271                /**
    272                 * IN句の値を組み立てなおします。
    273                 *
    274                 * @param str String
    275                 * @param is_number boolean
    276                 * @return      IN句のフォーマット
    277                 */
    278                static String inFormat(final String str , final boolean is_number){
    279                        StringBuilder formated = new StringBuilder("");
    280                        String[] ins = str.split( "," );
    281                        for (String in :ins ){
    282                                if (formated.length() > 0 ){
    283                                        formated.append( "," );
    284                                }
    285                                if ( is_number ) {
    286                                        formated.append( in );
    287                                }else{
    288                                        formated.append( "'" ).append( in ).append( "'" );
    289                                }
    290                        }
    291
    292                        return formated.toString();
    293
    294                }
    295
    296                /**
    297                 * BETWEENを組み立てなおす。
    298                 *
    299                 * @param str String
    300                 * @param suffix String
    301                 * @return      BETWEENのフォーマット
    302                 */
    303                static String betweenFormat(final String str , final String suffix){
    304                        StringBuilder sb = new StringBuilder(str);
    305                        if ( str.indexOf("{@") == 0 ){
    306                                sb.insert( sb.length() - 1 , suffix );
    307                        }else{
    308                                sb.append( suffix );
    309                        }
    310                        return sb.toString();
    311                }
    312
    313                static Pattern LK1_PTN = Pattern.compile("like\\s+\\'\\{@(\\w*?)\\}%\\'");
    314                static Pattern LK2_PTN = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}\\'");
    315                static Pattern LK3_PTN = Pattern.compile("like\\s+\\'%\\{@(\\w*?)\\}%\\'");
    316
    317                /**
    318                 * 演算子の記号を略語に変換する。
    319                 *
    320                 * @param arg   引数
    321                 * @return      演算子の記号の略語
    322                 */
    323                static String convert(final String arg){
    324                        for( WHERE_OPERATORS fnc : values() ){
    325                                if ( fnc.symbol().length == 1 && arg.trim().indexOf( fnc.symbol()[0] ) == 0 ){
    326                                        return fnc.toString();
    327                                }
    328                                if( fnc.symbol().length == 3){
    329                                        Matcher matcher = LK1_PTN.matcher( arg );
    330                                        if (matcher.find()){
    331                                                return lk1.toString();
    332                                        }
    333                                        matcher = LK2_PTN.matcher( arg );
    334                                        if (matcher.find()){
    335                                                return lk2.toString();
    336                                        }
    337                                        matcher = LK3_PTN.matcher( arg );
    338                                        if (matcher.find()){
    339                                                return lk3.toString();
    340                                        }
    341                                }
    342                        }
    343                        return "";
    344                }
    345        }
    346}