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