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.io;
017
018import java.util.concurrent.ConcurrentMap;                                                                              // 7.0.1.2 (2018/11/04)
019import java.util.concurrent.ConcurrentHashMap;                                                                  // 7.0.1.2 (2018/11/04)
020
021// import org.opengion.fukurou.system.HybsConst;
022import org.opengion.fukurou.util.StringUtil;                                                                    // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientEmptyStringCheck 対応
023import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;                              // 8.0.0.0 (2021/08/31)
024import static org.opengion.fukurou.system.HybsConst.CR;                                                 // 8.0.0.0 (2021/08/31)
025
026/**
027 * JsChartData は、JsChartData の個別属性を管理しているデータ管理クラスです。
028 *
029 * 内部には、data:datasets: の 要素の属性と、options:scales:[x/y]: の 要素の属性を管理します。
030 * chartColumn、useAxis 属性は別管理で、ticks と、grid:属性 は、関連する属性を無効化します。
031 * datasetOptions と、yAxesOptions は、直接追加されますので、既存の属性をセットしている場合は、
032 * 動作保障できません。
033 *
034 * 8.0.0.0 (2021/08/31) V2 → V3 対応
035 *  scaleLabel → title
036 *  gridLines  → grid
037 *  options       追加
038 *  plugins       追加(options:plugins:)
039 *  annotations   追加(plugins:annotation:annotations:)
040 *
041 * @og.rev 5.9.17.2 (2017/02/08) 新規作成
042 * @og.rev 7.0.1.1 (2018/10/22) 大幅見直し
043 * @og.rev 8.0.0.0 (2021/08/31) Ver3対応 大幅見直し
044 *
045 * @version     8.0.0.0
046 * @author      T.OTA
047 * @since       JDK11.0
048 *
049 */
050public class JsChartData {
051        /** チャート属性 {@value} */ public static final String DATASET               = "dataset";
052        /** チャート属性 {@value} */ public static final String AXIS          = "axis";
053        /** チャート属性 {@value} */ public static final String TICKS         = "ticks";
054        /** チャート属性 {@value} */ public static final String TIME          = "time";                               // X軸用 axis属性
055//      /** チャート属性 {@value} */ public static final String SCALE_LABEL   = "scaleLabel";
056        /** チャート属性 {@value} */ public static final String TITLE         = "title";                              // 8.0.0.0 (2021/08/31) V2 → V3 対応
057//      /** チャート属性 {@value} */ public static final String GRID_LINES    = "gridLines";
058        /** チャート属性 {@value} */ public static final String GRID          = "grid";                               // 8.0.0.0 (2021/08/31) V2 → V3 対応
059
060        /** チャート属性 {@value} */ public static final String OPTIONS               = "options";                    // 8.0.0.0 (2021/08/31) V2 → V3 対応
061        /** チャート属性 {@value} */ public static final String PLUGINS               = "plugins";                    // 8.0.0.0 (2021/08/31) V2 → V3 対応
062        /** チャート属性 {@value} */ public static final String ANNOTATIONS   = "annotations";                // 8.0.0.0 (2021/08/31) V2 → V3 対応
063
064        private static final String CR_TAB = CR + "\t\t";                                                       // 8.0.0.0 (2021/08/31)
065
066//      final int MAX_LEN = SCALE_LABEL.length();                                                                       // 暫定的に最も長い文字列
067
068//      private final String[] AXIS_OPTS = new String[] { TICKS,TIME,SCALE_LABEL,GRID_LINES } ; // 7.2.9.4 (2020/11/20) private 追加
069        // 8.5.4.2 (2024/01/12) PMD 7.0.0 UseShortArrayInitializer
070//      private final String[] AXIS_OPTS = new String[] { TICKS,TIME,TITLE,GRID } ;                             // 8.0.0.0 (2021/08/31) V2 → V3 対応
071        private final String[] AXIS_OPTS = { TICKS,TIME,TITLE,GRID } ;                          // 8.0.0.0 (2021/08/31) V2 → V3 対応
072
073        private final ConcurrentMap<String,StringBuilder> charts  = new ConcurrentHashMap<>();  // 7.0.1.2 (2018/11/04) チャート本体のバッファのMap (not null保障)
074//      private final ConcurrentMap<String,StringBuilder> options = new ConcurrentHashMap<>();  // 7.0.1.2 (2018/11/04) オプションバッファのMap (not null保障)
075
076        private String  chartColumn                     ;                                                                               // チャートカラム
077        private String  yid                                     ;                                                                               // yAxesIDに使用するキーとなるid ( yAxesID=yid+'Ax' )
078        private boolean useAxis                         ;                                                                               // y軸表示を行うかどうか(true/false)
079        private boolean useTime                         ;                                                                               // x軸の時間表示を使用するかどうか。
080
081//      private final StringBuilder errBuf = new StringBuilder();                                       // 8.0.0.0 (2021/08/31)
082        private final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE );        // 8.5.4.2 (2024/01/12) PMD 7.0.0 InsufficientStringBufferDeclaration
083
084//      private final StringBuilder dataset = new StringBuilder( BUFFER_MIDDLE );
085//      private final StringBuilder axis    = new StringBuilder( BUFFER_MIDDLE );
086//      private final StringBuilder ticks   = new StringBuilder( BUFFER_MIDDLE );       // axis の属性
087//      private final StringBuilder scLbl   = new StringBuilder( BUFFER_MIDDLE );       // axis の属性
088//      private final StringBuilder grdLine = new StringBuilder( BUFFER_MIDDLE );       // axis の属性
089//      private final StringBuilder time    = new StringBuilder( BUFFER_MIDDLE );       // axis の属性
090
091        /**
092         * デフォルトコンストラクター
093         *
094         * @og.rev 6.9.7.0 (2018/05/14) PMD Each class should declare at least one constructor
095         */
096        public JsChartData() { super(); }       // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
097
098        /**
099         * チャートカラムを設定します。
100         *
101         * @param       chartColumn     チャートカラム
102         */
103        public void setChartColumn( final String chartColumn ) {
104                this.chartColumn = chartColumn;
105//              addDataset( "data" , chartColumn , true );      // オブジェクトなので、クオート処理しません。
106        }
107
108        /**
109         * JsChartData オブジェクトを作成する時のチャートカラムを取得します。
110         *
111         * @return      チャートカラム
112         */
113        public String getChartColumn() {
114                return chartColumn;
115        }
116
117        /**
118         * データチャートのIDを指定します。
119         *
120         * yAxisIDに使用するキーとなるid ( yAxisID=yid+'Ax' )
121         *
122         * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
123         *
124         * @param       id      固有の名前
125         */
126        public void setId( final String id ) {
127                yid = id;
128
129                addAxis( "id" , yid + "Ax" , false );
130        }
131
132        /**
133         * y軸表示を使用するかどうか(true/false)を設定します。
134         *
135         * 使用するとは、yAxisID属性を、内部的に登録します。
136         *
137         * @param       flag    true:使用する/false:使用しない
138         */
139        public void setUseAxis( final boolean flag ) {
140                useAxis = flag;
141        }
142
143        /**
144         * y軸表示を使用するかどうか(true/false)を設定します。
145         *
146         * @return      true:使用する/false:使用しない
147         */
148        public boolean isUseAxis() {
149                return useAxis;
150        }
151
152        /**
153         * x軸の時間表示を使用するかどうか(true/false)を設定します。
154         *
155         * 使用しない場合は、time バッファーを axis 属性に追加しません。
156         *
157         * @param       flag    true:使用する/false:使用しない
158         */
159        public void setUseTime( final boolean flag ) {
160                useTime = flag;
161        }
162
163        /**
164         * キーと設定値をdatasetに追加します。
165         *
166         * @param       key             キー
167         * @param       val             設定値
168         * @param       isNum   数値項目/boolean項目かどうか(true:数値要素/false:文字または配列要素)
169         */
170        public void addDataset( final String key , final String val , final boolean isNum ) {
171                addBuffer( DATASET,key,val,isNum );
172        }
173
174        /**
175         * キーと設定値をaxisに追加します。
176         *
177         *  ※ chartJS上は、Axes(axisの複数形)と、Axis を使い分けていますが、属性は、axis で統一します。
178         *
179         * @param       key             キー
180         * @param       val             設定値
181         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
182         */
183        public void addAxis( final String key , final String val , final boolean isNum ) {
184                addBuffer( AXIS,key,val,isNum );
185        }
186
187        /**
188         * 設定値をaxisに追加します。
189         *
190         * これは、chartsバッファに、bufKey 毎のバッファに、引数をそのまま追加します。
191         *
192         * @og.rev 8.0.0.0 (2021/08/31) 新規作成
193         *
194         * @param       bufKey  追加するバッファのキー
195         * @param       val             設定値
196         */
197        public void addAxis( final String bufKey , final String val ) {
198                if( val != null && val.length() > 0 ) {
199                        // チャート本体のバッファに追加していきます。
200                        final StringBuilder buf = charts.computeIfAbsent( bufKey , k -> new StringBuilder( BUFFER_MIDDLE ) );
201                        // 登録時の同一キーワードチェック
202                        final int st = val.indexOf( ':' );
203                        if( st > 0 && buf.indexOf( val.substring( 0,st+1 ) ) >= 0 ) {           // キーチェックは、':' も含めて確認する
204                                errBuf.append( "addAxisで登録された" ).append( bufKey )
205                                                .append( "属性は、chartsに設定済みです。" ).append( CR )
206                                                .append( "val=" ).append( val ).append( CR );
207                        }
208                        else {
209                                buf.append( val ).append( ',' );
210                        }
211                }
212        }
213
214        /**
215         * キーと設定値をaxisのticks に追加します。
216         *
217         * @param       key             キー
218         * @param       val             設定値
219         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
220         */
221        public void addTicks( final String key , final String val , final boolean isNum ) {
222                addBuffer( TICKS,key,val,isNum );
223        }
224
225        /**
226         * キーと設定値をaxisのtime に追加します。
227         *
228         * @param       key             キー
229         * @param       val             設定値
230         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
231         */
232        public void addTime( final String key , final String val , final boolean isNum ) {
233                addBuffer( TIME,key,val,isNum );
234        }
235
236        /**
237         * キーと設定値をplugins に追加します。
238         *
239         * @og.rev 8.0.0.0 (2021/08/31) 新規作成
240         *
241         * @param       key             キー
242         * @param       val             設定値
243         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
244         */
245        public void addPlugins( final String key , final String val , final boolean isNum ) {
246                addBuffer( PLUGINS,key,val,isNum );
247        }
248
249        /**
250         * キーと設定値をannotations に追加します。
251         *
252         * @og.rev 8.0.0.0 (2021/08/31) 新規作成
253         *
254         * @param       key             キー
255         * @param       val             設定値
256         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
257         */
258        public void addAnnotations( final String key , final String val , final boolean isNum ) {
259                addBuffer( ANNOTATIONS,key,val,isNum );
260        }
261
262        /**
263         * キーと設定値を指定のバッファーに追加します。
264         *
265         * isNum=true か、内部で、先頭文字が、'[' か '{' の場合は、クオーテーションを付けません。
266         * また、引数が、nullか、空文字列の場合は、追加しません。
267         *
268         * @param       bufKey  追加するバッファのキー
269         * @param       key             キー
270         * @param       val             設定値
271         * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列、オブジェクト要素)
272         */
273        private void addBuffer( final String bufKey , final String key , final String val , final boolean isNum ) {
274                // 8.5.4.2 (2024/01/12) PMD 7.0.0 InefficientEmptyStringCheck 対応
275//              if( val != null && !val.trim().isEmpty() ) {
276//              if( StringUtil.isNull( val ) ) {
277                if( StringUtil.isNotNull( val ) ) {                     // 8.5.5.0 (2024/02/02) 間違い訂正
278                        final String val2 = val.trim();
279
280                        // チャート本体のバッファに追加していきます。
281                        final StringBuilder buf = charts.computeIfAbsent( bufKey , k -> new StringBuilder( BUFFER_MIDDLE ) );
282
283                        // 登録時の同一キーワードチェック
284                        if( buf.indexOf( key+':' ) >= 0 ) {                             // キーチェックは、':' も含めて確認する
285                                errBuf.append( "addBufferで登録された" ).append( bufKey ).append( ':' ).append( key )
286                                                .append( "属性は、chartsに設定済みです。" ).append( CR )
287                                                .append( "key:val=" ).append( key ).append( ':' ).append( val2 ).append( CR );
288                        }
289                        else {
290                                // bufKey が DATASET とAXIS の場合は、40文字単位で改行する。
291                                // 8.5.4.2 (2024/01/12) PMD 7.0.0 CollapsibleIfStatements
292//                              if( DATASET.equals( bufKey ) || AXIS.equals( bufKey ) ) {
293//                                      if( buf.length() - buf.lastIndexOf( CR ) > 40 ) {
294//                                              buf.append( CR_TAB );
295//                                      }
296//                              }
297                                if( (DATASET.equals( bufKey ) || AXIS.equals( bufKey ) ) &&
298                                        ( buf.length() - buf.lastIndexOf( CR ) > 40 ) ) {
299                                                buf.append( CR_TAB );
300                                }
301
302                                if( isNum || '[' == val2.charAt(0) || '{' == val2.charAt(0) ) {
303                                        buf.append( key ).append( ':' ).append( val2 ).append( ',' );
304                                }
305                                else {
306                                        buf.append( key ).append( ":'" ).append( val2 ).append( "'," );
307                                }
308                        }
309                }
310        }
311
312//      /**
313//       * 指定のバッファーに、オプション属性を追加します。
314//       *
315//       * オプション属性は、各バッファーの一番最後にまとめて追加します。
316//       * key:val の関係ではなく、val だけをそのまま追加していきます。
317//       * オプションの追加は、まとめて最後に行いますので、このメソッド上では
318//       * 最後にカンマは付けません。必要であれば、追加する設定値にカンマをつけてください。
319//       *
320//       * @og.rev 8.0.0.0 (2021/08/31) コメント修正(scaleLabel→title , gridLines→grid)
321//       *
322//       * @param       bufKey  キー [dataset,axis,ticks,time,scaleLabel,gridLines] が指定可能
323//       * @param       val             設定値
324//       */
325//      public void addOptions( final String bufKey , final String val ) {
326//              if( val != null && val.length() > 0 ) {
327//                      // オプション専用のバッファに追加していきます。
328//                      // これは、チャート本体のバッファに対して、最後に追加する必要があるためです。
329////                    options.computeIfAbsent( bufKey , k -> new StringBuilder( BUFFER_MIDDLE ) )
330////                                            .append( val ).append( ',' );
331//
332//                      // オプション専用のバッファに追加していきます。
333//                      final StringBuilder buf = options.computeIfAbsent( bufKey , k -> new StringBuilder( BUFFER_MIDDLE ) );
334//
335//                      // 登録時の同一キーワードチェック
336//                      final int st = val.indexOf( ':' );
337//                      if( st > 0 && buf.indexOf( val.substring( 0,st+1 ) ) >= 0 ) {   // キーチェックは、':' も含めて確認する
338//                              errBuf.append( "addOptionsで登録された" ).append( bufKey )
339//                                              .append( "属性は、options に設定済みです。" ).append( CR )
340//                                              .append( "val=" ).append( val ).append( CR );
341//                      }
342//                      else {
343//                              buf.append( val ).append( ',' ).append( CR_TAB );
344//                      }
345//              }
346//      }
347
348//      /**
349//       * キーと設定値をoptions に追加します。
350//       *
351//       * @og.rev 8.0.0.0 (2021/08/31) 新規作成
352//       *
353//       * @param       key             キー
354//       * @param       val             設定値
355//       * @param       isNum   数値項目かどうか(true:数値要素/false:文字または配列要素)
356//       */
357//      public void addOptions( final String key , final String val , final boolean isNum ) {
358//              if( val != null && !val.trim().isEmpty() ) {
359//                      final String val2 = val.trim();
360//
361//                      // チャート本体のバッファに追加していきます。
362//                      final StringBuilder buf = options.computeIfAbsent( key , k -> new StringBuilder( BUFFER_MIDDLE ) );
363//
364//                      // 登録時の同一キーワードチェック
365//                      if( buf.indexOf( key+':' ) >= 0 ) {     // キーチェックは、':' も含めて確認する
366//                              errBuf.append( "addOptionsで登録された" ).append( key )
367//                                              .append( "属性は、optionsに設定済みです。" ).append( CR )
368//                                              .append( "key:val=" ).append( key ).append( ':' ).append( val2 ).append( CR );
369//                      }
370//                      else {
371//                              if( isNum || '[' == val2.charAt(0) || '{' == val2.charAt(0) ) {
372//                                      buf.append( key ).append( ':' ).append( val2 ).append( ',' ) ;
373//                              }
374//                              else {
375//                                      buf.append( key ).append( ":'" ).append( val2 ).append( "'," ) ;
376//                              }
377//                      }
378//              }
379//      }
380
381        /**
382         * バッファキー内に、設定キーの値がすでに登録済みかどうか(あればtrue)を判定します。
383         *
384         * 一般とオプションの両方を検索します。
385         *
386         * @og.rev 7.0.1.3 (2018/11/12) バッファキー検索処理追加
387         *
388         * @param       bufKey  チェックするバッファのキー
389         * @param       key             キー
390         * @return      すでに登録済みかどうか [true:登録済み/false:未登録]
391         */
392        public boolean contains( final String bufKey , final String key ) {
393                boolean isContains = false;
394
395                final StringBuilder chBuf = charts.get( bufKey );
396                if( chBuf != null && chBuf.indexOf( key ) >= 0 ) { isContains = true; }
397//              else {
398//                      final StringBuilder optBuf = options.get( bufKey );
399//                      if( optBuf != null && optBuf.indexOf( key ) >= 0 ) { isContains = true; }
400//              }
401
402                return isContains ;
403        }
404
405        /**
406         * JsChartData オブジェクトのdata:datasets: パラメータ情報を取得します。
407         *
408         * ここで返す値は、yidが、'y0' とすると、
409         * const y0Ds = { dataset.toString() } ; という文字列を返します。
410         * 引数は、'x' か 'y' を指定します。
411         * 通常、Y軸表示を行う場合は、'y' を指定しまが、horizontalBar 使用時は、
412         * 'x' を指定することになります。
413         * ただし、useAxis=false の場合は、(x,y)AxisID は出力されません。
414         *
415         * @og.rev 7.0.1.1 (2018/10/22) data:datasets: パラメータ情報
416         *
417         * @param       xy      idのキーワード [x,y]
418         * @return      パラメータ文字列
419         */
420        public String getDataset( final char xy ) {
421                // チャート本体のバッファから取得します。
422                final StringBuilder dataset = charts.computeIfAbsent( DATASET , k -> new StringBuilder( BUFFER_MIDDLE ) );
423
424                // chartColumn は linear の場合、名前が変更されるので、出力の直前にセッティングします。
425                dataset.append( "data:" ).append( chartColumn ).append( ',' ) ;
426
427                // 8.0.0.0 (2021/08/31) yidの初期値(1つ目)は、AxisID を出さない。
428//              if( useAxis && dataset.indexOf( "AxisID:" ) < 0 ) {
429                if( useAxis && dataset.indexOf( "AxisID:" ) < 0 && !"y0".equals( yid ) ) {
430                        dataset.append( xy ).append( "AxisID:'" ).append( getAxisKey() ).append( "'," );
431                }
432
433                return new StringBuilder( BUFFER_MIDDLE )
434//                                      .append( "var " ).append( getDatasetKey() ).append( "={" )
435                                        .append( "const " ).append( getDatasetKey() ).append( "={" )
436                                        .append( dataset )
437//                                      .append( mapGet( options , DATASET ) )          // オプション専用のバッファ
438                                        .append( CR ).append( "\t};" ).toString();
439        }
440
441        /**
442         * JsChartData オブジェクトのdata:datasets: パラメータ情報の変数名を取得します。
443         *
444         * ここで返す値は、yidが、'y0' とすると、
445         * "y0Ds" という文字列を返します。
446         *
447         * @og.rev 7.0.1.1 (2018/10/22) data:datasets: パラメータ変数名
448         *
449         * @return      パラメータ文字列
450         */
451        public String getDatasetKey() {
452                return yid + "Ds" ;
453        }
454
455        /**
456         * JsChartData オブジェクトのoptions:scales:yAxes: パラメータ情報を取得します。
457         *
458         * ここで返す値は、yidが、'y0' とすると、
459         * const y0Ax = { addAxis.toString() } ; という文字列を返します。
460         * ただし、useAxis=false の場合は、ゼロ文字列を返します。
461         *
462         * @og.rev 7.0.1.1 (2018/10/22) options:scales:yAxes: パラメータ情報
463         *
464         * @return      パラメータ文字列
465         */
466        public String getAxis() {
467                // チャート本体のバッファから取得します。
468                final StringBuilder axis = charts.computeIfAbsent( AXIS , k -> new StringBuilder( BUFFER_MIDDLE ) );
469
470                // AXISのオプションである、TICKS,TIME,TITLE,GRID を追加します。
471                // これらは、チャート本体とオプション専用のバッファから取得しますが、オプション専用バッファは最後に追加します。
472                for( final String opt : AXIS_OPTS ) {
473                        // 超特殊処理:useTime=false のときは、TIME は、処理しません。
474                        if( !useTime && TIME.equals( opt ) ) { continue; }
475
476                        final String key = opt + ":{" ;
477//                      if( axis.indexOf( key ) < 0 && ( charts.containsKey( opt ) || options.containsKey( opt ) ) ) {
478                        if( axis.indexOf( key ) < 0 && charts.containsKey( opt ) ) {
479                                axis.append( CR_TAB ).append( key )
480                                        .append( mapGet( charts  , opt ) )                      // チャート本体のバッファ
481//                                      .append( mapGet( options , opt ) )                      // オプション専用のバッファ
482                                        .append( "}," );
483                        }
484                }
485
486                return new StringBuilder( BUFFER_MIDDLE )
487//                                      .append( "var " ).append( getAxisKey() ).append( "={" )
488                                        .append( "const " ).append( getAxisKey() ).append( "={" )
489                                        .append( axis )
490//                                      .append( mapGet( options , AXIS ) )                     // オプション専用のバッファ
491                                        .append( CR ).append( "\t};" ).toString();
492        }
493
494        /**
495         * JsChartData オブジェクトのoptions:scales:yAxes: パラメータ情報の変数名を取得します。
496         *
497         * ここで返す値は、yidが、'y0' とすると、
498         * "y0Ax ," という文字列を返します。便宜上、後ろのコロンも追加しています。
499         * その際、useAxis=false の場合は、空文字列を返します。
500         *  ※ chartJS上は、Axes(axisの複数形)と、Axis を使い分けていますが、属性は、axis で統一します。
501         *
502         * @og.rev 7.0.1.1 (2018/10/22) options:scales:yAxes:パラメータ情報の変数名
503         *
504         * @return      パラメータ文字列
505         */
506        public String getAxisKey() {
507                return yid + "Ax" ;
508        }
509
510        /**
511         * MapのStringBuilderがnullなら、ゼロ文字列を、そうでなければ、StringBuilder#toString()
512         * の値を返します。
513         *
514         * map.getOrDefault( KEY , new StringBuilder() ) ).toString()
515         * という処理の簡易版です。
516         *
517         * final StringBuilder buf = map.get( KEY );
518         * return buf == null || buf.length() == 0 ? "" : buf.toString();
519         *
520         * @og.rev 7.0.1.2 (2018/11/04) 新規登録
521         *
522         * @param       map     判定するMap
523         * @param       key     Mapから取り出すキー
524         * @return      MapにStringBuilderがあれば、#toString()を、無ければ、ゼロ文字列を返します。
525         */
526//      private String nval( final ConcurrentMap<String,StringBuilder> map , final String key ) {
527        private String mapGet( final ConcurrentMap<String,StringBuilder> map , final String key ) {
528                final StringBuilder buf = map.get( key );
529                return buf == null || buf.length() == 0 ? "" : buf.toString();
530        }
531
532        /**
533         * エラーメッセージを返します。
534         *
535         * エラーが存在しなかった場合は、長さゼロの文字列になります。
536         *
537         * @og.rev 8.0.0.0 (2021/08/31) 新規作成
538         *
539         * @return      エラーメッセージの内部バッファを文字列にして返します。
540         * @og.rtnNotNull
541         */
542        public String getErrorMessage() {
543                return errBuf.toString();
544        }
545
546        /**
547         * 内部バッファを文字列にして返します。
548         *
549         * @return      内部バッファを文字列にして返します。
550         * @og.rtnNotNull
551         */
552        @Override
553        public String toString() {
554                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
555                        .append( "chartColumn=" ).append( chartColumn     ).append( CR )
556                        .append( "datasetKey =" ).append( getDatasetKey() ).append( CR )
557                        .append( "axisKey    =" ).append( getAxisKey()    ).append( CR );
558
559                charts.forEach(  (k,v) -> buf.append( k ).append( " = "     ).append( v ).append( CR ) );
560//              options.forEach( (k,v) -> buf.append( k ).append( " opt = " ).append( v ).append( CR ) );
561
562                return buf.toString();
563        }
564}