OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / fukurou / util / Argument.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.fukurou.util;
17
18 import org.opengion.fukurou.system.OgRuntimeException ;         // 6.4.2.0 (2016/01/29)
19 import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
20 import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
21
22 import java.util.Map;
23 import java.util.LinkedHashMap;
24 import java.util.Collections;                                                                           // 6.4.3.1 (2016/02/12) refactoring
25 import java.util.List;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.Arrays;
29 import java.util.Date;
30 import java.util.Locale;
31
32 import java.text.DateFormat;
33 import java.text.SimpleDateFormat;
34
35 /**
36  * Argument は、バッチ処理の main メソッドの引数を解析するクラスです。
37  * Argument は、3つのタイプに分かれます。
38  *
39  * [コメント]  : # で始まる引数で、使用されません。(登録もされません。)
40  * [引数]      : #,-,= 以外で始まる通常の文字列。登録の順番が指定されます。
41  * [プロパティ]: - で始まり、キーと値を=で区切っているパラメータです。順序は無関係。
42  *
43  * これらのタイプを混在させても構いません。[引数]は、[コメント] や[プロパティ]を
44  * 無視した、入力の順番が重要視されます。取り出す場合も、番号で取り出します。
45  * 最初の[引数]が、0 で、以降 引数個数-1 までの番号で取り出します。
46  * [プロパティ]は、順番は無視し、キー部を指定することで取り出せます。
47  * ただし、キー部を重複して登録することは出来ません。なお、キー部の頭の文字列のみで
48  * 取り出すメソッドがあるため、key1,key2,key3 などと指定して、key で取り出せば、
49  * 複数プロパティを同一キーで取り出すことが可能です。
50  * [プロパティ]の指定では、キーと値を=で区切りますが、その前後にスペースを
51  * 入れないで下さい。引数の前後に = が付く文字列は指定できません。
52  *
53  * java Program AAA BBB #CCC -DD=XX -EE=YY -FF=ZZ GGG
54  *              ~~~ ~~~ ~~~~ ~~~~~~ ~~~~~~ ~~~~~~ ~~~
55  * [コメント]  : #CCC
56  * [引数]      : [0]=AAA , [1]=BBB , [2]=GGG
57  * [プロパティ]: key=DD,val=XX  key=EE,val=YY  key=FF,val=ZZ
58  *
59  * Argument の整合性チェックは、3つのパターンがあります。
60  *
61  * [引数]個数指定 :引数自身の最小個数、最大個数を登録しておくことで、プロパティのハイフン忘れ等を防止します。
62  * [プロパティ]必須チェック :必須キーが登録されたかどうかのチェックを行います。
63  * [プロパティ]整合性チェック : 指定されているキーのみ登録可能です。
64  *
65  * これらのチェックで、整合性チェックのみ、Argument の登録時に行います。
66  * それ以外は、取り出し時まで、判断できません。
67  * (取り出しは、登録がすべて終了したのちに行われると仮定しています)
68  *
69  * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
70  * [プロパティ]設定可能なプロパティの値を指定することで、誤記入を防止します。
71  *
72  * @version  4.0
73  * @author   Kazuhiko Hasegawa
74  * @since    JDK5.0,
75  */
76 public final class Argument  {
77         /** Argument引数のタイプ [コメント]は、無視されます。 {@value} */
78         public static final int CMNT = 0;       // [コメント]
79
80         /** Argument引数のタイプ [引数]は、入力順にアクセスできます。 {@value} */
81         public static final int ARGS = 1;       // [引数]
82
83         /** Argument引数のタイプ [プロパティ]は、-KEY=VALUE 形式でキーでアクセスできます。 {@value} */
84         public static final int PROP = 2;       // [プロパティ]
85
86         private boolean argOkFlag       ;
87         private final List<String> argments = new ArrayList<>();
88         /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
89         private final Map<String,String> propMap = Collections.synchronizedMap( new LinkedHashMap<>() );
90
91         private int argRangeMin ;                       // 初期値:0
92         private int argRangeMax = 200 ;         // 本当は、Windows の引数の上限値を設定
93
94         /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
95         private final Map<String,String> mustProparty   = Collections.synchronizedMap( new LinkedHashMap<>() );
96         /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
97         private final Map<String,String> usableProparty = Collections.synchronizedMap( new LinkedHashMap<>() );
98
99         private final String programID  ;
100
101         /**
102          * この Argument を使用している プログラムID(Javaクラス名)を指定して
103          * インスタンスを作成します。
104          * toString() する際に、表示します。
105          *
106          * @param   pgid プログラムID
107          */
108         public Argument( final String pgid ) {
109                 programID = pgid;
110         }
111
112         /**
113          * Argument の配列文字列から、引数やプロパティをセットします。
114          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
115          * これは、main メソッド等で単独起動する場合に、引数そのままを
116          * セットする場合に使用します。
117          *
118          * @param   args 引数配列(可変長引数)
119          * @see  #putArgument( String )
120          */
121         public void setArgument( final String... args ) {
122                 for( int i=0; i<args.length; i++ ) {
123                         putArgument( args[i] );
124                 }
125         }
126
127         /**
128          * Argument の文字列から、引数かプロパティをセットします。
129          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
130          * Argument を設定する時に、タイプ判断として、getArgumentType( String ) を
131          * 使用します。よって、不正な Argument を設定した場合は、強制終了されます。
132          *
133          * @og.rev 6.4.8.3 (2016/07/15) key,val 分解後は、#putArgument(String,String)
134          *
135          * @param   arg 引数
136          * @see  #putArgument( String,String )
137          */
138         public void putArgument( final String arg ) {
139                 final int type = getArgumentType( arg );
140
141                 switch( type ) {
142                         case CMNT : break;
143                         case ARGS : argments.add( arg ); break;
144                         case PROP :
145                                 final int sep = arg.indexOf( '=' );     // sep は、 0 以上保証済み
146                                 final String key = arg.substring(1,sep);
147                                 final String val = arg.substring(sep+1);
148                                 putArgument( key,val );         // 6.4.8.3 (2016/07/15)
149                                 break;
150                         default: break;
151                 }
152         }
153
154         /**
155          * Argument の文字列から、プロパティをセットします。
156          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
157          * このメソッドは、引数 や コメントの判断を行いません。プロパティ のみ
158          * 設定されるものとして、処理します。
159          * プロパティの key=val が初めから分割されている場合の簡易メソッドです。
160          *
161          * @og.rev 6.4.8.3 (2016/07/15) val で、「\t」と、「\n」の文字列を、タブと改行に変換します。
162          * @og.rev 6.4.8.4 (2016/07/22) 元に戻します。タブと改行は、ここで変換できません。
163          *
164          * @param   key プロパティのキー
165          * @param   val プロパティの値
166          * @see  #putArgument( String )
167          */
168         public void putArgument( final String key,final String val ) {
169                 checkProparty( key );           // 3.8.0.1 (2005/06/17)
170                 propMap.put( key,val );
171         }
172
173         /**
174          * [引数]個数指定を設定します。
175          * 最大値、最小値を登録しておくことで、個数が、規定から外れていないか
176          * どうかを確認します。
177          * エラー判定は、実際に、[引数]を取り出すときに行われます。
178          * このチェックの登録は、putArgument( String ) の前でも後でもよく、
179          * getArgument の実行前であれば、いつでも構いません。
180          * 設定しない場合の初期値は、0~200 です。
181          *
182          * @param   min [引数]の最小個数(初期値:0)
183          * @param   max [引数]の最大個数(初期値:200)
184          */
185         public void setArgRange( final int min, final int max ) {
186                 argRangeMin = min ;
187                 argRangeMax = max ;
188         }
189
190         /**
191          * [プロパティ]必須チェック  Map 登録
192          * 必須キーが登録されたかどうかのチェックを行います。
193          * マスト判定は、実際に、[プロパティ]を取り出すときに行われます。
194          * すべてのプロパティーがセットし終わったかどうかの判断が出来ないためです。
195          * それ以外のチェックは、putArgument( String ) 時に行われるので、それまでに
196          * mustProparty のMapを登録しておく必要があります。
197          * ただし、引数文字列の記述チェック(使用してもよい値の配列チェック)は、
198          * #getProparty( String , String , String[] ) で行われるので、取得時になります。
199          *
200          * 設定しない場合の初期値は、制限なしです。
201          * 指定のMapのValue値には、エラー時のコメントを記述しておきます。
202          *
203          * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
204          *
205          * @param   mustProp 必須キーのMap
206          * @see #getProparty( String , String , String[] )
207          */
208         public void setMustProparty( final Map<String,String> mustProp ) {
209                 mustProparty.putAll( mustProp ) ;
210         }
211
212         /**
213          * [プロパティ]整合性チェック Map 登録
214          * 指定されているキーのみ登録可能です。
215          * エラー判定は、実際に、[プロパティ]を取り出すときに行われます。
216          * このチェックの登録は、putArgument( String ) 時に行われるので、それまでに
217          * usableProparty のMapを登録しておく必要があります。
218          * ただし、引数文字列の記述チェック(使用してもよい値の配列チェック)は、
219          * #getProparty( String , String , String[] ) で行われるので、取得時になります。
220          *
221          * 設定しない場合の初期値は、制限なしです。
222          * 指定のMapのValue値には、このキーに対する解説を登録しておきます。
223          *
224          * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
225          *
226          * @param   useProp 使用可能キーのMap
227          */
228         public void setUsableProparty( final Map<String,String> useProp ) {
229                 usableProparty.putAll( useProp ) ;
230         }
231
232         /**
233          * Argument の文字列から、そのタイプを判断します。
234          * 引数の形式が不正な場合(例えば、キーと値の分離の = の前後にスペースが入った場合)
235          * RuntimeException で強制終了します。
236          *
237          * [コメント]  : # で始まる引数で、使用されません。(登録もされません。)
238          * [引数]      : #,-,= 以外で始まる通常の文字列。登録の順番が指定されます。
239          * [プロパティ]: - で始まり、キーと値を=で区切っているパラメータです。順序は無関係。
240          *
241          * ※ 引数の設定方法が間違っている場合、RuntimeException が throw されます。
242          *
243          * @og.rev 5.3.4.0 (2011/04/01) 空文字列など無関係なパラメータは処理しないように変更
244          * @og.rev 6.4.8.3 (2016/07/15) KEY=VALUE の VALUE が、ゼロ文字列でも許可します。
245          *
246          * @param   arg 引数
247          *
248          * @return  引数タイプ(CMNT,ARGS,PROP)
249          * @see Argument#CMNT [コメント]
250          * @see Argument#ARGS [引数]
251          * @see Argument#PROP [プロパティ]
252          */
253         public int getArgumentType( final String arg ) {
254                 if( arg == null || arg.trim().isEmpty() || '#' == arg.charAt(0) ) {
255                         return CMNT;
256                 }
257                 else if( '=' == arg.charAt(0)  ) {      // 不正引数
258                         final String errMsg = "引数の = の前後には、スペースを入れないで下さい。"
259                                         +       " BAD Argument=[" + arg + "]"  ;
260                         throw new OgRuntimeException( errMsg );
261                 }
262                 else if( '-' == arg.charAt(0) ) {
263                         final int sep = arg.indexOf( '=' );
264         //              if( sep > 0 && sep < arg.length()-1 ) {
265                         if( sep > 0 && sep < arg.length() ) {                                   // 6.4.8.3 (2016/07/15)
266                                 return PROP;
267                         }
268                         else {
269                                 final String errMsg = "-KEY を指定する場合は、= を続けて、VALUEを指定して下さい。"
270                                                 +       "  -KEY=VALUE 形式 BAD Argument=[" + arg + "]"  ;
271                                 throw new OgRuntimeException( errMsg );
272                         }
273                 }
274                 else {
275                         return ARGS ;
276                 }
277         }
278
279         /**
280          * 指定の番号に対する[引数]を返します。
281          * [引数]は、#,-,= 以外で始まる通常の文字列として登録されています。
282          * 登録された順番で取得します。
283          *
284          * ※ 引数の設定方法が間違っている場合、RuntimeException が throw されます。
285          *
286          * @param   adrs 番号
287          *
288          * @return  [引数]
289          */
290         public String getArgument( final int adrs ) {
291                 // 以下のチェックは、getArgument が呼ばれて一度のみの実行でよい。
292                 if( ! argOkFlag ) {
293                         if( argRangeMin < argments.size() || argments.size() < argRangeMax ) {
294                                 final String errMsg = "[引数]個数が最小/最大個数を満たしていません。"
295                                                 +       "  Min:" + argRangeMin + " <= " + argments.size() + " < Max:" + argRangeMax  ;
296                                 throw new OgRuntimeException( errMsg );
297                         }
298                         argOkFlag = true;
299                 }
300
301                 if( argments.size() <= adrs ) {
302                         final String errMsg = "指定のアドレスは、[引数]設定個数外です。"
303                                         +       "  Size:" + argments.size() + " <= " + adrs ;
304                         throw new OgRuntimeException( errMsg );
305                 }
306
307                 return argments.get( adrs );
308         }
309
310         /**
311          * 指定の番号に対する[引数]を返します。
312          * def には、文字列の初期値を指定しておきます。adrs に対応する値が、null の場合、
313          * この def をそのまま返します。
314          *
315          * 処理は、getArgument( int ) の結果を、使用しています。
316          *
317          * @param   adrs 番号
318          * @param   def 値が null の場合の初期値
319          *
320          * @return  [引数]
321          * @see #getArgument( int )
322          */
323         public String getArgument( final int adrs, final String def ) {
324                 final String value = getArgument( adrs );
325                 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
326                 return value == null ? def : value ;
327         }
328
329         /**
330          * 指定の番号に対する[引数]を返します。
331          * def には、数字の初期値を指定しておきます。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 int getArgument( final int adrs, final int def ) {
343                 final String value = getArgument( adrs );
344                 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
345                 return value == null ? def : Integer.parseInt( value ) ;
346         }
347
348         /**
349          * 指定の番号に対する[引数]を返します。
350          * def には、boolean の初期値を指定しておきます。adrs に対応する値が、null の場合、
351          * この def をそのまま返します。
352          *
353          * 処理は、getArgument( int ) の結果を、使用しています。
354          *
355          * @param   adrs 番号
356          * @param   def 値が null の場合の初期値
357          *
358          * @return  [引数]
359          * @see #getArgument( int )
360          */
361         public boolean getArgument( final int adrs, final boolean def ) {
362                 final String value = getArgument( adrs );
363                 return ( value == null ) ? def : Boolean.parseBoolean( value ) ;                // 6.1.0.0 (2014/12/26) refactoring
364         }
365
366         /**
367          * [プロパティ]整合性チェック 実行
368          * 設定された整合性チェックを実行します。
369          * 複数キーに対応する為に、先頭からの判定も行います。
370          * チェックするキーの大文字・小文字は、厳格に判定しています。
371          *
372          * ※ 引数の設定方法が間違っている場合、RuntimeException が throw されます。
373          *
374          * @og.rev 5.1.5.0 (2010/04/01) 判定の条件が、重複していたので修正。
375          * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
376          * @og.rev 6.4.3.3 (2016/03/04) Iterator 処理を、拡張for文に変更。
377          *
378          * @param   key チェックする入力キー
379          */
380         private void checkProparty( final String key ) {
381
382                 // 第1の判定。 propMap にすでに存在していれば、エラーになる。
383                 if( propMap.get( key ) != null ) {
384                         final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
385                                 .append( "キー[" ).append( key ).append( "]は、すでに指定済みです。" ).append( CR )
386                                 .append( "  登録済み:-" )
387                                 .append( key ).append( '=' ).append( propMap.get( key ) )               // 6.0.2.5 (2014/10/31) char を append する。
388                                 .append( CR );
389                         throw new OgRuntimeException( errMsg.toString() );
390                 }
391
392                 // 6.4.3.1 (2016/02/12) インスタンスで初期化しているため、null はない。
393                 if( !mustProparty.isEmpty() ) {                                                         // 6.4.3.1 (2016/02/12)
394                         // 第2の判定。 mustProparty に存在すれば、即抜けする。
395                         if( mustProparty.containsKey( key ) ) { return; }
396
397                         // 第3の判定。複数キー(先頭一致キー)の場合もありうるため、先頭からの比較を行う。
398                         // 6.4.3.3 (2016/03/04) Iterator 処理を、拡張for分に変更。判定は、keyのみでよい
399                         for( final String propKey : mustProparty.keySet() ) {
400                                 if( key.startsWith( propKey ) ) { return ; }            // マッチすれば、即抜ける。
401                         }
402                 }
403
404                 // 5.1.5.0 (2010/04/01) 判定の条件が、重複していたので修正。
405                 // 6.4.3.1 (2016/02/12) インスタンスで初期化しているため、null はない。
406                 if( !usableProparty.isEmpty() ) {                                                       // 6.4.3.1 (2016/02/12)
407                         // 第4の判定。 usableProparty に存在すれば、即抜けする。
408                         if( usableProparty.containsKey( key ) ) { return ; }
409
410                         // 第5の判定。複数キー(先頭一致キー)の場合もありうるため、先頭からの比較を行う。
411                         // 6.4.3.3 (2016/03/04) Iterator 処理を、拡張for分に変更。判定は、keyのみでよい
412                         for( final String propKey : usableProparty.keySet() ) {
413                                 if( key.startsWith( propKey ) ) { return ; }            // マッチすれば、即抜ける。
414                         }
415
416                         // そこまで探して見つからない場合は、定義外引数エラー
417                         final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
418                                 .append( "-KEY が、指定の整合性リストに含まれていません。" )
419                                 .append( CR )
420                                 .append( "  -KEY=VALUE 形式 BAD Key=[" ).append( key ).append( ']' )          // 6.0.2.5 (2014/10/31) char を append する。
421                                 .append( CR )
422                                 .append( toString() );
423                         throw new OgRuntimeException( errMsg.toString() );
424                 }
425         }
426
427         /**
428          * 内部で使用する[プロパティ]を、キーを指定して取得します。
429          * 値が設定されていない場合は、 null を返します。
430          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
431          *
432          * ※ 引数の設定方法が間違っている場合、RuntimeException が throw されます。
433          *
434          * @og.rev 6.4.3.1 (2016/02/12) Collections.synchronizedMap に置き換え。
435          *
436          * @param   key 引数のキー
437          *
438          * @return  引数に対する値
439          */
440         public String getProparty( final String key ) {
441
442                 final String value = propMap.get( key );
443
444                 // 値が null で must 設定があり、かつマストキーが指定している場合。
445                 if( value == null &&
446                         // 6.4.3.1 (2016/02/12) インスタンスで初期化しているため、null はない。
447                         !mustProparty.isEmpty() &&                                      // 6.4.3.1 (2016/02/12)
448                         mustProparty.containsKey( key ) ) {
449                                 final String errMsg = "指定の[プロパティ]は、必須キーですが、値が null です。"
450                                                 +       "  Key:" + key + "  説明:" + mustProparty.get( key )
451                                                 + CR + toString() ;
452                                 throw new OgRuntimeException( errMsg );
453                 }
454
455                 return value ;
456         }
457
458         /**
459          * 内部で使用する[プロパティ]を、キーを指定して取得します。
460          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
461          * def には、文字列の初期値を指定しておきます。key に対応する値が、null の場合、
462          * この def をそのまま返します。
463          *
464          * 処理は、getProparty( String ) の結果を、使用しています。
465          *
466          * @param   key キー
467          * @param   def 値が null の場合の初期値
468          *
469          * @return  [プロパティ]
470          * @see #getProparty( String )
471          */
472         public String getProparty( final String key, final String def ) {
473                 final String value = getProparty( key );
474                 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
475                 return value == null ? def : value ;
476         }
477
478         /**
479          * 内部で使用する[プロパティ]を、キーを指定して取得します。
480          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
481          * def には、文字列の初期値を指定しておきます。key に対応する値が、null の場合、
482          * この def をそのまま返します。
483          * list 配列には、登録できる文字列配列を指定します。この文字列に含まれない
484          * 値が設定されていた場合は、エラーになります。
485          *
486          * 処理は、getProparty( String ) の結果を、使用しています。
487          *
488          * ※ 引数の設定方法が間違っている場合、RuntimeException が throw されます。
489          *
490          * @param   key キー
491          * @param   def  値が null の場合の初期値
492          * @param   list 値として存在できる文字列配列(可変長引数)
493          *
494          * @return  [プロパティ]
495          * @see #getProparty( String )
496          */
497         public String getProparty( final String key, final String def, final String... list ) {
498                 final String value = getProparty( key,def );
499                 if( value != null ) {
500                         boolean isOK = false;
501                         for( int i=0; i<list.length; i++ ) {
502                                 if( value.equalsIgnoreCase( list[i] ) ) {
503                                         isOK = true; break;
504                                 }
505                         }
506                         if( !isOK ) {
507                                 final String errMsg = key + " は、" + Arrays.toString( list )
508                                                                         + " から指定してください。" + CR
509                                                                         + "-" + key + "=[" + value + "]" ;
510                                 throw new OgRuntimeException( errMsg );
511                         }
512                 }
513
514                 return value ;
515         }
516
517         /**
518          * 内部で使用する[プロパティ]を、キーを指定して取得します。
519          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
520          * def には、数字の初期値を指定しておきます。key に対応する値が、null の場合、
521          * この def をそのまま返します。
522          *
523          * 処理は、getProparty( String ) の結果を、使用しています。
524          *
525          * @param   key キー
526          * @param   def 値が null の場合の初期値
527          *
528          * @return  [プロパティ]
529          * @see #getProparty( String )
530          */
531         public int getProparty( final String key, final int def ) {
532                 final String value = getProparty( key );
533                 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
534                 return value == null ? def : Integer.parseInt( value ) ;
535         }
536
537         /**
538          * 内部で使用する[プロパティ]を、キーを指定して取得します。
539          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
540          * def には、boolean の初期値を指定しておきます。key に対応する値が、null の場合、
541          * この def をそのまま返します。
542          *
543          * 処理は、getProparty( String ) の結果を、使用しています。
544          *
545          * @param   key キー
546          * @param   def 値が null の場合の初期値
547          *
548          * @return  [プロパティ]
549          * @see #getProparty( String )
550          */
551         public boolean getProparty( final String key, final boolean def ) {
552                 final String value = getProparty( key );
553                 return ( value == null ) ? def : Boolean.parseBoolean( value ) ;                // 6.1.0.0 (2014/12/26) refactoring
554         }
555
556         /**
557          * 内部で使用する[プロパティ]を、キーを指定して取得します。
558          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
559          * key プロパティは、通常の引数として指定できる簡易的な値を設定します。
560          * keyFile プロパティ は、ファイル名を指定し、そのファイルの中身を
561          * 取得して返します。通常は1行であるが、時には複数行のデータを指定
562          * したい場合に、2つのパラメータを使いますが、設定値は、同じ引数として
563          * 使用したいケースに便利です。
564          * key プロパティと、keyFile プロパティ は、同時指定できません。
565          * これは、指定方法の間違い等を避ける為です。
566          * どちらも、null である可能性はあります。
567          *
568          * ※ 同時指定時、または、must 必須時に null の場合、RuntimeException が throw されます。
569          *
570          * @param   key キー
571          * @param   keyFile  設定ファイル名
572          * @param   must 必須条件[true/false]
573          *
574          * @return  [プロパティ]
575          * @see #getProparty( String )
576          */
577         public String getFileProparty( final String key, final String keyFile, final boolean must ) {
578                 return getFileProparty( key,keyFile,null,must );
579         }
580
581         /**
582          * 内部で使用する[プロパティ]を、キーを指定して取得します。
583          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
584          * key プロパティは、通常の引数として指定できる簡易的な値を設定します。
585          * keyFile プロパティ は、ファイル名を指定し、そのファイルの中身を
586          * 取得して返します。通常は1行であるが、時には複数行のデータを指定
587          * したい場合に、2つのパラメータを使いますが、設定値は、同じ引数として
588          * 使用したいケースに便利です。
589          * key プロパティと、keyFile プロパティ は、同時指定できません。
590          * これは、指定方法の間違い等を避ける為です。
591          * どちらも、null である可能性はあります。
592          *
593          * ※ 同時指定時、または、must 必須時に null の場合、RuntimeException が throw されます。
594          *
595          * @og.rev 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
596          * @og.rev 6.4.5.2 (2016/05/06) fukurou.util.FileString から、fukurou.util.FileUtil に移動。
597          *
598          * @param   key キー
599          * @param   keyFile 設定ファイル名
600          * @param   encode keyFile読取エンコード(null はデフォルトエンコード)
601          * @param   must 必須条件[true/false]
602          *
603          * @return  [プロパティ]
604          * @see #getProparty( String )
605          */
606         public String getFileProparty( final String key, final String keyFile,
607                                                                          final String encode,final boolean must ) {
608                 String val     = getProparty( key );
609                 final String valFile = getProparty( keyFile );
610
611                 if( val != null && valFile != null ) {
612                         final String errMsg = key + "か、" + keyFile + " は、両方同時に指定できません。[" + val + "],[" + valFile + "]";
613                         throw new OgRuntimeException( errMsg );
614                 }
615
616                 if( valFile != null ) {
617                         // 6.4.5.1 (2016/04/28) FileStringのコンストラクター変更
618                         val = FileUtil.getValue( valFile , encode );            // 6.4.5.2 (2016/05/06)
619                 }
620
621                 if( must && val == null ) {
622                         final String errMsg = key + "か、" + keyFile + " は、片方必須です。";
623                         throw new OgRuntimeException( errMsg );
624                 }
625
626                 return val;
627         }
628
629         /**
630          * 内部で使用する[プロパティ]を、キーを先頭に含む値を取得します。
631          * [プロパティ]のキー部の大文字・小文字は、厳格に判定しています。
632          * 値が設定されていない場合は、String[0] を返します。
633          * HybsEntry のキーに設定される値は、引数の先頭キーを除いた文字列です。
634          * 例えば、"const_" のような値を与えて、const_AA, const_BB, const_CC の
635          * 3つのキーが選定された場合、キーは、AA, BB, CC のみ返します。
636          *
637          * @param   startsKey 引数の先頭のキー
638          *
639          * @return  引数に対する[プロパティ]のHybsEntry
640          * @og.rtnNotNull
641          */
642         public HybsEntry[] getEntrys( final String startsKey ) {
643                 final ArrayList<HybsEntry> list = new ArrayList<>();
644                 final int len = startsKey.length();
645
646                 final Iterator<Map.Entry<String,String>> ite = propMap.entrySet().iterator();   // 4.3.3.6 (2008/11/15) Generics警告対応
647                 while( ite.hasNext() ) {
648                         final Map.Entry<String,String> entry = ite.next();      // 4.3.3.6 (2008/11/15) Generics警告対応
649                         final String key = entry.getKey();                                      // 4.3.3.6 (2008/11/15) Generics警告対応
650                         if( key.startsWith( startsKey ) ) {
651                                 list.add( new HybsEntry( key.substring( len ), entry.getValue() ) );    // 4.3.3.6 (2008/11/15) Generics警告対応
652                         }
653                 }
654
655                 return list.toArray( new HybsEntry[list.size()] ) ;
656         }
657
658         /**
659          * 入力文字列に、{&#064;XXXX}関係の文字列変換を行います。
660          * 引数に含まれる {&#064;XXXX}=YYYY という入力に対して、inMsg に
661          * 含まれる{&#064;XXXX} 文字列を、YYYY という文字列に変換します。
662          * それ以外に、予約文字変換として、
663          *   {&#064;ARG.XXX}  引数に使用された値を再利用(割り当て)します。
664          *   {&#064;DATE.XXX} SimpleDateFormat 形式の文字を変換します。(日付、時刻等)
665          *   {&#064;ENV.XXX}  システムプロパティーの文字を変換します。(java -Dkey=value オプション)
666          *
667          * @param  inMsg 入力文字列
668          *
669          * @return  変換後文字列
670          */
671         public String changeParam( final String inMsg ) {
672                 if( inMsg == null ) { return inMsg; }
673
674                 String message = inMsg;
675
676                 // {@ARG.XXXX} 変数の置換処理
677                 int adrs = message.indexOf( "{@ARG." ) ;
678                 while( adrs >= 0 ) {
679                         final int end = message.indexOf( '}',adrs ) ;
680                         final String key = message.substring( adrs+6,end );
681                         final String oldData = "{@ARG." + key + "}" ;
682                         // 注意:{@XXX}と異なり、{@ARG.XXX} では、XXX で propMap を検索する。
683                         final String newData = StringUtil.nval( getProparty( key ),"" );
684                         message = StringUtil.replace( message,oldData,newData );
685                         adrs = message.indexOf( "{@ARG.",adrs ) ;
686                 }
687                 // {@DATE.XXXX} 変数の置換処理
688                 adrs = message.indexOf( "{@DATE." ) ;
689                 if( adrs >= 0 ) {
690                         final Date dt = new Date();
691                         while( adrs >= 0 ) {
692                                 final int end = message.indexOf( '}',adrs ) ;
693                                 final String key = message.substring( adrs+7,end );
694                                 final String oldData = "{@DATE." + key + "}" ;
695                                 final DateFormat formatter = new SimpleDateFormat( key, Locale.JAPAN );
696                                 final String newData = StringUtil.nval( formatter.format(dt),"" );
697                                 message = StringUtil.replace( message,oldData,newData );
698                                 adrs = message.indexOf( "{@DATE.",adrs ) ;
699                         }
700                 }
701                 // {@ENV.XXXX} 変数の置換処理
702                 adrs = message.indexOf( "{@ENV." ) ;
703                 while( adrs >= 0 ) {
704                         final int end = message.indexOf( '}',adrs ) ;
705                         final String key = message.substring( adrs+6,end );
706                         final String oldData = "{@ENV." + key + "}" ;
707                         final String newData = System.getProperty( key,"" );
708                         message = StringUtil.replace( message,oldData,newData );
709                         adrs = message.indexOf( "{@ENV.",adrs ) ;
710                 }
711
712                 // 残りのメッセージ本文中の置換文字列を処理します。
713                 adrs = message.indexOf( "{@" ) ;
714                 while( adrs >= 0 ) {
715                         final int end = message.indexOf( '}',adrs ) ;
716                         final String key = message.substring( adrs,end+1 );     // +1 注意
717                         final String oldData = key ;
718                         // 注意:{@ARG.XXX} と異なり、{@XXX} そのもので propMap を検索する。
719                         final String newData = StringUtil.nval( getProparty( key ),"" );
720                         message = StringUtil.replace( message,oldData,newData );
721                         adrs = message.indexOf( "{@",adrs ) ;
722                 }
723
724                 return message;
725         }
726
727         /**
728          * このオブジェクトの内部表現を、文字列にして返します。
729          * クラス名 + 起動時の引数リストを表示します。
730          *
731          * @return  引数に対する値
732          * @og.rtnNotNull
733          */
734         @Override
735         public String toString() {
736                 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
737
738                 buf.append( "java " ).append( programID ).append( CR );
739
740                 if( ! argments.isEmpty() ) {
741                         for( int i=0; i<argments.size(); i++ ) {
742                                 buf.append( ' ' ).append( argments.get(i) );            // 6.0.2.5 (2014/10/31) char を append する。
743                         }
744                         buf.append( CR );
745                 }
746
747                 final Iterator<Map.Entry<String,String>> propIte = propMap.entrySet().iterator();       // 4.3.3.6 (2008/11/15) Generics警告対応
748                 while( propIte.hasNext() ) {
749                         final Map.Entry<String,String> entry = propIte.next();  // 4.3.3.6 (2008/11/15) Generics警告対応
750                         final String key = entry.getKey();                                              // 4.3.3.6 (2008/11/15) Generics警告対応
751                         Object val = entry.getValue();
752                         if( key.startsWith( "passwd" ) ) {
753                                 val = "*****" ;
754                         }
755
756                         buf.append( "    -" ).append( key ).append( '=' ).append( val );                // 6.0.2.5 (2014/10/31) char を append する。
757                         buf.append( CR );
758                 }
759
760                 return buf.toString();
761         }
762
763         /**
764          * このクラスの使用方法を返します。
765          *
766          * @return      このクラスの使用方法
767          * @og.rtnNotNull
768          */
769         public String usage() {
770                 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
771                         .append( toString() )
772                         .append( CR )
773                         .append( propMapToString( "[ Must Proparty List ]"  , mustProparty   ) )
774                         .append( propMapToString( "[ Usable Proparty List ]", usableProparty ) );
775
776                 return buf.toString();
777         }
778
779         /**
780          * プロパティーを文字列に変換します。
781          *
782          * propMap の キーの最大長さを求め、位置あわせのためのスペースを追加します。
783          *
784          * @param       title タイトル
785          * @param       propMap プロパティー(Mapオブジェクト)
786          *
787          * @return      プロパティー文字列
788          * @og.rtnNotNull
789          */
790         private String propMapToString( final String title,final Map<String,String> propMap ) {
791                 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
792
793                 if( propMap != null ) {
794                         buf.append( title ).append( CR );
795
796                         // キーの長さをそろえるための処理
797                         int maxLen = 0;
798                         final Iterator<String> keyIte = propMap.keySet().iterator();    // 4.3.3.6 (2008/11/15) Generics警告対応
799                         while( keyIte.hasNext() ) {
800                                 final int len = keyIte.next().length(); // 4.3.3.6 (2008/11/15) Generics警告対応
801                                 if( len > maxLen ) { maxLen = len; }
802                         }
803
804                         final char[] ch = new char[maxLen];
805                         Arrays.fill( ch,' ' );          // スペースで埋めます。
806                         final String SPACE = new String( ch );
807                         final String VAL_SPACE = CR + SPACE + "        " ;
808
809                         final Iterator<Map.Entry<String,String>> propIte = propMap.entrySet().iterator();       // 4.3.3.6 (2008/11/15) Generics警告対応
810                         while( propIte.hasNext() ) {
811                                 final Map.Entry<String,String> entry = propIte.next();  // 4.3.3.6 (2008/11/15) Generics警告対応
812                                 final String key = entry.getKey();                                              // 4.3.3.6 (2008/11/15) Generics警告対応
813                                 String val = entry.getValue();                                                  // 4.3.3.6 (2008/11/15) Generics警告対応
814                                 if( val != null ) { val = val.replaceAll( CR,VAL_SPACE ); }
815                                 buf.append( "    -" ).append( key );
816                                 buf.append( SPACE.substring( key.length() ) );  // 使用されるキー
817                                 buf.append( " : " ).append( val ) ;     // その説明
818                                 buf.append( CR );
819                         }
820                 }
821
822                 return buf.toString();
823         }
824 }