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     */
016    package org.opengion.fukurou.util;
017    
018    import java.util.Map;
019    import java.util.LinkedHashMap;
020    import java.util.List;
021    import java.util.ArrayList;
022    import java.util.Iterator;
023    import java.util.Arrays;
024    import java.util.Date;
025    import java.util.Locale;
026    
027    import java.text.DateFormat;
028    import java.text.SimpleDateFormat;
029    
030    /**
031     * Argument は、バãƒ?ƒ�処ç�?? main メソãƒ?ƒ‰の引数を解析するクラスですã?
032     * Argument はã€?¼“つのタイプにåˆ?�‹れますã?
033     *
034     * ?»コメント]  ??# で始まる引数で、使用されませんã€?登録もされませんã€?
035     * ?»引数?½      ??#,-,= 以外で始まるé?常のæ–?­—å?。登録のé ?•ªが指定されますã?
036     * ?»プロパティ?½??- で始まりã?キーと値ã‚?で区åˆ?�£てã�?‚‹パラメータですã?é ?º�ã?無関係ã?
037     *
038     * これらã?タイプを混在させても構いませんã€?引数]は、[コメンãƒ? や[プロパティ]ã‚?
039     * 無視したã?入力ã?é ?•ªが重要視されますã?取り出すå?合も、番号で取り出しますã?
040     * æœ??の?»引数?½がã?0 で、以é™?引数個数-1 までの番号で取り出しますã?
041     * ?»プロパティ?½はã€??番は無視し、キー部を指定することで取り出せますã?
042     * ただしã?キー部を重è¤?�—て登録することは出来ません。なおã?キー部の頭のæ–?­—å?のみで
043     * 取り出すメソãƒ?ƒ‰があるためã?key1,key2,key3 などとæŒ?®šして、key で取り出せã?ã€?
044     * è¤?•°プロパティを同ä¸?‚­ーで取り出すことが可能ですã?
045     * ?»プロパティ?½のæŒ?®šでは、キーと値ã‚?で区åˆ?‚Šますが、その前後にスペã?スã‚?
046     * 入れなã�?�§下さã�??引数の前後に = が付くæ–?­—å?はæŒ?®šできませんã€?
047     *
048     * java Program AAA BBB #CCC -DD=XX -EE=YY -FF=ZZ GGG
049     *              ~~~ ~~~ ~~~~ ~~~~~~ ~~~~~~ ~~~~~~ ~~~
050     * ?»コメント]  ??#CCC
051     * ?»引数?½      ??[0]=AAA , [1]=BBB , [2]=GGG
052     * ?»プロパティ?½??key=DD,val=XX  key=EE,val=YY  key=FF,val=ZZ
053     *
054     * Argument の整合æ?チェãƒ?‚¯はã€?¼“つのパターンがありますã?
055     *
056     * ?»引数?½個数æŒ?®??š引数自身のæœ?°�å?数、最大個数を登録しておくことで、ã?ロパティのハイフン忘れ等を防止しますã?
057     * ?»プロパティ?½å¿??チェãƒ?‚¯ ?šå¿??キーが登録されたかどã�?�‹のチェãƒ?‚¯を行いますã?
058     * ?»プロパティ?½整合æ?チェãƒ?‚¯ ??æŒ?®šされてã�?‚‹キーのみ登録可能ですã?
059     *
060     * これらã?チェãƒ?‚¯で、整合æ?チェãƒ?‚¯のみ、Argument の登録時に行いますã?
061     * それ以外ã?、取りå?し時まで、判断できませんã€?
062     * (取り出しã?、登録がすべて終äº?�—たã?ちに行われると仮定してã�?�¾ã�?
063     *
064     * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
065     * ?»プロパティ?½設定可能なプロパティの値を指定することで、誤記å?を防止しますã?
066     *
067     * @version  4.0
068     * @author   Kazuhiko Hasegawa
069     * @since    JDK5.0,
070     */
071    public final class Argument  {
072            /** Argument引数のタイãƒ??»コメント]は、無視されますã? {@value}  */
073            public static final int CMNT = 0;       // ?»コメント]
074    
075            /** Argument引数のタイãƒ??»引数?½は、å?力é?にアクセスできますã? {@value}  */
076            public static final int ARGS = 1;       // ?»引数?½
077    
078            /** Argument引数のタイãƒ??»プロパティ?½はã€?KEY=VALUE 形式でキーでアクセスできますã? {@value}  */
079            public static final int PROP = 2;       // ?»プロパティ?½
080    
081            private static final String CR = System.getProperty("line.separator");
082    
083            private boolean argOkFlag = false;
084            private final List<String> argments = new ArrayList<String>();
085            private final Map<String,String> proparty = new LinkedHashMap<String,String>();
086    
087            private int argRangeMin = 0;
088            private int argRangeMax = 200 ;         // 本当ã?、Windows の引数の上限値を設å®?
089    
090            private Map<String,String> mustProparty   = null;
091            private Map<String,String> usableProparty = null;
092    
093            private final String programID  ;
094    
095            /**
096             * こã? Argument を使用してã�?‚‹ プログラãƒ?D(Javaクラスå�?を指定して
097             * インスタンスを作æ?しますã?
098             * toString() する際に、表示しますã?
099             *
100             * @param   pgid プログラãƒ?D
101             */
102            public Argument( final String pgid ) {
103                    programID = pgid;
104            }
105    
106            /**
107             * Argument の配å?æ–?­—å?から、引数ã‚??ロパティをセãƒ?ƒˆしますã?
108             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
109             * これは、main メソãƒ?ƒ‰等で単独起動するå?合に、引数そã?ままã‚?
110             * セãƒ?ƒˆする場合に使用しますã?
111             *
112             * @param   args 引数配å?æ–?­—å?
113             * @see  #putArgument( String )
114             */
115            public void setArgument( final String[] args ) {
116                    for( int i=0; i<args.length; i++ ) {
117                            putArgument( args[i] );
118                    }
119            }
120    
121            /**
122             * Argument のæ–?­—å?から、引数かã?ロパティをセãƒ?ƒˆしますã?
123             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
124             * Argument を設定する時に、タイプ判断として、getArgumentType( String ) ã‚?
125             * 使用しますã?よって、不正な Argument を設定したå?合ã?、強制終äº?�•れますã?
126             *
127             * @param   arg 引数
128             * @see  #putArgument( String,String )
129             */
130            public void putArgument( final String arg ) {
131                    int type = getArgumentType( arg );
132    
133                    switch( type ) {
134                            case CMNT : break;
135                            case ARGS : argments.add( arg ); break;
136                            case PROP :
137                                    int sep = arg.indexOf( '=' );   // sep はã€?0 以上保証済み
138                                    String key = arg.substring(1,sep);
139                                    String val = arg.substring(sep+1);
140                                    checkProparty( key );           // 3.8.0.1 (2005/06/17)
141                                    proparty.put( key,val );
142                                    break;
143                            default: break;
144                    }
145            }
146    
147            /**
148             * Argument のæ–?­—å?から、ã?ロパティをセãƒ?ƒˆしますã?
149             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
150             * こã?メソãƒ?ƒ‰は、引数 ã‚?コメントã?判断を行いません。ã?ロパティ のみ
151             * 設定されるもã?として、å?ç�?�—ますã?
152             * プロパティの key=val がå?めからå?割されてã�?‚‹場合ã?簡易メソãƒ?ƒ‰ですã?
153             *
154             * @param   key プロパティのキー
155             * @param   val プロパティの値
156             * @see  #putArgument( String )
157             */
158            public void putArgument( final String key,final String val ) {
159                    checkProparty( key );           // 3.8.0.1 (2005/06/17)
160                    proparty.put( key,val );
161            }
162    
163            /**
164             * ?»引数?½個数æŒ?®šを設定しますã?
165             * æœ?¤§値、最小å?を登録しておくことで、å?数がã?規定から外れてã�?�ªã�?�‹
166             * どã�?�‹を確認しますã?
167             * エラー判定ã?、実際にã€?¼»引数?½を取りå?すときに行われますã?
168             * こã?チェãƒ?‚¯の登録は、putArgument( String ) の前でも後でもよくã?
169             * getArgument の実行前であれば、いつでも構いませんã€?
170             * 設定しなã�??合ã?初期値はã€???00 ですã?
171             *
172             * @param   min ?»引数?½のæœ?°�å?数(初期値:0)
173             * @param   max ?»引数?½のæœ?¤§個数(初期値:200)
174             */
175            public void setArgRange( final int min, final int max ) {
176                    argRangeMin = min ;
177                    argRangeMax = max ;
178            }
179    
180            /**
181             * ?»プロパティ?½å¿??チェãƒ?‚¯  Map 登録
182             * å¿??キーが登録されたかどã�?�‹のチェãƒ?‚¯を行いますã?
183             * マスト判定ã?、実際にã€?¼»プロパティ?½を取りå?すときに行われますã?
184             * すべてのプロパティーがセãƒ?ƒˆし終わったかどã�?�‹の判断がå?来なã�?�Ÿめですã?
185             * それ以外ã?チェãƒ?‚¯は、putArgument( String ) 時に行われるので、それまでに
186             * mustProparty のMapを登録しておくå¿?¦�がありますã?
187             * ただしã?引数æ–?­—å?の記述チェãƒ?‚¯(使用してもよã�??の配å?チェãƒ?‚¯)はã€?
188             * #getProparty( String , String , String[] ) で行われるので、取得時になりますã?
189             *
190             * 設定しなã�??合ã?初期値は、制限なしですã?
191             * æŒ?®šã?MapのValue値には、エラー時ã?コメントを記述しておきますã?
192             *
193             * @param   mustProp å¿??キーのMap
194             * @see #getProparty( String , String , String[] )
195             */
196            public void setMustProparty( final Map<String,String> mustProp ) {
197                    mustProparty = new LinkedHashMap<String,String>( mustProp ) ;
198            }
199    
200            /**
201             * ?»プロパティ?½整合æ?チェãƒ?‚¯ Map 登録
202             * æŒ?®šされてã�?‚‹キーのみ登録可能ですã?
203             * エラー判定ã?、実際にã€?¼»プロパティ?½を取りå?すときに行われますã?
204             * こã?チェãƒ?‚¯の登録は、putArgument( String ) 時に行われるので、それまでに
205             * usableProparty のMapを登録しておくå¿?¦�がありますã?
206             * ただしã?引数æ–?­—å?の記述チェãƒ?‚¯(使用してもよã�??の配å?チェãƒ?‚¯)はã€?
207             * #getProparty( String , String , String[] ) で行われるので、取得時になりますã?
208             *
209             * 設定しなã�??合ã?初期値は、制限なしですã?
210             * æŒ?®šã?MapのValue値には、このキーに対する解説を登録しておきますã?
211             *
212             * @param   useProp 使用可能キーのMap
213             */
214            public void setUsableProparty( final Map<String,String> useProp ) {
215                    usableProparty = new LinkedHashMap<String,String>( useProp ) ;
216            }
217    
218            /**
219             * Argument のæ–?­—å?から、そのタイプを判断しますã?
220             * 引数の形式が不正な場å�?例えば、キーと値のåˆ?›¢の = の前後にスペã?スがå?ったå?å�?
221             * RuntimeException で強制終äº?�—ますã?
222             *
223             * ?»コメント]  ??# で始まる引数で、使用されませんã€?登録もされませんã€?
224             * ?»引数?½      ??#,-,= 以外で始まるé?常のæ–?­—å?。登録のé ?•ªが指定されますã?
225             * ?»プロパティ?½??- で始まりã?キーと値ã‚?で区åˆ?�£てã�?‚‹パラメータですã?é ?º�ã?無関係ã?
226             *
227             * @og.rev 5.3.4.0 (2011/04/01) 空æ–?­—å?など無関係なパラメータは処ç�?�—なã�?‚ˆã�?�«変更
228             *
229             * @param   arg 引数
230             *
231             * @return  引数タイãƒ?CMNT,ARGS,PROP)
232             * @see Argument#CMNT ?»コメント]
233             * @see Argument#ARGS ?»引数?½
234             * @see Argument#PROP ?»プロパティ?½
235             * @throws RuntimeException
236             */
237            public int getArgumentType( final String arg ) {
238    //              if( arg == null || arg.length() == 0 || arg.startsWith( "#" ) ) {
239                    if( arg == null || arg.trim().length() == 0 || arg.startsWith( "#" ) ) {                // 5.3.4.0 (2011/04/01)
240                            return CMNT;
241                    }
242                    else if( arg.startsWith( "=" ) || arg.endsWith( "=" ) ) {       // 不正引数
243                            String errMsg = "引数の = の前後には、スペã?スをå?れなã�?�§下さã�??"
244                                            +       " BAD Argument=[" + arg + "]"  ;
245                            throw new RuntimeException( errMsg );
246                    }
247                    else if( arg.startsWith( "-" ) ) {
248                            int sep = arg.indexOf( '=' );
249                            if( sep > 0 && sep < arg.length()-1 ) {
250                                    return PROP;
251                            }
252                            else {
253                                    String errMsg = "-KEY を指定するå?合ã?ã€? を続けて、VALUEを指定して下さã�??"
254                                                    +       "  -KEY=VALUE 形å¼?BAD Argument=[" + arg + "]"  ;
255                                    throw new RuntimeException( errMsg );
256                            }
257                    }
258                    else {
259                            return ARGS ;
260                    }
261            }
262    
263            /**
264             * æŒ?®šã?番号に対する?»引数?½を返しますã?
265             * ?»引数?½はã€?,-,= 以外で始まるé?常のæ–?­—å?として登録されてã�?�¾すã?
266             * 登録されたé?番で取得しますã?
267             *
268             * @param   adrs 番号
269             *
270             * @return  ?»引数?½
271             * @throws RuntimeException
272             */
273            public String getArgument( final int adrs ) {
274                    // 以下ã?チェãƒ?‚¯は、getArgument が呼ばれてä¸?º¦のみの実行でよいã€?
275                    if( ! argOkFlag ) {
276                            if( argRangeMin < argments.size() || argments.size() < argRangeMax ) {
277                                    String errMsg = "?»引数?½個数が最å°?æœ?¤§個数をæº?�Ÿしてã�?�¾せんã€?
278                                                    +       "  Min:" + argRangeMin + " <= " + argments.size() + " < Max:" + argRangeMax  ;
279                                    throw new RuntimeException( errMsg );
280                            }
281                            argOkFlag = true;
282                    }
283    
284                    if( argments.size() <= adrs ) {
285                            String errMsg = "æŒ?®šã?アドレスはã€?¼»引数?½設定å?数外ですã?"
286                                            +       "  Size:" + argments.size() + " <= " + adrs ;
287                            throw new RuntimeException( errMsg );
288                    }
289    
290                    return argments.get( adrs );
291            }
292    
293            /**
294             * æŒ?®šã?番号に対する?»引数?½を返しますã?
295             * def には、文字å?の初期値を指定しておきますã?adrs に対応するå?がã?null の場合ã?
296             * こã? def をそのまま返しますã?
297             *
298             * 処ç�??、getArgument( int ) の結果をã?使用してã�?�¾すã?
299             *
300             * @param   adrs 番号
301             * @param   def 値ã�?null の場合ã?初期値
302             *
303             * @return  ?»引数?½
304             * @see #getArgument( int )
305             */
306            public String getArgument( final int adrs, final String def ) {
307                    String value = getArgument( adrs );
308                    return ( value != null ) ? value : def ;
309            }
310    
311            /**
312             * æŒ?®šã?番号に対する?»引数?½を返しますã?
313             * def には、数字ã?初期値を指定しておきますã?adrs に対応するå?がã?null の場合ã?
314             * こã? def をそのまま返しますã?
315             *
316             * 処ç�??、getArgument( int ) の結果をã?使用してã�?�¾すã?
317             *
318             * @param   adrs 番号
319             * @param   def 値ã�?null の場合ã?初期値
320             *
321             * @return  ?»引数?½
322             * @see #getArgument( int )
323             */
324            public int getArgument( final int adrs, final int def ) {
325                    String value = getArgument( adrs );
326                    return ( value != null ) ? Integer.parseInt( value ) : def ;
327            }
328    
329            /**
330             * æŒ?®šã?番号に対する?»引数?½を返しますã?
331             * def には、boolean の初期値を指定しておきますã?adrs に対応するå?がã?null の場合ã?
332             * こã? def をそのまま返しますã?
333             *
334             * 処ç�??、getArgument( int ) の結果をã?使用してã�?�¾すã?
335             *
336             * @param   adrs 番号
337             * @param   def 値ã�?null の場合ã?初期値
338             *
339             * @return  ?»引数?½
340             * @see #getArgument( int )
341             */
342            public boolean getArgument( final int adrs, final boolean def ) {
343                    String value = getArgument( adrs );
344                    return ( value != null ) ?  Boolean.valueOf( value ).booleanValue() : def ;
345            }
346    
347            /**
348             * ?»プロパティ?½整合æ?チェãƒ?‚¯ 実è¡?
349             * 設定された整合æ?チェãƒ?‚¯を実行しますã?
350             * è¤?•°キーに対応する為に、å?頭からの判定も行いますã?
351             * チェãƒ?‚¯するキーの大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
352             *
353             * @og.rev 5.1.5.0 (2010/04/01) 判定ã?条件がã?重è¤?�—てã�?�Ÿので修正ã€?
354             *
355             * @param   key チェãƒ?‚¯する入力キー
356             * @throws RuntimeException
357             */
358            private void checkProparty( final String key ) {
359    
360                    // 第?‘ã?判定ã? proparty にすでに存在してã�?‚Œば、エラーになるã?
361                    if( proparty.get( key ) != null ) {
362                            StringBuilder errMsg = new StringBuilder();
363    
364                            errMsg.append( "キー[" ).append( key ).append( "]は、すでにæŒ?®š済みですã?" ).append( CR );
365                            errMsg.append( "  登録済み??" ).append( key ).append( "=" ).append( proparty.get( key ) );
366                            errMsg.append( CR );
367                            throw new RuntimeException( errMsg.toString() );
368                    }
369    
370                    if( mustProparty != null ) {
371                            // 第?’ã?判定ã? mustProparty に存在すれば、即抜けするã€?
372                            if( mustProparty.containsKey( key ) ) { return; }
373    
374                            // 第?“ã?判定ã?è¤?•°キー(先é?ä¸??キー)の場合もありã�?‚‹ため、å?頭からの比è¼?‚’行うã€?
375                            Iterator<Map.Entry<String,String>> ite = mustProparty.entrySet().iterator();        // 4.3.3.6 (2008/11/15) Generics警告対å¿?
376                            while( ite.hasNext() ) {
377                                    Map.Entry<String,String> entry = ite.next();      // 4.3.3.6 (2008/11/15) Generics警告対å¿?
378                                    String propKey = entry.getKey();                                // 4.3.3.6 (2008/11/15) Generics警告対å¿?
379                                    if( key.startsWith( propKey ) ) { return ; }    // マッチすれã?、即抜けるã?
380                            }
381                    }
382    
383                    // 5.1.5.0 (2010/04/01) 判定ã?条件がã?重è¤?�—てã�?�Ÿので修正ã€?
384    //              if( usableProparty != null && !usableProparty.containsKey( key ) ) {
385                    if( usableProparty != null ) {
386                            // 第?”ã?判定ã? usableProparty に存在すれば、即抜けするã€?
387                            if( usableProparty.containsKey( key ) ) { return ; }
388    
389                            // 第?•ã?判定ã?è¤?•°キー(先é?ä¸??キー)の場合もありã�?‚‹ため、å?頭からの比è¼?‚’行うã€?
390                            Iterator<Map.Entry<String,String>> ite = usableProparty.entrySet().iterator();      // 4.3.3.6 (2008/11/15) Generics警告対å¿?
391                            while( ite.hasNext() ) {
392                                    Map.Entry<String,String> entry = ite.next();      // 4.3.3.6 (2008/11/15) Generics警告対å¿?
393                                    String propKey = entry.getKey();                                // 4.3.3.6 (2008/11/15) Generics警告対å¿?
394                                    if( key.startsWith( propKey ) ) { return ; }    // マッチすれã?、即抜けるã?
395                            }
396    
397                            // そこまで探して見つからなã�??合ã?、定義外引数エラー
398                            StringBuilder errMsg = new StringBuilder();
399    
400                            errMsg.append( "-KEY がã?æŒ?®šã?整合æ?リストに含まれてã�?�¾せんã€? );
401                            errMsg.append( CR ) ;
402                            errMsg.append( "  -KEY=VALUE 形å¼?BAD Key=[" ).append( key ).append( "]" );
403                            errMsg.append( CR ) ;
404                            errMsg.append( toString() ) ;
405                            throw new RuntimeException( errMsg.toString() );
406                    }
407            }
408    
409            /**
410             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
411             * 値が設定されてã�?�ªã�??合ã?ã€?null を返しますã?
412             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
413             *
414             * @param   key 引数のキー
415             *
416             * @return  引数に対する値
417             * @throws RuntimeException
418             */
419            public String getProparty( final String key ) {
420    
421                    String value = proparty.get( key );
422    
423                    // 値ã�?null で must 設定があり、かつマストキーが指定してã�?‚‹場合ã?
424                    if( value == null &&
425                            mustProparty != null &&
426                            mustProparty.containsKey( key ) ) {
427                                    String errMsg = "æŒ?®šã??»プロパティ?½は、å¿??キーですが、å?ã�?null ですã?"
428                                                    +       "  Key:" + key + "  説æ˜?" + mustProparty.get( key )
429                                                    + CR + toString() ;
430                                    throw new RuntimeException( errMsg );
431                    }
432    
433                    return value ;
434            }
435    
436            /**
437             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
438             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
439             * def には、文字å?の初期値を指定しておきますã?key に対応するå?がã?null の場合ã?
440             * こã? def をそのまま返しますã?
441             *
442             * 処ç�??、getProparty( String ) の結果をã?使用してã�?�¾すã?
443             *
444             * @param   key キー
445             * @param   def 値ã�?null の場合ã?初期値
446             *
447             * @return  ?»プロパティ?½
448             * @see #getProparty( String )
449             */
450            public String getProparty( final String key, final String def ) {
451                    String value = getProparty( key );
452                    return ( value != null ) ? value : def ;
453            }
454    
455            /**
456             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
457             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
458             * def には、文字å?の初期値を指定しておきますã?key に対応するå?がã?null の場合ã?
459             * こã? def をそのまま返しますã?
460             * list 配å?には、登録できるæ–?­—å?配å?を指定しますã?こã?æ–?­—å?に含まれなã�?
461             * 値が設定されてã�?�Ÿ場合ã?、エラーになりますã?
462             *
463             * 処ç�??、getProparty( String ) の結果をã?使用してã�?�¾すã?
464             *
465             * @param   key キー
466             * @param   def  値ã�?null の場合ã?初期値
467             * @param   list 値として存在できるæ–?­—å?リスãƒ?
468             *
469             * @return  ?»プロパティ?½
470             * @see #getProparty( String )
471             * @throws RuntimeException
472             */
473            public String getProparty( final String key, final String def, final String[] list ) {
474                    String value = getProparty( key,def );
475                    if( value != null ) {
476                            boolean isOK = false;
477                            for( int i=0; i<list.length; i++ ) {
478                                    if( value.equalsIgnoreCase( list[i] ) ) {
479                                            isOK = true; break;
480                                    }
481                            }
482                            if( !isOK ) {
483                                    String errMsg = key + " はã€? + Arrays.toString( list )
484                                                                            + " からæŒ?®šしてくださいã€? + CR
485                                                                            + "-" + key + "=[" + value + "]" ;
486                                    throw new RuntimeException( errMsg );
487                            }
488                    }
489    
490                    return value ;
491            }
492    
493            /**
494             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
495             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
496             * def には、数字ã?初期値を指定しておきますã?key に対応するå?がã?null の場合ã?
497             * こã? def をそのまま返しますã?
498             *
499             * 処ç�??、getProparty( String ) の結果をã?使用してã�?�¾すã?
500             *
501             * @param   key キー
502             * @param   def 値ã�?null の場合ã?初期値
503             *
504             * @return  ?»プロパティ?½
505             * @see #getProparty( String )
506             */
507            public int getProparty( final String key, final int def ) {
508                    String value = getProparty( key );
509                    return ( value != null ) ? Integer.parseInt( value ) : def ;
510            }
511    
512            /**
513             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
514             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
515             * def には、boolean の初期値を指定しておきますã?key に対応するå?がã?null の場合ã?
516             * こã? def をそのまま返しますã?
517             *
518             * 処ç�??、getProparty( String ) の結果をã?使用してã�?�¾すã?
519             *
520             * @param   key キー
521             * @param   def 値ã�?null の場合ã?初期値
522             *
523             * @return  ?»プロパティ?½
524             * @see #getProparty( String )
525             */
526            public boolean getProparty( final String key, final boolean def ) {
527                    String value = getProparty( key );
528                    return ( value != null ) ?  Boolean.valueOf( value ).booleanValue() : def ;
529            }
530    
531            /**
532             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
533             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
534             * key プロパティはã€??常の引数としてæŒ?®šできる簡易的な値を設定しますã?
535             * keyFile プロパティ は、ファイル名をæŒ?®šし、そのファイルの中身ã‚?
536             * 取得して返しますã?通常は?‘行であるがã?時にはè¤?•°行ã?ãƒ??タを指å®?
537             * したã�??合にã€?¼’つのパラメータを使ã�?�¾すが、設定å?は、同じ引数として
538             * 使用したã�?‚±ースに便利ですã?
539             * key プロパティと、keyFile プロパティ は、同時指定できませんã€?
540             * これは、指定方法ã?間違ã�?­‰を避ける為ですã?
541             * どちらも、null である可能性はありますã?
542             *
543             * @param   key キー
544             * @param   keyFile  設定ファイルå�?
545             * @param   must å¿??条件[true/false]
546             *
547             * @return  ?»プロパティ?½
548             * @see #getProparty( String )
549             * @throws RuntimeException 同時æŒ?®š時、またã?、must å¿??時に null の場合ã?
550             */
551            public String getFileProparty( final String key, final String keyFile, final boolean must ) {
552                    return getFileProparty( key,keyFile,null,must );
553            }
554    
555            /**
556             * å†?ƒ¨で使用する?»プロパティ?½をã?キーを指定して取得しますã?
557             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
558             * key プロパティはã€??常の引数としてæŒ?®šできる簡易的な値を設定しますã?
559             * keyFile プロパティ は、ファイル名をæŒ?®šし、そのファイルの中身ã‚?
560             * 取得して返しますã?通常は?‘行であるがã?時にはè¤?•°行ã?ãƒ??タを指å®?
561             * したã�??合にã€?¼’つのパラメータを使ã�?�¾すが、設定å?は、同じ引数として
562             * 使用したã�?‚±ースに便利ですã?
563             * key プロパティと、keyFile プロパティ は、同時指定できませんã€?
564             * これは、指定方法ã?間違ã�?­‰を避ける為ですã?
565             * どちらも、null である可能性はありますã?
566             *
567             * @param   key キー
568             * @param   keyFile 設定ファイルå�?
569             * @param   encode keyFile読取エンコーãƒ?null はãƒ?ƒ•ォルトエンコーãƒ?
570             * @param   must å¿??条件[true/false]
571             *
572             * @return  ?»プロパティ?½
573             * @see #getProparty( String )
574             * @throws RuntimeException 同時æŒ?®š時、またã?、must å¿??時に null の場合ã?
575             */
576            public String getFileProparty( final String key, final String keyFile,
577                                                                             final String encode,final boolean must ) {
578                    String val     = getProparty( key );
579                    String valFile = getProparty( keyFile );
580    
581                    if( val != null && valFile != null ) {
582                            String errMsg = key + "かã?" + keyFile + " は、両方同時にæŒ?®šできませんã€?" + val + "],[" + valFile + "]";
583                            throw new RuntimeException( errMsg );
584                    }
585    
586                    if( valFile != null ) {
587                            FileString fs = new FileString();
588                            fs.setFilename( valFile );
589                            fs.setEncode( encode );
590                            val = fs.getValue();
591                    }
592    
593                    if( must && val == null ) {
594                            String errMsg = key + "かã?" + keyFile + " は、片方å¿??ですã?";
595                            throw new RuntimeException( errMsg );
596                    }
597    
598                    return val;
599            }
600    
601            /**
602             * å†?ƒ¨で使用する?»プロパティ?½をã?キーをå?頭に含ã‚??を取得しますã?
603             * ?»プロパティ?½のキー部の大æ–?­—・小文字ã?、厳格に判定してã�?�¾すã?
604             * 値が設定されてã�?�ªã�??合ã?、String[0] を返しますã?
605             * HybsEntry のキーに設定される値は、引数の先é?キーを除ã�?�Ÿæ–?­—å?ですã?
606             * 例えばã€?const_" のような値を与えて、const_AA, const_BB, const_CC の
607             * ?“つのキーが選定された場合ã?キーは、AA, BB, CC のみ返しますã?
608             *
609             * @param   startsKey 引数の先é?のキー
610             *
611             * @return  引数に対する?»プロパティ?½のHybsEntry
612             */
613            public HybsEntry[] getEntrys( final String startsKey ) {
614    
615                    ArrayList<HybsEntry> list = new ArrayList<HybsEntry>();
616                    int len = startsKey.length();
617    
618                    Iterator<Map.Entry<String,String>> ite = proparty.entrySet().iterator();    // 4.3.3.6 (2008/11/15) Generics警告対å¿?
619                    while( ite.hasNext() ) {
620                            Map.Entry<String,String> entry = ite.next();      // 4.3.3.6 (2008/11/15) Generics警告対å¿?
621                            String key = entry.getKey();                                    // 4.3.3.6 (2008/11/15) Generics警告対å¿?
622                            if( key.startsWith( startsKey ) ) {
623                                    list.add( new HybsEntry( key.substring( len ), entry.getValue() ) );    // 4.3.3.6 (2008/11/15) Generics警告対å¿?
624                            }
625                    }
626    
627                    return list.toArray( new HybsEntry[list.size()] ) ;
628            }
629    
630            /**
631             * 入力文字å?に、{&#064;XXXX}関係ã?æ–?­—å?変換を行いますã?
632             * 引数に含まれる {&#064;XXXX}=YYYY とã�?�†入力に対して、inMsg に
633             * 含まれる{&#064;XXXX} æ–?­—å?をã?YYYY とã�?�†æ–?­—å?に変換しますã?
634             * それ以外に、予ç´?–‡字変換としてã€?
635             *   {&#064;ARG.XXX}  引数に使用されたå?をå?利用(割り当て)しますã?
636             *   {&#064;DATE.XXX} SimpleDateFormat 形式ã?æ–?­—を変換しますã?(日付ã?時刻ç­?
637             *   {&#064;ENV.XXX}  シスãƒ?ƒ プロパティーのæ–?­—を変換しますã?(java -Dkey=value オプション)
638             *
639             * @param  inMsg 入力文字å?
640             *
641             * @return  変換後文字å?
642             */
643            public String changeParam( final String inMsg ) {
644                    if( inMsg == null ) { return inMsg; }
645    
646                    String message = inMsg;
647    
648                    // {@ARG.XXXX} 変数の置換å?ç�?
649                    int adrs = message.indexOf( "{@ARG." ) ;
650                    while( adrs >= 0 ) {
651                            int end = message.indexOf( '}',adrs ) ;
652                            String key = message.substring( adrs+6,end );
653                            String oldData = "{@ARG." + key + "}" ;
654                            // 注意:{@XXX}と異なりã?{@ARG.XXX} では、XXX で proparty を検索するã€?
655                            String newData = StringUtil.nval( getProparty( key ),"" );
656                            message = StringUtil.replace( message,oldData,newData );
657                            adrs = message.indexOf( "{@ARG.",adrs ) ;
658                    }
659                    // {@DATE.XXXX} 変数の置換å?ç�?
660                    adrs = message.indexOf( "{@DATE." ) ;
661                    if( adrs >= 0 ) {
662                            Date dt = new Date();
663                            while( adrs >= 0 ) {
664                                    int end = message.indexOf( '}',adrs ) ;
665                                    String key = message.substring( adrs+7,end );
666                                    String oldData = "{@DATE." + key + "}" ;
667                                    DateFormat formatter = new SimpleDateFormat( key, Locale.JAPANESE );
668                                    String newData = StringUtil.nval( formatter.format(dt),"" );
669                                    message = StringUtil.replace( message,oldData,newData );
670                                    adrs = message.indexOf( "{@DATE.",adrs ) ;
671                            }
672                    }
673                    // {@ENV.XXXX} 変数の置換å?ç�?
674                    adrs = message.indexOf( "{@ENV." ) ;
675                    while( adrs >= 0 ) {
676                            int end = message.indexOf( '}',adrs ) ;
677                            String key = message.substring( adrs+6,end );
678                            String oldData = "{@ENV." + key + "}" ;
679                            String newData = System.getProperty( key,"" );
680                            message = StringUtil.replace( message,oldData,newData );
681                            adrs = message.indexOf( "{@ARG.",adrs ) ;
682                    }
683    
684                    // 残りのメãƒ?‚»ージ本æ–?¸­の置換文字å?をå?ç�?�—ますã?
685                    adrs = message.indexOf( "{@" ) ;
686                    while( adrs >= 0 ) {
687                            int end = message.indexOf( '}',adrs ) ;
688                            String key = message.substring( adrs,end+1 );   // +1 注æ„?
689                            String oldData = key ;
690                            // 注意:{@ARG.XXX} と異なりã?{@XXX} そã?もã?で proparty を検索するã€?
691                            String newData = StringUtil.nval( getProparty( key ),"" );
692                            message = StringUtil.replace( message,oldData,newData );
693                            adrs = message.indexOf( "{@",adrs ) ;
694                    }
695    
696                    return message;
697            }
698    
699            /**
700             * こã?オブジェクトã?å†?ƒ¨表現をã?æ–?­—å?にして返しますã?
701             * クラスå�???起動時の引数リストを表示しますã?
702             *
703             * @return  引数に対する値
704             */
705            @Override
706            public String toString() {
707                    StringBuilder buf = new StringBuilder();
708    
709                    buf.append( "java " ).append( programID ).append( CR );
710    
711                    if( ! argments.isEmpty() ) {
712                            for( int i=0; i<argments.size(); i++ ) {
713                                    buf.append( " " ).append( argments.get(i) );
714                            }
715                            buf.append( CR );
716                    }
717    
718                    Iterator<Map.Entry<String,String>> propIte = proparty.entrySet().iterator();        // 4.3.3.6 (2008/11/15) Generics警告対å¿?
719                    while( propIte.hasNext() ) {
720                            Map.Entry<String,String> entry = propIte.next();  // 4.3.3.6 (2008/11/15) Generics警告対å¿?
721                            String key = entry.getKey();                                            // 4.3.3.6 (2008/11/15) Generics警告対å¿?
722                            Object val = entry.getValue();
723                            if( key.startsWith( "passwd" ) ) {
724                                    val = "*****" ;
725                            }
726    
727                            buf.append( "    -" ).append( key ).append( "=" ).append( val );
728                            buf.append( CR );
729                    }
730    
731                    return buf.toString();
732            }
733    
734            /**
735             * こã?クラスの使用方法を返しますã?
736             *
737             * @return      こã?クラスの使用方æ³?
738             */
739            public String usage() {
740                    StringBuilder buf = new StringBuilder();
741    
742                    buf.append( toString() );
743                    buf.append( CR );
744    
745                    buf.append( propartyToString( "[ Must Proparty List ]",mustProparty ) );
746    
747                    buf.append( propartyToString( "[ Usable Proparty List ]",usableProparty ) );
748    
749                    return buf.toString();
750            }
751    
752            /**
753             * プロパティーを文字å?に変換しますã?
754             *
755             * proparty の キーのæœ?¤§長さを求め、位置あわせã?ためのスペã?スを追åŠ?�—ますã?
756             *
757             * @param       title タイトル
758             * @param       proparty プロパティー(Mapオブジェクãƒ?
759             *
760             * @return      プロパティーæ–?­—å?
761             */
762            private String propartyToString( final String title,final Map<String,String> proparty ) {
763                    StringBuilder buf = new StringBuilder();
764    
765                    if( proparty != null ) {
766                            buf.append( title ).append( CR );
767    
768                            // キーの長さをそろえるための処ç�?
769                            int maxLen = 0;
770                            Iterator<String> keyIte = proparty.keySet().iterator();   // 4.3.3.6 (2008/11/15) Generics警告対å¿?
771                            while( keyIte.hasNext() ) {
772                                    int len = keyIte.next().length();       // 4.3.3.6 (2008/11/15) Generics警告対å¿?
773                                    if( len > maxLen ) { maxLen = len; }
774                            }
775    
776                            char[] ch = new char[maxLen];
777                            Arrays.fill( ch,' ' );          // スペã?スで埋めますã?
778                            String SPACE = new String( ch );
779                            String VAL_SPACE = CR + SPACE + "        " ;
780    
781                            Iterator<Map.Entry<String,String>> propIte = proparty.entrySet().iterator();        // 4.3.3.6 (2008/11/15) Generics警告対å¿?
782                            while( propIte.hasNext() ) {
783                                    Map.Entry<String,String> entry = propIte.next();  // 4.3.3.6 (2008/11/15) Generics警告対å¿?
784                                    String key = entry.getKey();                                            // 4.3.3.6 (2008/11/15) Generics警告対å¿?
785                                    String val = entry.getValue();                                          // 4.3.3.6 (2008/11/15) Generics警告対å¿?
786                                    if( val != null ) { val = val.replaceAll( CR,VAL_SPACE ); }
787                                    buf.append( "    -" ).append( key );
788                                    buf.append( SPACE.substring( key.length() ) );  // 使用されるキー
789                                    buf.append( " : " ).append( val ) ;     // そã?説æ˜?
790                                    buf.append( CR );
791                            }
792                    }
793    
794                    return buf.toString();
795            }
796    }