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}