001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.hayabusa.db;
017
018import org.opengion.fukurou.system.HybsConst ;                                          // 6.1.0.0 (2014/12/26)
019import org.opengion.fukurou.util.ErrorMessage;
020import org.opengion.fukurou.db.Transaction;
021import org.opengion.hayabusa.common.HybsSystemException;
022import org.opengion.hayabusa.resource.ResourceManager;
023import org.opengion.hayabusa.html.ViewMarker;                                           // 8.0.0.0 (2021/09/30)
024
025import java.util.Locale;
026import java.util.Map;
027import java.util.LinkedHashMap ;
028import java.util.concurrent.ConcurrentMap;                                                      // 6.4.3.3 (2016/03/04)
029import java.util.concurrent.ConcurrentHashMap;                                          // 6.4.3.1 (2016/02/12) refactoring
030import java.util.Collections;                                                                           // 6.4.3.1 (2016/02/12) refactoring
031import java.util.List;                                                                                          // 8.2.1.0 (2022/07/15)
032import java.util.ArrayList;                                                                                     // 8.2.1.0 (2022/07/15)
033
034/**
035 * AbstractTableFilter は、TableUpda インターフェースを継承した、DBTableModel 処理用の
036 * Abstract実装クラスです。
037 *
038 * @og.rev 5.5.2.6 (2012/05/25) protected変数をprivateに変更。インターフェースにメソッド追加
039 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
040 *
041 * @version  0.9.0  2000/10/17
042 * @author   Kazuhiko Hasegawa
043 * @since    JDK1.1,
044 */
045public abstract class AbstractTableFilter implements TableFilter {
046        /** システムの改行コードを設定します。*/
047        protected static final String CR                 = HybsConst.CR;                        // 6.1.0.0 (2014/12/26) refactoring
048        /** StringBilderなどの初期値を設定します。   {@value} */
049        protected static final int BUFFER_MIDDLE = HybsConst.BUFFER_MIDDLE;     // 6.1.0.0 (2014/12/26) refactoring
050
051        // 5.5.2.6 (2012/05/25) protected変数をprivateに変更。インターフェースにメソッド追加
052        private DBTableModel    table           ;
053        private String                  modifyType      ;
054        private int[]                   rowNo           ;
055        private boolean                 useDebug        ;               // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更
056        private Transaction             tran            ;               // 5.1.9.0 (2010/08/01) 追加
057        private String                  sql                     ;               // 4.2.4.0 (2008/06/23)
058        private String                  dbid            ;               // 4.2.4.0 (2008/06/23)
059        private ResourceManager resource        ;               // 4.3.7.4 (2009/07/01)
060        private ViewMarker              viewMarker      ;               // 8.0.0.0 (2021/09/30)
061
062        private int                     errCode         = ErrorMessage.OK;
063        private ErrorMessage    errMessage      ;
064
065        // 8.2.1.0 (2022/07/15) TableFilter_MAPCLM 専用のMapを管理するList
066        private List<Map<String,String>> mapList ;
067
068        /** 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 */
069        private final ConcurrentMap<String,String> keyValMap = new ConcurrentHashMap<>();
070
071        /** 7.4.0.1 (2021/04/16) 値を返すための変数 */
072        private final ConcurrentMap<String,String> rtnValMap = new ConcurrentHashMap<>();
073
074        // 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。
075        // 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更
076        /** 6.4.3.1 (2016/02/12) Collections.synchronizedMap で同期処理を行います。 */
077        private final Map<String,String> keysMap = Collections.synchronizedMap( new LinkedHashMap<>() ) ;
078
079        // 6.0.2.3 (2014/10/10) plugin.table.TableFilter_XXXX から移動
080        /** XML宣言定数 */
081        protected static final String XML_START_TAG     = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>";
082        /** ROWSET 終了TAG {@value} */
083        protected static final String XML_END_TAG       = "</ROWSET>";
084        /** EXEC_SQL 開始TAG {@value} */
085        protected static final String EXEC_START_TAG= "<EXEC_SQL>";
086        /** EXEC_SQL exists="0" 開始TAG {@value} */
087        protected static final String EXEC_EXISTS_0_TAG= "<EXEC_SQL exists=\"0\">";             // 8.1.0.3 (2022/01/21)
088        /** EXEC_SQL 終了TAG {@value} */
089        protected static final String EXEC_END_TAG      = "</EXEC_SQL>";
090
091        // 6.0.2.3 (2014/10/10) isXml で、CR + EXEC_END_TAG のキャッシュを作成します。
092        /** XML形式かどうか */
093        protected boolean       isXml           ;               // 6.0.2.3 (2014/10/10)
094        /** exists判定に使用するSQL文 */
095        protected String        execExistsSQL;          // 8.1.0.3 (2022/01/21)
096        /** 終了タグ */
097        protected String        execEndTag      ;               // 6.0.2.3 (2014/10/10)
098
099        /**
100         * デフォルトコンストラクター
101         *
102         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
103         */
104        protected AbstractTableFilter() { super(); }            // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
105
106        /**
107         * keys の整合性チェックを行うための初期設定を行います。
108         * サブクラスのコンストラクタ内で、設定するようにしてください。
109         *
110         * @og.rev 6.4.1.1 (2016/01/16) keys の整合性チェック対応
111         * @og.rev 6.4.3.1 (2016/02/12) ConcurrentMap 系は、key,val ともに not null 制限です。
112         *
113         * @param       key  整合性チェックを行うための keysMap に設定するキー
114         * @param       cmnt 整合性チェックを行うための キー の説明
115         */
116        protected void initSet( final String key , final String cmnt ) {
117                if( key != null && cmnt != null ) {
118                        keysMap.put( key , cmnt );
119                }
120        }
121
122        /**
123         * DBTableModel をセットします。
124         *
125         * @param       table DBTableModelオブジェクト
126         */
127        @Override       // TableFilter
128        public void setDBTableModel( final DBTableModel table ) {
129                this.table = table;
130        }
131
132        /**
133         * DBTableModel を取得します。
134         *
135         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
136         *
137         * @return      内部のDBTableModel
138         */
139        @Override       // TableFilter
140        public DBTableModel getDBTableModel() {
141                return table;
142        }
143
144        /**
145         * データ処理の方法(A:追加 C:更新 D:削除)を指定します。
146         *
147         * 通常は、DBTableModel に自動設定されている modifyType を元に、データ処理方法を
148         * 選別します。(A:追加 C:更新 D:削除)
149         * この場合、行単位で modifyType の値を取得して判別する必要がありますが、一般には
150         * 処理対象は、全件おなじ modifyType である可能性が高いです。
151         * また、selectedAll などで強制的に全件処理対象とする場合は、modifyType に値が
152         * 設定さていません。その様な場合に外部より modifyType を指定します。
153         * 初期値は、自動判定 です。
154         *
155         * @og.rev 5.5.2.6 (2012/05/25) 廃止
156         *
157         * @param  type データ処理の方法(A:追加 C:更新 D:削除)
158         */
159        @Override       // TableFilter
160        public void setModifyType( final String type ) {
161                modifyType = type;
162        }
163
164        /**
165         * データ処理の方法(A:追加 C:更新 D:削除)を取得します。
166         *
167         * 初期値は、自動判定 です。
168         *
169         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
170         *
171         * @return  データ処理の方法(A:追加 C:更新 D:削除)
172         */
173        @Override       // TableFilter
174        public String getModifyType() {
175                return modifyType ;
176        }
177
178        /**
179         * キーと値のペアの変数配列を受け取ります。
180         *
181         * ここでは、この方式以外に、パラメーターMapを受け取る方法もあります。
182         * この受け取る時に、キーを大文字化します。TableFilter の keys は、
183         * 大文字のみで定義しておくことで、HTMLやWindows世代の曖昧な表記方法に
184         * 対応しています。(unixやxmlのような厳格な方が好きですけど)
185         *
186         * keys,vals とパラメーターMapを同時に指定した場合は、両方とも有効です。
187         * ただし、キーが重複した場合は、不定と考えてください。
188         *
189         * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。
190         *
191         * @param   keys キー配列
192         * @param   vals 値配列
193         * @see         #setParamMap( ConcurrentMap )
194         */
195        @Override       // TableFilter
196        public void setKeysVals( final String[] keys,final String[] vals ) {
197                if( keys != null && vals != null ) {
198                        for( int i=0; i<keys.length; i++ ) {
199                                // 5.6.6.0 (2013/07/05) 共通のセッターメソッド経由で登録します。
200                                setKeyVal( keys[i],vals[i] );
201                        }
202                }
203        }
204
205        /**
206         * キーと値のペアを受け取り、内部の keyValMap マップに追加します。
207         *
208         * キーか値のどちらかが null の場合は、何もしません。つまり、val に
209         * null をセットすることはできません。
210         *
211         * このメソッドは、setKeysVals( String[] ,String[] ) メソッドと、
212         * setParamMap( Map<String,String> ) メソッドの両方から、使用します。
213         * 処理を行うに当たり、下記の処理を行います。
214         * 1.キーを大文字化します。
215         * 2.各クラスの keys と整合性チェックを行います。
216         *
217         * ただし、setKeysVals と setParamMap の登録順は、不定と考えてください。
218         * 両方に同じキーを指定すると、どちらの値がセットされたかは、不定です。
219         *
220         * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。
221         * @og.rev 6.4.3.4 (2016/03/12) Map#forEach で対応する。
222         * @og.rev 6.7.9.1 (2017/05/19) keysMap が、空の場合も、keyValMap に登録する。(initSet 未登録時)
223         * @og.rev 7.0.1.0 (2018/10/15) XHTML → HTML5 対応(空要素の、"/>" 止めを、">" に変更します)。
224         * @og.rev 8.0.0.0 (2021/09/30) brタグを止めてを、preタグに変更します。
225         *
226         * @param   key キー文字列(null の場合は、処理しない)
227         * @param   val 値文字列(null の場合は、処理しない)
228         * @see         #setKeysVals( String[] ,String[] )
229         * @see         #setParamMap( ConcurrentMap )
230         */
231        private void setKeyVal( final String key,final String val ) {
232                // key か val かどちらかが null の場合は、処理を行わない。
233                if( key == null || val == null ) { return; }
234
235                final String upKey = key.toUpperCase(Locale.JAPAN);
236
237                // 6.7.9.1 (2017/05/19) keysMap が、空の場合も、keyValMap に登録する。(initSet 未登録時)
238                if(  keysMap.isEmpty() || keysMap.containsKey( upKey ) ) {              // keysMap は、各サブクラスで定義
239                        keyValMap.put( upKey,val );
240                }
241                else {
242//                      final String BR = "<br />" + CR ;
243//                      final String BR = "<br>" + CR ;                         // 7.0.1.0 (2018/10/15)
244                        final String BR = CR ;                                          // 8.0.0.0 (2021/09/30)
245                        final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE );
246                        // 6.0.2.5 (2014/10/31) char を append する。
247//                      errMsg.append( BR )
248                        errMsg.append( "<pre>" ).append( BR )
249                                  .append( "指定のキーは、この tableFilter では、使用できません。" ).append( BR )
250                                  .append( "  class=[" ).append( getClass().getName() ).append( ']' ).append( BR )
251                                  .append( "  key  =[" ).append( key                              ).append( ']' ).append( BR )
252                                  .append( "  ======== usage keys ======== " ).append( BR ) ;
253                        // 6.4.3.4 (2016/03/12) Map#forEach で対応する。
254                        keysMap.forEach( (k,v) -> { errMsg.append( ' ' ).append( k ).append( ':' ).append( v ).append( BR ); } );
255                        errMsg.append( "  ============================ " ).append( BR ).append( "</pre>" );
256
257                        throw new HybsSystemException( errMsg.toString() );
258                }
259        }
260
261        /**
262         * 選択された行番号の配列をセットします。
263         *
264         * 表示データの HybsSystem.ROW_SELECTED_KEY を元に、選ばれた 行を
265         * 処理の対象とします。
266         *
267         * @param   rowNoTmp 行番号配列(可変長引数)
268         */
269        @Override       // TableFilter
270        public void setParameterRows( final int... rowNoTmp ) {
271                if( rowNoTmp != null && rowNoTmp.length > 0 ) {         // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
272                        final int size = rowNoTmp.length ;
273                        rowNo = new int[size];
274                        System.arraycopy( rowNoTmp,0,rowNo,0,size );
275                }
276        }
277
278        /**
279         * 選択された行番号の配列を取得します。
280         *
281         * 表示データの HybsSystem.ROW_SEL_KEY を元に、選ばれた 行を
282         * 処理の対象とします。
283         *
284         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
285         * @og.rev 6.0.2.5 (2014/10/31) null ではなく、サイズ0の配列を返すように変更。
286         *
287         * @return   行番号の配列(選ばれていない場合は、サイズ0の配列を返す)
288         * @og.rtnNotNull
289         */
290        @Override       // TableFilter
291        public int[] getParameterRows() {
292                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
293                return rowNo == null ? new int[0] : rowNo.clone() ;
294        }
295
296        /**
297         * アクセスログ取得の為、Transactionオブジェクトを設定します。
298         *
299         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応(新規追加)
300         *
301         * @param   tran Transactionオブジェクト
302         */
303        @Override       // TableFilter
304        public void setTransaction( final Transaction tran ) {
305                this.tran = tran;
306        }
307
308        /**
309         * アクセスログ取得の為、Transactionオブジェクトを取得します。
310         *
311         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応(新規追加)
312         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
313         *
314         * @return   Transactionオブジェクト
315         */
316        @Override       // TableFilter
317        public Transaction getTransaction() {
318                return tran;
319        }
320
321        /**
322         * DBIDを指定します。
323         *
324         * @og.rev 4.2.4.0 (2008/06/23) 新規追加
325         *
326         * @param dbid 接続先ID
327         */
328        @Override       // TableFilter
329        public void setDbid( final String dbid ) {
330                this.dbid = dbid;
331        }
332
333        /**
334         * DBIDを取得します。
335         *
336         * @og.rev 4.2.4.0 (2008/06/23) 新規追加
337         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
338         *
339         * @return DBID(接続先情報)
340         */
341        @Override       // TableFilter
342        public String getDbid() {
343                return dbid;
344        }
345
346        /**
347         * ボディー部分のSQLを指定します。
348         *
349         * @og.rev 4.2.4.0 (2008/06/23) 新規追加
350         *
351         * @param sql ボディー部分のSQL
352         */
353        @Override       // TableFilter
354        public void setSql( final String sql ) {
355                this.sql = sql;
356        }
357
358        /**
359         * ボディー部分のSQLを取得します。
360         *
361         * @og.rev 4.2.4.0 (2008/06/23) 新規追加
362         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
363         *
364         * @return ボディー部分のSQL
365         */
366        @Override       // TableFilter
367        public String getSql() {
368                return sql;
369        }
370
371        /**
372         * パラメーターMapを指定します。
373         *
374         * keys,vals と パラメーターMapを同時に指定した場合は、両方とも有効です。
375         * ただし、キーが重複した場合は、不定と考えてください。
376         *
377         * この受け取る時に、キーを大文字化します。TableFilter の keys は、
378         * 大文字のみで定義しておくことで、HTMLやWindows世代の曖昧な表記方法に
379         * 対応しています。(unixやxmlのような厳格な方が好きですけど)
380         *
381         * @og.rev 5.6.5.2 (2013/06/21) 新規追加
382         * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを行います。
383         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap を受け取ることを明確にするため、I/FをConcurrentMapに変更します。
384         *
385         * @param paramMap パラメーターMap
386         * @see         #setKeysVals( String[] ,String[] )
387         */
388        @Override       // TableFilter
389        public void setParamMap( final ConcurrentMap<String,String> paramMap ) {
390                // 6.4.3.3 (2016/03/04) Map#forEach に変更
391                if( paramMap != null ) {
392                        paramMap.forEach( (k,v) -> setKeyVal( k,v ) );
393                }
394        }
395
396        /**
397         * リソースオブジェクトを指定します。
398         *
399         * @og.rev 4.3.7.4 (2009/07/01) 新規追加
400         *
401         * @param resource リソースオブジェクト
402         */
403        @Override       // TableFilter
404        public void setResource( final ResourceManager resource ) {
405                this.resource = resource;
406        }
407
408        /**
409         * リソースオブジェクトを取得します。
410         *
411         * @og.rev 4.3.7.4 (2009/07/01) 新規追加
412         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
413         *
414         * @return リソースオブジェクト
415         */
416        @Override       // TableFilter
417        public ResourceManager getResource() {
418                return resource;
419        }
420
421        /**
422         * viewMarkerオブジェクトを指定します。
423         *
424         * @og.rev 8.0.0.0 (2021/09/30) viewMarker追加
425         *
426         * @param marker viewMarkerオブジェクト
427         */
428        @Override       // TableFilter
429        public void setViewMarker( final ViewMarker marker ) {
430                viewMarker = marker;
431        }
432
433        /**
434         * viewMarkerオブジェクトを取得します。
435         *
436         * @og.rev 8.0.0.0 (2021/09/30) viewMarker追加
437         *
438         * @return viewMarkerオブジェクト
439         */
440        @Override       // TableFilter
441        public ViewMarker getViewMarker() {
442                return viewMarker;
443        }
444
445        /**
446         * 値を返すためのMapを返します。
447         *
448         * Mapそのものを返しますので、中身の書き換えは行わないでください。
449         *
450         * @og.rev 7.4.0.1 (2021/04/16) 値を返すための変数
451         *
452         * @return Mapオブジェクト
453         */
454        @Override       // TableFilter
455        public Map<String,String> getReturnMap() {
456                return rtnValMap;
457        }
458
459        /**
460         * TableFilter_MAPCLM 専用のMapを管理するListを設定します。
461         *
462         * @og.rev 8.2.1.0 (2022/07/15) TableFilter_MAPCLM 専用のMapを管理するList
463         *
464         * @param       valList Mapオブジェクトのリスト
465         */
466        @Override       // TableFilter
467        public void setMapList( final List<Map<String,String>> valList ) {
468                mapList = valList ;
469        }
470
471        /**
472         * TableFilter_MAPCLM 専用のMapを管理するListを返します。
473         *
474         * リストの登録順は、vals で指定されたMapオブジェクトの登録順です。
475         * 指定がない場合は、null が返ります。
476         *
477         * @og.rev 8.2.1.0 (2022/07/15) TableFilter_MAPCLM 専用のMapを管理するList
478         *
479         * @return  Mapオブジェクト
480         */
481        protected List<Map<String,String>> getMapList() {
482                return mapList;
483        }
484
485        /**
486         * デバッグ情報を出力するかどうか[true:する/false:しない]を指定します。
487         * true でデバッグ情報を表示します。
488         *
489         * @param   flag  デバッグ出力するか [true:する/false:しない]
490         */
491        @Override       // TableFilter
492        public void setDebug( final boolean flag ) {
493                useDebug = flag;        // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更
494        }
495
496        /**
497         * デバッグ情報を出力するかどうか[true:する/false:しない]を取得します。
498         * true でデバッグ情報を表示します。
499         *
500         * @og.rev 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加
501         *
502         * @return  デバッグ出力 [true:する/false:しない]
503         */
504        @Override       // TableFilter
505        public boolean isDebug() {
506                return useDebug ;       // 6.0.2.5 (2014/10/31) refactoring メソッドと同じなので名称変更
507        }
508
509        /**
510         * エラーコード を取得します。
511         * エラーコード は、ErrorMessage クラスで規定されているコードです。
512         *
513         * @return   エラーコード
514         */
515        @Override       // TableFilter
516        public int getErrorCode() {
517                return errCode;
518        }
519
520        /**
521         * エラーメッセージオブジェクト を取得します。
522         *
523         * @return   エラーメッセージオブジェクト
524         */
525        @Override       // TableFilter
526        public ErrorMessage getErrorMessage() {
527                return errMessage;
528        }
529
530        /**
531         * タイトルとエラーコードを指定して、エラーメッセージオブジェクト を作成します。
532         * すでに、作成済みの場合は、作成済みのオブジェクトを、まだ、未作成の場合は、
533         * 新規に作成します。
534         *
535         * @param       title   タイトル
536         * @param       code    エラーコード
537         *
538         * @return      エラーメッセージオブジェクト
539         */
540        protected ErrorMessage makeErrorMessage( final String title,final int code ) {
541                if( errMessage == null ) {
542                        errMessage = new ErrorMessage( title );
543                }
544                if( errCode < code ) { errCode = code; }
545                return errMessage;
546        }
547
548        /**
549         *  カラム名配列(String[])より、対応するカラムNo配列(int[])を作成します。
550         *
551         * @param       nameArray カラム名配列
552         *
553         * @return      カラムNo配列(可変長引数)
554         */
555        protected int[] getTableColumnNo( final String... nameArray ) {
556                int[] clmNo = new int[nameArray.length];
557                for( int i=0; i<clmNo.length; i++ ) {
558                        clmNo[i] = table.getColumnNo( nameArray[i] );
559                }
560                return clmNo;
561        }
562
563        /**
564         * 設定されたパラメータキーに対する値を取得します。
565         * 引数、および、パラメータが null の場合は、 null を返します。
566         *
567         * @og.rev 6.4.3.3 (2016/03/04) ConcurrentHashMap の not null制限のチェック追加
568         *
569         * @param       key     パラメータキー
570         *
571         * @return      パラメータ値
572         */
573        protected String getValue( final String key ) {
574                return key == null ? null : keyValMap.get( key );
575        }
576
577        /**
578         * フィルターからtaglibのリクエスト変数に値を書き戻したい場合に、key と val をセットします。
579         * 引数、および、パラメータが null の場合は、何もしません。
580         *
581         * @og.rev 7.4.0.1 (2021/04/16) 値を返すための変数セット
582         *
583         * @param       key     戻しキー
584         * @param       val     戻し値
585         */
586        protected void setValue( final String key ,final String val ) {
587                if( key != null && val != null ) {
588                        rtnValMap.put( key,val );
589                }
590        }
591
592        /**
593         * keyValMapに持っているキーの配列を取得します。
594         * これは、サブクラスで、initSet(String,String) を行わない場合、keys には
595         * 値を自由に設定できます。
596         * その値を取り出すためです。
597         *
598         * @og.rev 6.7.9.1 (2017/05/19) 新規追加
599         *
600         * @return      キー値の配列(keyValMapに持っているキー)
601         */
602        protected String[] getKeys() {
603                return keyValMap.keySet().toArray( new String[keyValMap.size()] );
604        }
605}