    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.fukurou.util;
    017
    018import java.util.ArrayList;
    019import java.util.Map;
    020import java.util.HashMap;
    021
    022/**
    023 * SystemParameter は、{&#064;XXXX} 文字列を処理するクラスです。
    024 * このクラスでは、{&#064;XXXX} 文字列を別の文字列と置き換えることや、
    025 * 予め予約されている予約語 {&#064;DATE.XXXX} 文字列を置き換えます。
    026 * 通常の {&#064;XXXX} 文字列の置き換えは、キーと値のペアを、HybsEntry オブジェクトに
    027 * セットして、その配列を受け取って処理します。
    028 *
    029 * 以下の値はあらかじめ、動的に作成されます。
    030 * ・DATE.YMD       ８byte の今日のシステム日付(yyyyMMdd)
    031 * ・DATE.YMDH    １４byte の今日のシステム日時(yyyyMMddHHmmss)
    032 * ・DATE.HMS       ６byte の今日のシステム時間(HHmmss)
    033 *
    034 * @og.group ユーティリティ
    035 *
    036 * @version  4.0
    037 * @author   Kazuhiko Hasegawa
    038 * @since    JDK5.0,
    039 */
    040public final class SystemParameter {
    041
    042        /** 改行コード */
    043        public static final String CR = System.getProperty("line.separator");   // 5.1.9.0 (2010/08/01) 追加
    044
    045        private final String    original ;
    046
    047        private final String[] clms;
    048        private final String[] formats;
    049
    050        /**
    051         *  {&#064;XXXX} の特殊文字を含む文字列を、置き換えます。
    052         * 対象外の文字列は、そのまま、残されます。
    053         *
    054         * @og.rev 5.1.8.0 (2010/07/01) パース方法見直し(StringTokenizerでは、{&#064;XXXX}が連続してある場合に対応できない)
    055         * @og.rev 5.3.2.0 (2011/02/01) original データを、パース結果を利用するように修正する。
    056         * @og.rev 5.3.4.0 (2011/04/01) {&#064;DATE.XXXX} を処理できるように機能追加
    057         * @og.rev 5.3.5.0 (2011/05/01) {&#064;SYS.XXXX} は、廃止
    058         * @og.rev 5.5.7.2 (2012/10/09) rightNow をCalendarオブジェクト ではなく、String時刻とします。
    059         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
    060         *
    061         * @param       orig    変換する文字列(オリジナル)
    062         */
    063        public SystemParameter( final String orig ) {
    064                if( orig == null || orig.length() == 0 || orig.indexOf( "{@" ) < 0 ) {
    065                        clms     = null;
    066                        formats  = null;
    067                        original = orig;                // 5.3.2.0 (2011/02/01)
    068                }
    069                else {
    070                        StringBuilder buf = new StringBuilder(orig.length());           // 5.3.2.0 (2011/02/01)
    071
    072                        ArrayList<String> fmtList = new ArrayList<String>();
    073                        ArrayList<String> clmList = new ArrayList<String>();
    074
    075                        // 5.1.8.0 (2010/07/01) パース方法見直し
    076                        int start = 0;
    077                        int index = orig.indexOf( "{@" );
    078                        String val ;
    079                        while( index >= 0 ) {
    080                                val = orig.substring( start, index );                                   // 5.3.4.0 (2011/04/01)
    081                                buf.append(  val );
    082                                fmtList.add( val );
    083                                int end = orig.indexOf( '}',index );
    084                                if( end < 0 ) {
    085                                        String errMsg = "{@ と } との対応関係がずれています。" + CR
    086                                                                + "str=[" + orig + "] : index=" + index ;
    087                                        throw new RuntimeException( errMsg );
    088                                }
    089                                String param = orig.substring( index+2,end );
    090                                if( param.startsWith( "DATE." ) ) {             // 5.3.5.0 (2011/05/01) {&#064;SYS.XXXX} は、廃止
    091                                        val = getDateFormat( param.substring( 5 ) );    // 5.5.7.2 (2012/10/09) HybsDateUtil を利用時に "DATE." は不要
    092                                        clmList.add( null );            // パースした場合は、clmList は、使用しない。
    093                                        buf.append( val );
    094                                }
    095                                else {
    096                                        clmList.add( param );
    097                                        buf.append( "{@" ).append( param ).append( "}" );               // 元のままの文字列を生成
    098                                }
    099                                start = end+1;
    100                                index = orig.indexOf( "{@",start );
    101                        }
    102                        val = orig.substring( start, orig.length() );                           // 5.3.4.0 (2011/04/01)
    103                        buf.append(  val );
    104                        fmtList.add( val );
    105
    106                        original = buf.toString();              // 5.3.2.0 (2011/02/01)
    107                        if( original.indexOf( "{@" ) < 0 ) {
    108                                clms     = null;
    109                                formats  = null;
    110                        }
    111                        else {
    112                                clms    = clmList.toArray( new String[clmList.size()] );
    113                                formats = fmtList.toArray( new String[fmtList.size()] );
    114                        }
    115                }
    116        }
    117
    118        /**
    119         * 日付関係の情報を簡易的に取り出す処理を行います。
    120         *
    121         * 引数は、"XXXX AA BB CC" という状態で受け取ります。
    122         *
    123         * 処理の詳細は、{@link org.opengion.fukurou.util.HybsDateUtil#getDateFormat( String,String,String,int ) }
    124         * または、{@link org.opengion.hayabusa.taglib.CommonTagSupport#getDateFormat( String ) } を
    125         * 参照してください。
    126         *
    127         * @og.rev 5.3.4.0 (2011/04/01) 新規追加
    128         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
    129         * @og.rev 5.5.8.2 (2012/11/09) prmA の判定に、null と ゼロ文字列を判定する。
    130         * @og.rev 5.7.4.1 (2014/03/14) AA 引数の@解析後のコマンド判定方法を、８ケタ以下から先頭が数字以外に変更します。
    131         * @og.rev 5.7.4.1 (2014/03/14) taglib.CommonTagSupport#getDateFormat( String ) と処理を合わせます。
    132         * @og.rev 5.7.4.2 (2014/03/20) リクエストパラメータ(@で始まる引数)は使えません。
    133         *
    134         * @param   value パラメータ(引数は、"DATE.XXXX AA BB" などという状態)
    135         *
    136         * @return   メッセージ情報
    137         * @see         org.opengion.fukurou.util.HybsDateUtil#getDateFormat( String,String,String,int )
    138         * @see         org.opengion.hayabusa.taglib.CommonTagSupport#getDateFormat( String )
    139         */
    140        private String getDateFormat( final String value ) {
    141                // 5.7.4.1 (2014/03/14) taglib.CommonTagSupport#getDateFormat( String ) と処理を合わせます。
    142                String[] vals = StringUtil.csv2Array( value,' ' );
    143
    144                String key = vals[0] ;
    145
    146                String prmA = (vals.length >= 2) ? vals[1] : null ;
    147                String prmB = (vals.length >= 3) ? vals[2] : null ;
    148                String prmC = (vals.length >= 4) ? vals[vals.length-1] : null ;         // 互換性。最後の値が、CC引数
    149
    150                // 5.7.4.2 (2014/03/20) 現時点では、SystemParameter 処理にはリクエスト変数は使えないので、@変数も使えない。
    151                if( prmA != null && prmA.startsWith( "@" ) ) {
    152                        String errMsg = "AA引数に、リクエストパラメータ(@で始まる引数)は使えません。value=[" + value + "]" ;
    153                        throw new RuntimeException( errMsg );
    154                }
    155
    156                if( prmB != null && prmB.startsWith( "@" ) ) {
    157                        String errMsg = "BB引数に、リクエストパラメータ(@で始まる引数)は使えません。value=[" + value + "]" ;
    158                        throw new RuntimeException( errMsg );
    159                }
    160
    161                if( prmC != null && prmC.startsWith( "@" ) ) {
    162                        String errMsg = "CC引数に、リクエストパラメータ(@で始まる引数)は使えません。value=[" + value + "]" ;
    163                        throw new RuntimeException( errMsg );
    164                }
    165
    166                // 5.7.4.1 (2014/03/14) AA 引数の@解析後のコマンド判定方法を、８ケタ以下から先頭が数字以外に変更します。
    167                if( prmA != null && prmA.length() > 0 ) {
    168                        char chA = prmA.charAt(0);
    169                        if( chA < '0' || chA > '9' ) {          // 先頭が、数字以外の場合は、コマンドなので、一つずつずらす。
    170                                prmC = prmB;
    171                                prmB = prmA;
    172                                prmA = null;
    173                        }
    174                }
    175
    176                // 5.7.4.1 (2014/03/14) CC 引数を、"H" , "D" , "M" 以外でも使用できるように拡張します。
    177                int intC = 0;
    178                if( prmC != null && prmC.length() > 0 ) {
    179                        try {
    180                                intC = Integer.parseInt( prmC );
    181                        }
    182                        catch( NumberFormatException ex ) {
    183                                String errMsg = "CC引数が数字ではありません。value=[" + value + "]"
    184                                                                + ex.getMessage() ;
    185                                System.err.println( errMsg );
    186                        }
    187                }
    188
    189                // prmA が null か、isEmpty() の場合は、現在時刻が使用される。
    190                return HybsDateUtil.getDateFormat( key,prmA,prmB,intC );        // 5.7.4.1 (2014/03/14) CC 引数を拡張します。
    191        }
    192
    193        /**
    194         *  {&#064;XXXX} の特殊文字を含む文字列を、置き換えます。
    195         * 対象外の文字列は、そのまま、残されます。
    196         *
    197         * @og.rev 5.3.4.0 (2011/04/01) 判定方法 修正
    198         *
    199         * @param       entry   置換文字列のキーと値のペアを管理しているEntryオブジェクトの配列
    200         *
    201         * @return      置換後の文字列
    202         */
    203        public String replace( final HybsEntry[] entry ) {
    204                if( formats == null ) { return original; }              // 5.3.4.0 (2011/04/01) 判定方法 修正
    205                if( entry == null || entry.length == 0 ) { return original; }
    206
    207                // HybsEntry[] データを、Mapにマッピングします。
    208                Map<String, String> sysMap = new HashMap<String, String>();
    209                int size = entry.length;
    210                for( int i=0; i<size; i++ ) {
    211                        sysMap.put( entry[i].getKey(),entry[i].getValue() );
    212                }
    213
    214                return replace( sysMap );
    215        }
    216
    217        /**
    218         *  {&#064;XXXX} の特殊文字を含む文字列を、置き換えます。
    219         * 対象外の文字列は、そのまま、残されます。
    220         *
    221         * @param  map  置換文字列のキーと値のペアを管理しているMapオブジェクト
    222         *
    223         * @return      置換後の文字列
    224         */
    225        public String replace( final Map<String,String> map ) {
    226                if( formats == null ) { return original; }              // 5.3.4.0 (2011/04/01) 判定方法 修正
    227                if( map == null || map.isEmpty() ) { return original; }
    228
    229                StringBuilder sb = new StringBuilder();
    230                for( int i=0; i<formats.length; i++ ) {
    231                        sb.append( formats[i] );
    232                        if( i < clms.length && clms[i] != null ) {              // 5.3.4.0 (2011/04/01) nullチェック追加
    233                                sb.append(  StringUtil.nval( map.get( clms[i] ), "" ) );
    234                        }
    235                }
    236
    237                return sb.toString();
    238        }
    239
    240        /**
    241         * フォーマットをパースした結果から、カラム一覧を配列形式で返します。
    242         *
    243         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
    244         *
    245         * @return カラム配列
    246         */
    247        public String[] getColumns() {
    248                if( clms == null ) { return new String[0]; }
    249                return clms.clone();
    250        }
    251
    252        /**
    253         * フォーマットをパースした結果から、フォーマット一覧を配列形式で返します。
    254         *
    255         * @og.rev 5.1.7.0 (2010/06/01) 新規作成
    256         *
    257         * @return フォーマット配列
    258         */
    259        public String[] getFormats() {
    260                if( formats == null ) { return new String[0]; }
    261                return formats.clone();
    262        }
    263}