/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.hayabusa.taglib;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;											// 6.4.3.4 (2016/03/11)
import java.util.Iterator;										// 6.7.7.0 (2017/03/31)
import java.util.function.IntFunction;							// 7.0.1.3 (2018/11/12)

// import org.opengion.fukurou.system.BuildNumber;					// 7.0.1.2 (2018/11/04)
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.DBTableModelSorter;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.db.DBColumn;						// 6.8.3.1 (2017/12/01)
import org.opengion.hayabusa.io.JsChartDataV3;					// 7.0.1.1 (2018/10/22)

import org.opengion.fukurou.util.ArraySet;						// 6.4.3.4 (2016/03/11)
import org.opengion.fukurou.util.ToString;
import org.opengion.fukurou.util.StringUtil;					// 6.8.3.1 (2017/12/01)
import org.opengion.fukurou.util.ColorMap;						// 7.0.1.3 (2018/11/12)
import static org.opengion.fukurou.util.StringUtil.nval ;

/**
 * JsChartV3 は、JavascriptのjsChart用のｽｸﾘﾌﾟﾄを出力するクラスです。
 * 複数の JsChartDataV3 オブジェクトを合成することも、ここで行っています。
 * ChartJSのVer3を利用しているため、標準属性以外の項目をセットする場合はoptionAttributesで行ってください。
 *
 * 出力されるスクリプトでは、idを指定しない場合はhybscanvas[tableId]が利用されます。
 * 複数のグラフを同一画面で出力する場合はidかtableIdを変えてください。
 * チャートオブジェクトはchart_[id]という名前で作成されるため、ajax等でコントロールが必要な場合は利用してください。
 *
 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html">とほほのChart.js入門</a>
 *
 * ChartのGlobal Configurationとして、Chart.defaults.**** が指定できる。これは本ﾀｸﾞでは
 * 用意していないが、グローバルなので、タグの前に個別に記述しておくことで適用される。
 *
 * <a href="https://www.chartjs.org/docs/latest/configuration/">Configuration</a>
 *
 * @og.formSample
 * ●形式：&lt;og:jsChartV3 chartType="…" ... /&gt;
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{$#064;XXXX} を解析します)
 *
 * ●Tag定義：
 *  &lt;og:jsChartV3
 *      chartType       ○【TAG】ﾁｬｰﾄの種類(type属性)を指定します[line/bar/radar/polarArea/pie/doughnut/bubble/scatter](必須)
 *                                  horizontalBar 廃止 → indexAxis="y" 指定verticalLine 相当の表示も indexAxis="y" 指定
 *      labelColumn     ○【TAG】ﾗﾍﾞﾙのｶﾗﾑ名(data:labels属性)を指定します(表示名称）(必須)
 *      id                【TAG】canvasﾀｸﾞのidを指定します(初期値:hybscanvas)
 *      height            【TAG】ﾁｬｰﾄ(canvasﾀｸﾞ)の高さを指定します(初期値:400px)
 *      width             【TAG】ﾁｬｰﾄ(canvasﾀｸﾞ)の幅を指定します(初期値:400px)
 *      plugins           【TAG】プラグイン定義された関数を指定します(plugins)	// 6.9.9.2 (2018/09/18)
 *  =================== options: 以下の属性
 * (V3) indexAxis         【TAG】"y" を指定することで、horizontalBar や verticalLine を実現する(options:indexAxis)	8.0.0.0 (2021/08/31) 新規追加
 *      barWidthPer       【TAG】棒線の横幅を指定します(初期値:0.8, typeがbar の場合に有効)(option:categoryPercentage)
 *      animation         【TAG】簡易的にアニメーションのON/OFFを設定(true/false)します(初期値::null=true)(options:animation)
 *      onClick           【TAG】ﾁｬｰﾄｸﾘｯｸ時のｲﾍﾞﾝﾄを指定します(options:onClick)
 *      optOptions        【TAG】optionsの要素に、その他ｵﾌﾟｼｮﾝを追加します
 *  =================== options:scales:x: 以下の属性
 *      xscaleType        【TAG】x軸のｽｹｰﾙﾀｲﾌﾟ[category/linear/time/realtime]を指定します(type[初期値:category])
 *      xposition         【TAG】x軸の表示位置[top/right/bottom/left]を指定します(初期値:bottom)(position)
 *      xmax              【TAG】x軸の最大値を指定します(xscaleTypeがlinearの場合に有効)(max)
 *      xmin              【TAG】x軸の最小値を指定します(xscaleTypeがlinearの場合に有効)(min)
 *      xlabel            【TAG】x軸のラベルを指定します(title:text)
 *      xscaleCallback    【TAG】x軸ｺｰﾙﾊﾞｯｸを指定します(ticks:callback)
 *      xbeginAtZero      【TAG】x軸を０から書き始まるかどうか(xscaleTypeがlinearの場合に有効)(beginAtZero[初期値:null(=false)])
 *      xstepSize         【TAG】x軸のメモリ幅を指定します(xscaleTypeがlinearの場合に有効)(ticks:stepSize)
 *      optAxis           【TAG】その他options:scales:x のｵﾌﾟｼｮﾝを追加します
 *      optTicks          【TAG】その他options:scales:x:ticksのｵﾌﾟｼｮﾝを追加します
 * (V3) optTitle          【TAG】その他options:scales:x:titleのｵﾌﾟｼｮﾝを追加します	8.0.0.0 (2021/08/31) 新規追加
 * (V3) optGrid           【TAG】その他options:scales:x:gridのｵﾌﾟｼｮﾝを追加します	8.0.0.0 (2021/08/31) 新規追加
 *  =================== options:scales:x:time: 以下の属性(xscaleTypeがtimeの場合に有効)
 *      timeUnit          【TAG】x軸のﾀｲﾑの単位[year/quarter/month/week/day/hour/minute/second/millisecond]を指定(unit)します(指定しない場合は自動)
 *      timeUnitStepSize  【TAG】x軸のﾀｲﾑの単位幅を指定します(stepSize)
 * (V3) timeParser        【TAG】x軸の設定するﾀｲﾑ(入力ﾃﾞｰﾀ)のﾌｫｰﾏｯﾄを指定します ･･･ 廃止 → time.parser になったが使い方不明 	8.0.0.0 (2021/08/31) 新規追加
 *      timeLblFormat     【TAG】x軸の表示するﾀｲﾑのﾌｫｰﾏｯﾄを指定します(time:displayFormats:year～secondまで同じ値を設定) → displayFormats
 *      tooltipFormat     【TAG】時間のﾂｰﾙﾁｯﾌﾟに使用するﾌｫｰﾏｯﾄ(tooltipFormat)
 *  =================== options:plugins: 以下の属性
 *      title             【TAG】ﾀｲﾄﾙ、またはﾀｲﾄﾙ要素を指定します(title:text)
 *      titlePosition     【TAG】ﾀｲﾄﾙの表示位置[top/right/bottom/left]を指定します(title:position:初期値 top)
 *      legendDisplay     【TAG】凡例を表示するか[true/false]を指定します(legend:display)
 *      legendPosition    【TAG】凡例の表示位置[top/right/bottom/left]を指定します(legend:position)
 *      usePointStyle     【TAG】凡例のスタイル属性を使用するかどうか[true/false]を指定します(legend:labels:usePointStyle)
 * (V3) optPlugins        【TAG】options:pluginsの要素に、その他ｵﾌﾟｼｮﾝを追加します
 * (V3) optTooltip        【TAG】options:plugins:tooltip の要素に、その他ｵﾌﾟｼｮﾝを追加します
 * (V3) optLegend         【TAG】options:plugins:legend の要素に、その他ｵﾌﾟｼｮﾝを追加します
 *  =================== options:plugins:annotation:annotations:(CSVで指定した分のline0): 以下の属性
 *      markValues        【TAG】y軸に横マーカーラインの設定値をCSV形式で複数指定します(yMin:値,yMax:値)
 *      markColors        【TAG】y軸に横マーカーラインの色をCSV形式で複数指定します(borderColor)
 *      markLbls          【TAG】y軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)(label:content)
 *      markAdjust        【TAG】y軸に横マーカーラインのラベル表示位置の上(－)下(＋)方向を調整します(yAdjust:初期値 -6)
 *      xmarkLbls         【TAG】x軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)(label:content)
 *      xmarkValues       【TAG】x軸に縦マーカーラインの設定値をCSV形式で複数指定します(xMin:値,xMax:値)
 *      xmarkColors       【TAG】x軸に縦マーカーラインの色をCSV形式で複数指定します		// 7.0.1.1 (2018/10/22)
 *      markWidth         【TAG】x軸,y軸全マーカーライン共通のラインの幅を指定します(borderWidth:初期値 2)					// 7.0.1.1 (2018/10/22)
 *      markDash          【TAG】x軸,y軸全マーカーライン共通のラインに点線を指定([5,2]など)します:(borderDash:初期値 null)	// 7.0.1.1 (2018/10/22)
 *      markFontSize      【TAG】x軸,y軸全マーカーライン共通のラベルのフォントサイズを指定します:(label:font:size:初期値 10)
 *  =================== options:plugins:zoom: 以下の属性
 *      useZoom           【TAG】WheelZoom処理を使用するかどうか[true/false]を指定します(options:plugins:zoom:zoom:)
 *      useDragZoom       【TAG】DragZoom処理を使用するかどうか[true/false]を指定します(options:plugins:zoom:zoom:)
 *  ===================
 *      useZeroDataOmit   【TAG】ﾃﾞｰﾀが０の場合、使用しない（除外する）かどうかを指定します[true:０ﾃﾞｰﾀを除外する](初期値:false)
 *      useRenderer       【TAG】データ出力でレンデラを利用するかどうか[true/false]を指定します(初期値:false)
 *      sortColumn        【TAG】検索結果をこのカラムでソートしなおします(初期値:null)
 *      valueQuot         【TAG】値の前後にクオートをはさむかどうか[true/false]指定します
 *      varColumns        【TAG】TableModelの指定のカラムをconstの配列変数として出力します	// 7.0.1.2 (2018/11/04)
 *  ===================
 *      optChart          【廃止】chartの属性に、TLDで未定義の属性を追加します		8.0.0.0 (2021/08/31) 廃止(代替えはありません)
 *      optScaleLabel     【廃止】optTitle を使用してください(旧 scaleLabel)		8.0.0.0 (2021/08/31) 廃止
 *      optGridLines      【廃止】optGrid を使用してください(旧 gridLines)			8.0.0.0 (2021/08/31) 廃止
 *      timeMax           【廃止】廃止 → xmaxを使用してください		8.0.0.0 (2021/08/31) 廃止
 *      timeMin           【廃止】廃止 → xminを使用してください		8.0.0.0 (2021/08/31) 廃止
 *      timeSetFormat     【廃止】廃止 → timeParserを使用してください		8.0.0.0 (2021/08/31) 廃止
 *  ===================
 *      tableId           【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID
 *      scope             【TAG】キャッシュする場合のスコープ[request/page/session/application]を指定します(初期値:session)
 *      caseKey           【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
 *      caseVal           【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
 *      caseNN            【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
 *      caseNull          【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
 *      caseIf            【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
 *      debug             【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *  &gt;   ... Body ...
 *  &lt;/og:jsChartV3&gt;
 *
 * ●使用例
 *      &lt;og:jsChartV3
 *          chartType      = "[line/bar/radar/polarArea/pie/doughnut/bubble/scatter]"
 *          labelColumn    = "LDATA"
 *          id             = "hybscanvas"
 *          height         = "400px"
 *          width          = "400px"
 *          title          = "タイトル" または "{display:true,text:'ﾀｲﾄﾙ',color:'blue',font:{size:15},}" 形式
 *          titlePosition  = "top"				[top/right/bottom/left]
 *          xlabel         = "名称"
 *          legendPosition = "right"			[top/right/bottom/left]
 *          legendDisplay  = "true"				[true/false]
 *          xsclaeCallback = "function(value){return value + ' 様';}"
 *          xscaleType     = "linear"
 *          xmax           = "1000000"
 *          xmin           = "100000"
 *          xstepSize      = "10000"
 *          barWidthPer    = "0.4"
 *      &gt;
 *          &lt;og:jsChartDataV3 ... /&gt;
 *      &lt;/og:jsChartV3&gt;
 *
 * @og.rev 8.0.0.0 (2021/08/31) Ver3対応 大幅見直し
 * @og.group 画面表示
 *
 * @version	8.0
 * @author   Kazuhiko Hasegawa
 * @since	JDK11.0
 */
public class JsChartV3Tag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。{@value} */
	private static final String VERSION = "8.0.0.0 (2021/09/30)" ;
	private static final long serialVersionUID = 800020210930L ;

	private static final String IE_CHECK
			= "<script>{"
				+ "let userAgent = window.navigator.userAgent.toLowerCase();"			+ CR
				+ "if(userAgent.indexOf('msie') != -1 ||"								+ CR
				+ "   userAgent.indexOf('trident') != -1 ) {"							+ CR
				+ "    document.write('Internet Explorer では表示できません<br />');"	+ CR
				+ "}}</script>"															+ CR ;

	/** chartType 引数に渡す事の出来る タイプ 折れ線 {@value} */
	public static final String		CTYPE_LINE			= "line";
	/** chartType 引数に渡す事の出来る タイプ 棒線 {@value} */
	public static final String		CTYPE_BAR			= "bar";
//	/** chartType 引数に渡す事の出来る タイプ 横棒線 {@value} */
//	public static final String		CTYPE_HBAR			= "horizontalBar";
	/** chartType 引数に渡す事の出来る タイプ レイダー {@value} */
	public static final String		CTYPE_RADAR			= "radar";
	/** chartType 引数に渡す事の出来る タイプ ポーラエリア {@value} */
	public static final String		CTYPE_POLAR			= "polarArea";
	/** chartType 引数に渡す事の出来る タイプ 円 {@value} */
	public static final String		CTYPE_PIE			= "pie";
	/** chartType 引数に渡す事の出来る タイプ ドーナツ {@value} */
	public static final String		CTYPE_DOUGHNUT		= "doughnut";
	/** chartType 引数に渡す事の出来る タイプ バブル {@value} 8.0.0.0 (2021/08/20) 追加 */
	public static final String		CTYPE_BUBBLE			= "bubble";
	/** chartType 引数に渡す事の出来る タイプ 散乱図 {@value} 8.0.0.0 (2021/08/20) 追加 */
	public static final String		CTYPE_SCATTER		= "scatter";

	/** chartType 引数に渡す事の出来る タイプ リスト {@value} */
	private static final Set<String> CTYPE_SET
		= new ArraySet<>( CTYPE_LINE,CTYPE_BAR,CTYPE_RADAR,CTYPE_POLAR,
							CTYPE_PIE,CTYPE_DOUGHNUT,CTYPE_BUBBLE,CTYPE_SCATTER );

	// 6.9.9.4 (2018/10/01) String配列から、Set に変更
	/** chartType が円形のリスト */
	private static final Set<String> SET_CI_TYPE	= new ArraySet<>( CTYPE_RADAR, CTYPE_POLAR, CTYPE_PIE, CTYPE_DOUGHNUT );

	private static final String TYPE_CATEGORY		= "category";
	private static final String TYPE_LINEAR			= "linear";
	private static final String TYPE_TIME			= "time";
	private static final String TYPE_REALTIME		= "realtime";		// 7.0.1.2 (2018/11/04)

	private static final Set<String> SET_POSITION	= new ArraySet<>("top","right","bottom","left");
	private static final Set<String> SET_TIMEUNIT	= new ArraySet<>("year","quarter","month","week","day","hour","minute","second","millisecond");	// 8.0.0.0 (2021/08/31)
	private static final Set<String> SET_XSCALE		= new ArraySet<>( TYPE_CATEGORY, TYPE_TIME, TYPE_LINEAR, TYPE_REALTIME );
	private static final Set<String> SET_BOOLEAN	= new ArraySet<>( "true", "false" );

	private static final String 	CANVAS_NAME		= "hybscanvas";

	private static final String		MARK_DEF_ADJUST	= "-6";			// 6.8.5.0 (2018/01/09) y軸に横マーカーラインの位置調整の初期値

	// 7.0.1.3 (2018/11/12) バッファキー検索処理追加
	// 8.0.0.0 (2021/08/31) Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
	private static final String		TIME_FORMAT_JA	= "{year:'yyyy年',quarter:'yyyy年M月',month:'yyyy年M月',week:'M月d日',day:'M月d日',hour:'d日 h時',minute:'h時m分',second:'m分s秒'}" ;
	private static final String		TIME_FORMAT		= "{year:'yyyy',quarter:'yyyy/M',month:'yyyy/M',week:'M/d',day:'M/d',hour:'d HH',minute:'HH:mm',second:'HH:mm:ss'}" ;

	// 7.0.1.3 (2018/11/12) true/false なので、記号化します。
	private static final boolean	USE_QUOTE		= false;
	private static final boolean	NO_QUOTE		= true;		// IS_NUMBER か、!USE_QUOTE か、

	// JSON形式をそれなりに成形するためのタブと改行
	private static final String[]	CR_TAB = new String[10] ;
	static {
		final StringBuilder tabs = new StringBuilder().append( CR );
		for( int i=0; i<CR_TAB.length; i++ ) {
			CR_TAB[i] = tabs.toString();
			tabs.append( '\t' );
		}
	}

	private static final String WHEEL_ZOOM = "zoom:{zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},pan:{mode:'xy',enabled:true,},}," ;
	private static final String DRAG_ZOOM  = "zoom:{zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)',},},pan:{mode:'xy',enabled:true,modifierKey:'ctrl',},},";

	// 変数宣言
	// 6.9.8.0 (2018/05/28) FindBugs:直列化可能クラスの非 transient で非直列化可能なインスタンスフィールド
	private final transient	List<JsChartDataV3>	jsChartData = new ArrayList<JsChartDataV3>() ;		// 6.7.5.0 (2017/03/10) jsChartDataのﾘｽﾄ

	private transient	JsChartDataV3 jsXAxis  = new JsChartDataV3();	// xAxes の設定用(datasetは使いません)

	private String	chartBody			;							// ﾁｬｰﾄタグのBODY部分に書かれた文字列

	private String	chartType			;							// ﾁｬｰﾄﾀｲﾌﾟ(必須)
	private String	labelColumn			;							// ﾗﾍﾞﾙｶﾗﾑ(必須)
	private String	indexAxis			;							// horizontalBarや、verticalLine を実現 8.0.0.0 (2021/08/31)
	private String	id					;							// canvasﾀｸﾞのid
	private String	height				= "400px";					// canvasﾀｸﾞのheight
	private String	width				= "400px";					// canvasﾀｸﾞのwidth
	private String	title				;							// ﾀｲﾄﾙ
	private String	titlePosition		= "top";					// ﾀｲﾄﾙ位置
	private String	legendPosition		;							// 凡例位置
	private String	legendDisplay		;							// 凡例表示ﾌﾗｸﾞ
	private boolean	usePointStyle		;							// 6.8.5.0 (2018/01/09) 点のスタイル属性を使用するかどうか(初期値:false)
	private boolean	useLegend			;							// Legend関連属性(legendPosition,legendDisplay,usePointStyle) のどれかがセットされれば、true
	private String	barWidthPer			= "0.8";					// 棒線の横幅(ﾊﾟｰｾﾝﾄ)
	private String	animation			;							// 簡易的なアニメーションのON/OFF
	private String	onClick				;							// ｸﾘｯｸｲﾍﾞﾝﾄ
	private String	plugins				;							// 6.9.9.2 (2018/09/18) プラグイン定義された関数を指定します。
	private String	xscaleType			= TYPE_CATEGORY ;			// x軸のｽｹｰﾙﾀｲﾌﾟ
	private String	xposition			;							// x軸の表示位置[top/right/bottom/left]	 // 7.0.1.2 (2018/11/04)
	private boolean	valueQuot			;							// 値の前後にクオートをはさむかどうか[true/false]指定します。
	private String	tableId				= HybsSystem.TBL_MDL_KEY;	// ﾃｰﾌﾞﾙid
	private String	markValues			;							// 6.8.5.0 (2018/01/09) y軸に横マーカーラインの設定値をCSV形式で複数指定します
	private String	markColors			;							// 6.8.5.0 (2018/01/09) y軸に横マーカーラインの色をCSV形式で複数指定します
	private String	markLbls			;							// 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)
	private String	markAdjust			;							// 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベル表示位置の上下方向を調整します(初期値:-6)。
	private String	xmarkLbls			;							// 8.0.0.0 (2021/09/30) x軸に横マーカーラインのラベルをCSV形式で複数指定
	private String	xmarkValues			;							// 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの設定値をCSV形式で複数指定します
	private String	xmarkColors			;							// 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの色をCSV形式で複数指定します
	private String	markWidth			= "2";						// 7.0.1.1 (2018/10/22) マーカーライン共通のラインの幅を指定します:borderWidth(初期値:2)
	private String	markDash			;							// 7.0.1.1 (2018/10/22) マーカーライン共通のラインに点線を指定([5,2]など)します:borderDash(初期値:null)
	private String	markFontSize  		= "10";						// 7.0.1.1 (2018/10/22) マーカーライン共通のラベルのフォントサイズを指定します:fontSize(初期値:10)
	private boolean	useZoom				;							// 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか(初期値:false)
	private boolean	useDragZoom			;							// 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか(初期値:false)
	private String	varColumns  		;							// 7.0.1.2 (2018/11/04) TableModelの指定のカラムをconstの配列変数として出力します。
//	/ *      useVarCheck       【TAG】const定義するJavaScript変数に使用できるかどうか[true/false]指定します
//	private boolean useVarCheck			;							// 8.0.0.0 (2021/09/30) JavaScript変数に使用できるかどうか[true/false]指定します
	private boolean useZeroDataOmit		;							// 6.7.7.0 (2017/03/31) ﾃﾞｰﾀが０の場合、使用しない（除外する）かどうか
	private boolean useRenderer			;							// 6.7.9.0 (2017/04/28) useRenderer 追加
	private String	sortColumn			;							// 6.8.0.0 (2017/06/02) 検索結果をこのカラムでソートしなおします(初期値:null)。
//	private String	optChart			;							// 7.0.1.2 (2018/11/04) chartの属性に、TLDで未定義の属性を追加指定します。
	private String	optOptions			;							// 7.0.1.2 (2018/11/04) optionsの属性に、その他ｵﾌﾟｼｮﾝを追加指定します。
	private String	optPlugins			;							// 8.0.0.0 (2021/09/30) options:pluginsの属性に、その他ｵﾌﾟｼｮﾝを追加します
	private String	optTooltip			;							// 8.0.0.0 (2021/09/30) options:plugins:tooltip の属性に、その他ｵﾌﾟｼｮﾝを追加します
	private String	optLegend			;							// 8.0.0.0 (2021/09/30) options:plugins:legend の属性に、その他ｵﾌﾟｼｮﾝを追加します

//	private List<String> options = new ArrayList<>() ;				// 8.0.0.0 (2021/08/31) optionsの属性に、ｵﾌﾟｼｮﾝを追加設定します。

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.9.7.0 (2018/05/14) PMD Each class should declare at least one constructor
	 */
	public JsChartV3Tag() { super(); }		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 6.7.5.0 (2017/03/10) jsChartData属性の初期化もれ
	 * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02	ﾁｬｰﾄｻｲｽﾞ・max・minの動的変更対応
	 * @og.rev 6.7.7.0 (2017/03/31) useZeroDataOmit属性の追加
	 * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
	 * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
	 * @og.rev 6.8.3.0 (2017/11/27) useEqValOmit属性の追加
	 * @og.rev 6.8.5.0 (2018/01/09) xbeginAtZero,ybeginAtZero,markValues,markColors,markLbls,markAdjust,rangeMin,rangeMax,usePointStyle属性の追加
	 * @og.rev 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) ﾘﾆｱ対応,time 属性復活
	 * @og.rev 6.9.9.4 (2018/10/01) 7.0.1.0 (2018/10/15) time 属性修正、tooltipFormat属性の追加
	 * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
	 * @og.rev 7.0.1.1 (2018/10/22) ylabelColor,y2label,y2labelColor属性の追加
	 * @og.rev 7.0.1.2 (2018/11/04) ylabelColor,y2label,y2labelColor属性の追加
	 * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
	 */
	@Override
	protected void release2() {
		super.release2();
		jsChartData.clear();			// 6.7.5.0 (2017/03/10)
		jsXAxis				= new JsChartDataV3();				// xAxes の設定用(datasetは使いません)

		chartBody			= null;		// 7.0.1.1 (2018/10/22) ﾁｬｰﾄタグのBODY部分に書かれた文字列
		chartType			= null;
		id					= null;
		height				= "400px";
		width				= "400px";
		labelColumn			= null;
		indexAxis			= null;		// 8.0.0.0 (2021/08/31)
		title				= null;
		titlePosition		= "top";
		legendPosition		= null;
		legendDisplay		= null;
		usePointStyle		= false;	// 6.8.5.0 (2018/01/09) 点のスタイル属性を使用するかどうか
		useLegend			= false;	// 7.0.1.1 (2018/10/22) Legend関連属性(legendPosition,legendDisplay,usePointStyle) のどれかがセットされれば、true
		barWidthPer			= "0.8";
		animation			= null;		// 8.0.0.0 (2021/08/31) 簡易的なアニメーションのON/OFF
		onClick				= null;
		plugins				= null;		// 6.9.9.2 (2018/09/18) プラグイン定義された関数を指定します。
		xscaleType			= TYPE_CATEGORY;
		xposition			= null;		// 7.0.1.2 (2018/11/04) x軸の表示位置[top/right/bottom/left]
		valueQuot			= false;	// 7.0.1.1 (2018/10/22) 値の前後にクオートをはさむかどうか[true/false]指定します。
		tableId				= HybsSystem.TBL_MDL_KEY;
		markValues			= null;		// 6.8.5.0 (2018/01/09) y軸に横マーカーラインの設定値をCSV形式で複数指定します
		markColors			= null;		// 6.8.5.0 (2018/01/09) y軸に横マーカーラインの色をCSV形式で複数指定します
		markLbls			= null;		// 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベルをCSV形式で複数指定します(未指定時はラベルを表示しません)
		markAdjust			= null;		// 6.8.5.0 (2018/01/09) y軸に横マーカーラインのラベル表示位置の上下方向を調整します(初期値:-6)。
		xmarkLbls			= null;		// 8.0.0.0 (2021/09/30) x軸に横マーカーラインのラベルをCSV形式で複数指定
		xmarkValues			= null;		// 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの設定値をCSV形式で複数指定します
		xmarkColors			= null;		// 7.0.1.1 (2018/10/22) x軸に縦マーカーラインの色をCSV形式で複数指定します
		markWidth			= "2";		// 7.0.1.1 (2018/10/22) マーカーライン共通のラインの幅を指定します:borderWidth(初期値:2)
		markDash			= null;		// 7.0.1.1 (2018/10/22) マーカーライン共通のラインに点線を指定([5,2]など)します:borderDash(初期値:null)
		markFontSize  		= "10";		// 7.0.1.1 (2018/10/22) マーカーライン共通のラベルのフォントサイズを指定します:fontSize(初期値:10)
		useZoom				= false;	// 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか(初期値:false)
		useDragZoom			= false;	// 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか(初期値:false)
		varColumns  		= null;		// 7.0.1.2 (2018/11/04) TableModelの指定のカラムをconstの配列変数として出力します。
//		useVarCheck			= false;	// 8.0.0.0 (2021/09/30) JavaScript変数に使用できるかどうか[true/false]指定します
		useZeroDataOmit		= false;	// 6.7.7.0 (2017/03/31) ﾃﾞｰﾀが０の場合、使用しない（除外する）かどうか
		useRenderer			= false;	// 6.7.9.0 (2017/04/28) useRenderer 追加
		sortColumn			= null;		// 6.8.0.0 (2017/06/02) 検索結果をこのカラムでソートしなおします(初期値:null)。
//		optChart			= null;		// 7.0.1.2 (2018/11/04) chartの属性に、TLDで未定義の属性を追加指定します。
		optOptions			= null;		// 7.0.1.2 (2018/11/04) optionsの属性に、その他ｵﾌﾟｼｮﾝを追加指定します。
		optPlugins			= null;		// 8.0.0.0 (2021/09/30) options:pluginsの属性に、その他ｵﾌﾟｼｮﾝを追加します
		optTooltip			= null;		// 8.0.0.0 (2021/09/30) options:plugins:tooltip の属性に、その他ｵﾌﾟｼｮﾝを追加します
		optLegend			= null;		// 8.0.0.0 (2021/09/30) options:plugins:legend の属性に、その他ｵﾌﾟｼｮﾝを追加します
	}

	/**
	 * Taglibの開始タグが見つかった時に処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 6.7.5.0 (2017/03/10) タグの使用を決める共通属性の追加
	 *
	 * @return 後続処理の指示
	 */
	@Override
	public int doStartTag() {
		if( !useTag() ) { return SKIP_BODY ; }		// 6.7.5.0 (2017/03/10)

		return EVAL_BODY_BUFFERED; // Bodyを評価する
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) このスクリプトの中に入れたい文字があれば、登録できるようにします。
	 *
	 * @return	後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doAfterBody() {
		chartBody = getBodyString();

		if( chartBody != null ) {
			chartBody = chartBody.trim();
		}

		return SKIP_BODY ;
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 6.7.5.0 (2017/03/10) タグの使用を決める共通属性の追加
	 * @og.rev 6.9.9.4 (2018/10/01) idの振り方、データの持ち方変更
	 * @og.rev 8.0.0.0 (2021/08/31) ｴﾗｰﾒｯｾｰｼﾞを画面に返します。
	 *
	 * @return 後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();
		if( !useTag() ) { return EVAL_PAGE ; }			// 6.7.5.0 (2017/03/10)

		id = (id==null ? tableId : id );				// 6.9.9.4 (2018/10/01) id指定なしの場合はtableId

		// jsChart出力
		jspPrint( jsChartOutput() );

		// 8.0.0.0 (2021/08/31) ｴﾗｰﾒｯｾｰｼﾞを画面に表示する。
		final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE );
		final String axisErr = jsXAxis.getErrorMessage();
		if( !axisErr.isEmpty() ) {
			errBuf.append( "X軸の設定でエラーがあります" ).append( CR )
					.append( axisErr ).append( CR );
		}

		// jsChartDataﾀｸﾞの変数宣言
		for( int i=0; i<jsChartData.size(); i++ ) {
			final String dataErr = jsChartData.get(i).getErrorMessage();
			if( !dataErr.isEmpty() ) {
				errBuf.append( "Y軸[" ).append( i ) .append( "]の設定でエラーがあります" ).append( CR )
						.append( dataErr ).append( CR );
			}
		}

		if( errBuf.length() > 0 ) {				// 一応、設定されているかどうか確認する。
			errBuf.insert( 0,"<pre>" ).append( "</pre>" );
			jspPrint( errBuf.toString() );
		}

		return EVAL_PAGE;
	}

	/**
	 * jsChart出力用
	 * jsChartTag と jsChartData を使用して、jsChart情報を出力します。
	 *
	 * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02	ﾁｬｰﾄｻｲｽﾞ・max・minの動的変更対応
	 * @og.rev 6.7.7.0 (2017/03/31) ﾁｬｰﾄﾃﾞｰﾀで、ｾﾞﾛ、null カラムを非表示にします。
	 * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
	 * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
	 * @og.rev 6.8.3.0 (2017/11/27) useZeroDataOmit属性で、nullOmit属性もセットします。
	 * @og.rev 6.8.3.0 (2017/11/27) useEqValOmit属性の追加
	 * @og.rev 6.8.3.1 (2017/12/01) 不要なデータを出力しないようにします。
	 * @og.rev 5.9.27.0 2017/12/01	T.OTA 61200-170831-04	max,minの小数点対応
	 * @og.rev 6.8.5.0 (2018/01/09) xbeginAtZero,ybeginAtZero,markValues,markColors,markLbls,markAdjust,rangeMin,rangeMax,usePointStyle属性の追加
	 * @og.rev 6.9.9.2 (2018/09/18) chart.jsが2.4.0から2.7.2にバージョンアップにより、廃止された属性対応
	 * @og.rev 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) ﾘﾆｱ対応,time 属性復活
	 * @og.rev 6.9.9.4 (2018/10/01) idの振り方、データの持ち方変更
	 * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
	 * @og.rev 7.0.1.3 (2018/11/12) バッファキー検索処理追加、markColors,xmarkColors属性に、VIVID,PASTELカラー指定に対応します。
	 * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
	 * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
	 *
	 * @return jsChert用文字列
	 */
	private String jsChartOutput() {
		// 各JavaScriptの変数名
		final String cd			= "cd_" + id;		//chartData
		final String myChart	= "chart_"+id;

		// JSON形式でﾃｰﾌﾞﾙ情報を取得
		// ﾃｰﾌﾞﾙ情報の取得
		// 6.8.0.0 (2017/06/02) sortColumn 追加
		DBTableModel table = (DBTableModel)getObject( tableId ) ;
		if( StringUtil.isNotNull( sortColumn ) ) {						// 6.8.5.0 (2018/01/09)
			final int clmNo = table.getColumnNo( sortColumn );			// エラーを出す。

			final DBTableModelSorter temp = new DBTableModelSorter();
			temp.setModel( (DBTableModel)getObject( tableId ) );
			temp.sortByColumn( clmNo,true );							// 順方向のソート
			table = temp;
		}

		final int rowCount = table.getRowCount();						// 6.9.2.0 (2018/03/05)

		// 7.0.1.3 (2018/11/12) DBTableModelに存在しないカラムのChartDataは無視します。
		// これは、動的にグラフを生成する場合に、カラムの増減に合わせて、JsChartDataV3Tagを生成しなおすのが手間だからです。
		final Iterator<JsChartDataV3> itr = jsChartData.iterator();		// 個々のグラフ
		while( itr.hasNext() ) {
			final JsChartDataV3 jcData = itr.next();
			final String chtClm = jcData.getChartColumn();
			final int    clmNo  = table.getColumnNo( chtClm );	// エラーを出す。

			if( clmNo < 0 ) {
				itr.remove();											// 7.0.1.3 (2018/11/12) カラムがDBTableModelに存在しない。
			}
			else if( useZeroDataOmit ) {	// ｾﾞﾛﾃﾞｰﾀを使用しない設定
				// 6.8.3.1 (2017/12/01) ループ処理の判定は、ChartColumn のみでよい。
				boolean isRemove = true;
				for( int row=0; row<rowCount; row++ ) {
					final String val = table.getValue( row,clmNo );
					if( StringUtil.isNotNull( val ) && !"0".equals( val ) && !"0.0".equals( val ) && !"0.00".equals( val )  ) {	// 6.8.5.0 (2018/01/09)
						isRemove = false;
						break;		// 判定処理打ち切り
					}
				}

				if( isRemove ) {
					itr.remove();										// すべてが、ｾﾞﾛ、null カラムを、削除します。
				}
			}
		}

		// 6.8.3.1 (2017/12/01) 不要なデータを出力しないようにします。
		final int clmSize = jsChartData.size();								// JsChartV3Tag の 値部分のみの配列

		final String[] clmNms = new String[clmSize];						// 6.9.9.4 (2018/10/01) カラム名の配列
		final int[]    clmNos = new int[clmSize];
		final int      lblNos = table.getColumnNo( labelColumn );			// エラーを出す
		final DBColumn dbClm  = table.getDBColumn( lblNos );				// 6.9.2.0 (2018/03/05)

		// jsChartDataﾀｸﾞの変数宣言
		for( int j=0; j<clmSize; j++ ) {
			final String chtClm = jsChartData.get(j).getChartColumn();
//			clmNms[j] = chtClm;													// 6.9.9.4 (2018/10/01) カラム名の配列 8.0.0.0 (2021/09/30) Delete
			clmNos[j] = table.getColumnNo( chtClm );							// エラーを出す

			final String clmRnm = "CLM" + j;									// 8.0.0.0 (2021/09/30) JavaScript変数名対応
			jsChartData.get(j).setChartColumn(clmRnm);
			clmNms[j] = clmRnm;
		}

		//	8.0.0.0 (2021/08/31) chartJs V3 以降は、timeもrealtimeも表示するようになった…らしい
		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE )
			.append( IE_CHECK )													// IE 警告
			.append( "<canvas class=\""	).append( CANVAS_NAME )					// canvasﾀｸﾞの設定
			.append( "\" id=\""			).append( id		)
			.append( "\" width=\""		).append( width		)
			.append( "\" height=\""		).append( height	)
			.append( "\"><!-- --></canvas>" ).append( CR	)
			.append( "<script>{" ).append( CR )									// 8.0.0.0 (2021/08/31) スコープ限定の '{' を追加
			.append( chartBody );												// 7.0.1.1 (2018/10/22) BODY部分の文字列の組み込み

		final boolean isXcateType  = TYPE_CATEGORY.equals(	xscaleType );		// 6.9.9.4 (2018/10/01)
		final boolean isXlinerType = TYPE_LINEAR.equals(	xscaleType );		// 6.8.5.0 (2018/01/09) xscaleType が linear かどうか。
		final boolean isXtimeType  = TYPE_TIME.equals(		xscaleType );		// 6.8.5.0 (2018/01/09) xscaleType が time かどうか。

		// 7.0.1.3 (2018/11/12) const 変数に設定する配列情報を、bufに追加します。
		final DBTableModel fcTable = table;			// ラムダ式で使えるのは、final宣言された変数のみ。根本は、Sorterを組み込んでfinalすべき。
		final IntFunction<String> lcFunc = (row) -> {
				final String lval = fcTable.getValue( row,lblNos );
				return useRenderer && !isXlinerType
							? StringUtil.jsonFilter( dbClm.getRendererValue(row,lval) ) : lval ;
		};
		setVarArray( rtn,labelColumn,rowCount,isXcateType || isXtimeType || useRenderer,lcFunc );

		// 6.9.9.4 (2018/10/01) データ部の出力
		for( int j=0; j<clmSize; j++ ) {
			final int clmNo = clmNos[j];		// finalしか参照できないため。
			setVarArray( rtn,clmNms[j],rowCount,valueQuot,(row) -> fcTable.getValue( row,clmNo ) );
		}

		// x軸がlinearｽｹｰﾙの場合
		// [{x:値1,y:値2},{x:値1,y:値2},･･･] 形式のデータが必要
		if( isXlinerType ) {
			for( int j=0; j<clmSize; j++ ) {
				final String chtClm = clmNms[j];
				rtn.append( "const LI_" ).append( chtClm ).append( "=[];" ).append( CR );

				// 6.9.9.4 (2018/10/01) x軸がlinearｽｹｰﾙの場合、カラム名が、変わるので、再設定している。(超特殊処理)
				jsChartData.get(j).setChartColumn( "LI_" + chtClm );
			}

			rtn.append( "for(var i=0; i<").append( labelColumn ).append( ".length; i++){" );
			for( int j=0; j<clmSize; j++ ) {
				final String chtClm = clmNms[j];
					// {x:ﾗﾍﾞﾙ, y:値}の形式で値を設定
				rtn.append( "LI_" ).append( chtClm ).append( "[i]={x:" ).append( labelColumn )
					.append( "[i],y:" ).append( chtClm ).append( "[i]};" );
			}
			rtn.append( "};" ).append( CR );
		}

		// 7.0.1.2 (2018/11/04) varColumns 追加
		final String[] varClms  = StringUtil.csv2Array( varColumns );	// 独自に出力しておきたいカラム列の値
		for( int j=0; j<varClms.length; j++ ) {
			final int varNos = table.getColumnNo( varClms[j] );	// エラーを出す
			final boolean isNumType = table.getDBColumn( varNos ).isNumberType();			// 6.4.6.0 (2016/05/27)

			setVarArray( rtn,varClms[j],rowCount,!isNumType,(row) -> fcTable.getValue( row,varNos ) );
		}

		// 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
		// chartType が BUBBLE の場合、chtClmが x:、varColumns の最初が、y: 次が r: になる。
		// SCATTERの場合は、r: がないだけ。
		if( CTYPE_BUBBLE.equals( chartType ) || CTYPE_SCATTER.equals( chartType ) ) {
			if( CTYPE_BUBBLE.equals( chartType ) && varClms.length < 2 ||
				CTYPE_SCATTER.equals( chartType ) && varClms.length < 1 ) {
					final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
						.append( "chartTypeが、" ).append( chartType )
						.append( "の場合は、varColumns で、y: データ、r:データを指定してください。" );
					throw new HybsSystemException( errMsg.toString() );
			}

			final String chtClm = clmNms[0];		// chartDataの1個目決め打ち
			rtn.append( "const LI_" ).append( chtClm ).append( "=[];" ).append( CR );

			// x軸が[{x: , y: , r: }…} のカラム名が変わるので、再設定している。(超特殊処理)
			jsChartData.get(0).setChartColumn( "LI_" + chtClm );

			rtn.append( "for(var i=0; i<").append( chtClm ).append( ".length; i++){" )
				.append( "LI_" ).append( chtClm ).append( "[i]={x:" ).append( chtClm )
				.append( "[i],y:" ).append( varClms[0] );

			// 切れ切れで分かりにくいかもしれないが、BUBBLEのみ、r: を出す。
			if( CTYPE_BUBBLE.equals( chartType ) ) {
				rtn.append( "[i],r:" ).append( varClms[1] );
			}

			rtn.append( "[i]};}" ).append( CR );
		}

		// ==================================================================================
		// 7.0.1.1 (2018/10/22) jsChartData(X軸)の設定
		if( !SET_CI_TYPE.contains( chartType ) ) {
			jsXAxis.setId( "x0" );						// X軸のid
			jsXAxis.setUseTime( isXtimeType );			// x軸の時間表示を使用するかどうか

			// 7.0.1.3 (2018/11/12) バッファキー検索処理追加
			if( isXtimeType && !jsXAxis.contains( JsChartDataV3.TIME , "displayFormats" ) ) {		// ｷｰﾜｰﾄﾞが無ければ追加
				// ほんとはリソースに入れるべきでしょう。
				if( "ja".equalsIgnoreCase( getLanguage() ) ) {						// 'ja' なら日本
					jsXAxis.addTime( "displayFormats" , TIME_FORMAT_JA , NO_QUOTE );	// 標準ﾀｲﾑﾌｫｰﾏｯﾄ適用。ｵﾌﾞｼﾞｪｸﾄなので、クオートなし
				}
				else {
					jsXAxis.addTime( "displayFormats" , TIME_FORMAT , NO_QUOTE );		// 標準ﾀｲﾑﾌｫｰﾏｯﾄ適用。ｵﾌﾞｼﾞｪｸﾄなので、クオートなし
				}
			}

			// x軸にﾘﾆｱｽｹｰﾙを設定した場合(これは残す)
			final String xpos = xposition != null ? xposition
												  : isXlinerType ? "bottom"
																 : null ;	// horizontalBar 廃止
			jsXAxis.addAxis( "position" , xpos , USE_QUOTE );	// 文字

			rtn.append( jsXAxis.getAxis() ).append( CR );
		}

		// ==================================================================================
		// jsChartData(Y軸)の設定
		// 7.0.1.1 (2018/10/22) data:dataset と、options:scales:yAxes: を変数化して出力します。
		for( final JsChartDataV3 chData : jsChartData ) {
			rtn.append(  chData.getDataset( 'y' )	).append( CR )		// 横棒線の場合は、'x'が、それ以外は、'y'
				.append( chData.getAxis()			).append( CR );
		}

		rtn.append( "const ").append( cd ).append( "={labels:" ).append( labelColumn ).append( ",datasets:[" );
		for( final JsChartDataV3 chData : jsChartData ) {
			rtn.append( chData.getDatasetKey() ).append( ',' );
		}
		rtn.append( "]};" ).append( CR )
			// jsChartの生成(グローバル変数定義の var)
			.append( "var " ).append( myChart ).append( "=new Chart(" ).append( id )
			.append( ",{" )
			.append( CR_TAB[1] ).append( "type:'" ).append( chartType ).append( "'," )
			.append( CR_TAB[1] ).append( "data:"  ).append( cd ).append( ',' );

		// 6.9.9.2 (2018/09/18) plugins,chartAttributes属性の追加
		setProp( rtn, CR_TAB[1],"plugins:["  , plugins   , "]," );

		rtn.append( CR_TAB[1] ).append( "options:{responsive:false," );			// ﾚｽﾎﾟﾝｼﾌﾞ OFF

		// 8.0.0.0 (2021/08/31)
		setProp( rtn, CR_TAB[2],"indexAxis:'"  , indexAxis   , "'," );		// "y" を指定することで、horizontalBar や verticalLine を実現
		setProp( rtn, CR_TAB[2],"categoryPercentage:" , barWidthPer , ","  );	// 棒線の横幅
		setProp( rtn, CR_TAB[2],"animation:" , animation , ","  );			// 簡易的なアニメーションのON/OFFを設定

		// ｸﾘｯｸｲﾍﾞﾝﾄの設定
		// clickLink 変数を使用する場合、内部でﾏｽﾀﾃﾞｰﾀを使用します。ｷｰとして、渡しておく必要があります。
		setProp( rtn, CR_TAB[2],"onClick:function(event,obj){",CR_TAB[3], onClick,CR_TAB[2],"}," );

		// 8.0.0.0 (2021/08/31) options:plugins:
		rtn.append( CR_TAB[2] ).append( "plugins:{" );

		setProp( rtn, CR_TAB[3], optPlugins , "," );				// 8.0.0.0 (2021/09/30) 属性はマージされる
		setProp( rtn, CR_TAB[3],"tooltip:{" , optTooltip , "}," );	// 8.0.0.0 (2021/09/30)

		// ﾀｲﾄﾙ属性の設定(ﾀｲﾄﾙ要素も処理できるように変更))
		if( title != null && title.length() > 0 ) {
			if( title.charAt(0) == '{' ) {
				rtn.append( CR_TAB[3] ).append( "title:" ).append( title ).append( ',' );
			}
			else if( title.charAt(0) == '[' ) {
				// タイトルに配列を渡すと、改行表示する。
				setProp( rtn, CR_TAB[3],"title:{display:true,text:",title,",position:'", titlePosition, "',}," );
			}
			else {
				// タイトルを文字列として処理する。
				setProp( rtn, CR_TAB[3],"title:{display:true,text:'",title,"',position:'", titlePosition, "',}," );
			}
		}

		// 凡例属性の設定(
		if( useLegend ) {											// 7.0.1.1 (2018/10/22)
			rtn.append( CR_TAB[3] ).append( "legend:{" );
			setProp( rtn, optLegend  , ","  );						// 8.0.0.0 (2021/09/30) 属性はマージされる
			setProp( rtn, "display:"   , legendDisplay  , ","  );
			setProp( rtn, "position:'" , legendPosition , "'," );

			// 凡例のスタイルを、pointStyle にあわせるかどうか
			if( usePointStyle ) {									// 7.0.1.1 (2018/10/22)
				rtn.append( "labels:{usePointStyle:true}," );
			}
			rtn.append( "}," );
		}

		// 8.0.0.0 (2021/08/31) zoom は、文法も変わり、options:plugins: 以下の属性になった。
		// 6.8.5.0 (2018/01/09) ズーム処理を使用するかどうか
		if( useZoom ) {		// useZoom を優先する。
			rtn.append( CR_TAB[3] ).append( WHEEL_ZOOM );
		}
		else if( useDragZoom ) {
			rtn.append( CR_TAB[3] ).append( DRAG_ZOOM );
		}

		// 8.0.0.0 (2021/08/31) annotation は、options:plugins: 以下の属性になった。
		final String[] mkVals  = StringUtil.csv2Array( markValues );	// y軸の値で、横のﾏｰｶｰ
		final String[] xmkVals = StringUtil.csv2Array( xmarkValues );	// x軸の値で、縦のﾏｰｶｰ
		final int vCnt = mkVals.length;
		final int xCnt = xmkVals.length;
		if( vCnt > 0 || xCnt > 0 ) {
			rtn.append( CR_TAB[3] ).append( "annotation:{annotations:{" );	// 8.0.0.0 (2021/08/31) 配列からｵﾌﾞｼﾞｪｸﾄへ

			// 従来の markValues,markColors,markLbls,markAdjust 属性対応
			if( vCnt > 0 ) {
				final String[] mkLbls = StringUtil.csv2Array( markLbls		, ',' , vCnt );
				final String[] mkAjst = StringUtil.csv2Array( markAdjust	, ',' , vCnt , MARK_DEF_ADJUST );
				final String[] mkCols = colorCsv( markColors ,  vCnt );							// 7.0.1.3 (2018/11/12)

				// 7.0.1.1 (2018/10/22) 'y-axis-0' → 'y0Ax' これは、JsChartDataV3#getAxisKey() で取得できる値だが、決め打ち
				for( int i=0; i<vCnt; i++ ) {
					rtn.append( CR_TAB[4] ).append( "yline" ).append(i).append( ":{" )	// V3で、名前付きになった。
						.append( CR_TAB[5] ).append( "type:'line'," );
					setProp( rtn, "borderWidth:"		, markWidth	, ","	);
					setProp( rtn, "borderDash:"			, markDash	, ","	);
					setProp( rtn, "borderColor:'"		, mkCols[i] , "',"	);
					setProp( rtn, CR_TAB[5],"yMin:"		, mkVals[i]	, ","	);			// V3 → V2 で、valueから、yMin,yMax に変更
					setProp( rtn, 			"yMax:"		, mkVals[i]	, ","	);
					if( !mkLbls[i].isEmpty() ) {
						rtn.append( CR_TAB[5] ).append( "label:{" )
							.append( CR_TAB[6] )
							.append( "enabled:'true',position:'start',backgroundColor:'rgba(0,0,0,0)'," )	// position:left → start に変更
							.append( CR_TAB[6] );
						setProp( rtn, "content:'"		, mkLbls[i] , "'," );
						setProp( rtn, "color:'"			, mkCols[i] , "'," );
						setProp( rtn, "yAdjust:"		, mkAjst[i]	, ","	);
						setProp( rtn, CR_TAB[6],"font:{size:" , markFontSize , "},"	);	// fontSize:XX → font:{size:XX} に変更
						rtn.append( CR_TAB[5] ).append( "}," );		// label:{
					}
					rtn.append( CR_TAB[4] ).append( "}," );		// type:
				}
			}

			// 7.0.1.1 (2018/10/22) xmarkValues,markLbls,xmarkColors属性対応
			if( xCnt > 0 ) {
				final String[] xmkLbls = StringUtil.csv2Array( xmarkLbls	, ',' , xCnt );	// 8.0.0.0 (2021/09/30)
				final String[] xmkCols = colorCsv( xmarkColors ,  xCnt );			// 7.0.1.3 (2018/11/12)

				// 7.0.1.1 (2018/10/22) 'x-axis-0' → 'x0Ax' これは、JsChartDataV3#getAxisKey() で取得できる値だが、決め打ち
				for( int i=0; i<xCnt; i++ ) {
					rtn.append( CR_TAB[4] ).append( "xline" ).append(i).append( ":{" )
						.append( CR_TAB[5] ).append( "type:'line'," );				// V3で、名前付きになった。
					setProp( rtn, "borderWidth:"		, markWidth	, ","	);
					setProp( rtn, "borderDash:"			, markDash	, ","	);
					setProp( rtn, "borderColor:'"		, xmkCols[i] , "'," );
					setProp( rtn, CR_TAB[5],"xMin:'"	, xmkVals[i] , "',"	);		// V3 → V2 で、valueから、xMin,xMax に変更
					setProp( rtn, 			"xMax:'"	, xmkVals[i] , "',"	);		//カテゴリで文字列のケース有り
					if( !xmkLbls[i].isEmpty() ) {									// 8.0.0.0 (2021/09/30)
						rtn.append( CR_TAB[5] ).append( "label:{" )
							.append( CR_TAB[6] )
							.append( "enabled:'true',position:'end',backgroundColor:'white'," )	// position:left → start に変更
							.append( CR_TAB[6] );
						setProp( rtn, "content:'"		, xmkLbls[i] , "'," );
						setProp( rtn, "color:'"			, xmkCols[i] , "'," );
						setProp( rtn, CR_TAB[6],"font:{size:" , markFontSize , "},"	);	// fontSize:XX → font:{size:XX} に変更
						rtn.append( CR_TAB[5] ).append( "}," );		// label:{
					}
					rtn.append( CR_TAB[4] ).append( "}," );		// type:
				}
			}
			rtn.append( CR_TAB[3] ).append( "}}," );		// annotation:{annotations:{
		}
		rtn.append( CR_TAB[2] ).append( "}," );		// plugins:{

		// 6.9.9.2 (2018/09/18) chart.jsが2.4.0から2.7.2にバージョンアップにより、廃止された属性対応
		if( !SET_CI_TYPE.contains( chartType ) ) {
			// 円形以外の場合はscales属性に設定
			rtn.append( CR_TAB[2] ).append( "scales:{x:" )
				.append( jsXAxis.getAxisKey() ).append( ',' );

			// 7.0.1.1 (2018/10/22) options:scales:yAxes: を変数化して出力しているので、その設定のみでよい。
			// 最初の一つだけ、"y:" を付ける(何か方法があるはず)。
			boolean isFirst = true;
			for( final JsChartDataV3 chData : jsChartData ) {
				if( chData.isUseAxis() ) {
					if( isFirst ) { rtn.append( "y:" ); isFirst=false; }
					rtn.append( chData.getAxisKey() ).append( ',' );
				}
			}

			rtn.append( "}," );		// 7.0.1.1 (2018/10/22)
		}

		setProp( rtn, CR_TAB[2] , optOptions , "," );		// 7.0.1.2 (2018/11/04)
		rtn.append( CR_TAB[1] ).append( "}," );

		rtn.append( CR_TAB[0] ).append( "});" ).append( CR );

		// 8.0.0.0 (2021/08/31) zoom を使った場合は、ダブルクリックで元に戻す処理を入れておく
		if( useZoom || useDragZoom ) {
			rtn.append( "const cv_" ).append( id ).append( "=document.getElementById('" )
				.append( id ).append( "');" ).append( CR )
				.append( "cv_" ).append( id ).append( ".addEventListener( 'dblclick',function(){" )
				.append( myChart )								// Chart オブジェクト
				.append( ".resetZoom();});" ).append( CR );
		}

		rtn.append( "}</script>" );	// 8.0.0.0 (2021/08/31) スコープ限定の '}' を追加

		return rtn.toString();
	}

	/**
	 * s引数のすべての文字列が null か、長さゼロ文字列でない場合は、連結した結果を返します。
	 *
	 * @param buf	ベースとなるStringBuilder
	 * @param str	連結対象の文字列群(可変長引数)
	 */
	private void setProp( final StringBuilder buf, final String... strs ) {
		if( !StringUtil.isEmpty( strs ) ) {		// null か、長さゼロ文字列が、一つもない場合
			for( final String str : strs ) {
				buf.append( str );
			}
		}
	}

	/**
	 * const 変数に設定する配列情報を、bufに追加します。
	 *
	 * const 変数名が key で、cnt分の繰返しで、IntFunction を呼びます。
	 * isQuote=trueの場合は、前後にクォーテーションをつけます。
	 *
	 * @og.rev 7.0.1.3 (2018/11/12) const 変数に設定する配列情報を、bufに追加します。
	 *
	 * @param buf	ベースとなるStringBuilder
	 * @param key	キー
	 * @param cnt	ループする個数(通常は行数：rowCount)
	 * @param isQuote	クォーテーションで括るかどうか [true:括る/false:括らない]
	 * @param func	数値を引数に取る関数型インタフェース
	 */
	private void setVarArray( final StringBuilder buf, final String key, final int cnt,
								final boolean isQuote, final IntFunction<String> func ) {
		buf.append( "const " ).append( key ).append( "=[" );
		for( int row=0; row<cnt; row++ ) {
			final String val = nval( func.apply( row ),"" );	// null 文字列が append されるのを避ける

			if( isQuote ) {
				buf.append( '"' ).append( val ).append( "\"," );
			}
			else {
				buf.append( val ).append( ',' );
			}
		}
		buf.append( "];" ).append( CR );
	}

	/**
	 * ﾊﾟﾗﾒｰﾀﾁｪｯｸ用ﾒｿｯﾄﾞ。
	 *
	 * @param trg		ターゲット
	 * @param set		使用可能なキーワードのSet
	 * @param trgStr	ターゲットの名称
	 */
	private void checkPara( final String trg, final Set<String> set, final String trgStr ) {
		if( StringUtil.isNotNull( trg ) && !check( trg, set ) ) {						// 6.8.5.0 (2018/01/09)
			final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
				.append( "指定の" ).append( trgStr ).append( "は指定できません。" ).append( CR )
				.append( trgStr ).append( "=[" ).append( trg ).append( ']' ).append( CR )
				.append( set );		// org.opengion.fukurou.util.ArraySet の toStringメソッド
			throw new HybsSystemException( errMsg.toString() );
		}
	}

//	/**
//	 * JavaScript変数ﾁｪｯｸ用ﾒｿｯﾄﾞ。
//	 *
//	 * 1文字目は数字と、特殊記号(アンダーバー(_)、ドル記号($)を除く)、をチェックします。
//	 * 厳密には、予約文字が使えなかったりするが、簡易ﾁｪｯｸとする。
//	 * 前後の空白文字は除外、それ以外の特殊記号は、アンダーバー(_)に変換します。
//	 *
//	 * @og.rev 8.0.0.0 (2021/09/30) JavaScriptの変数名ﾁｪｯｸと置換
//	 *
//	 * @param key		ﾁｪｯｸする変数
//	 * @param trgStr	変数置換後の変数
//	 */
//	private String checkPara( final String key ) {
//		if( !useVarCheck ) { return key; }				// useVarCheck が false の場合は、何もしない。
//
//		if( key == null || key.isEmpty() ) { return "_"; }
//
//		final StringBuilder buf = new StringBuilder(key.trim());
//		for( int i=0; i<buf.length(); i++ ) {
//			final char ch = buf.charAt(i);
//			if( i==0 && '0'<=ch && ch<='9'			||
//				' '<=ch && ch<='/' && '$'!=ch		||
//				':'<=ch && ch<='@'					||
//				'['<=ch && ch<='`' && '_'!=ch		||
//				'{'<=ch && ch<='~' ) { buf.setCharAt( i,'_' ); }
//		}
//
//		return buf.toString();
//	}

	/**
	 * 色コードの配列を返すメソッドです。
	 *
	 * これは、普通のCSV形式のﾃﾞｰﾀなら、そのまま分割します。
	 * 配列は、lenの数だけ作成します。
	 * nullやゼロ文字列の場合は、ColorMapのOLOR_KEYすべてを対象にします。
	 * 1色の場合も、すべて同じ色をlen の数だけセットします。
	 *
	 * VIVIDとPASTEL はｷｰﾜｰﾄﾞで、org.opengion.fukurou.util.ColorMap のビビッドカラーと
	 * パステルカラーの配列を指定したことと同じになります。
	 * また、色番号として、ビビッドを、(V0～V11) , パステルを、(P0～P11)
	 * に割当てていますので、配列に分解後一旦すべてのｷｰﾜｰﾄﾞを色番号検索に使用します。
	 *
	 * @og.rev 7.0.1.3 (2018/11/12) 色コードの配列を返すメソッド追加
	 *
	 * @param colCsv	色コードのCSV形式文字列
	 * @param len		作成する配列の個数
	 * @return	色コードに変換後の配列
	 */
	private String[] colorCsv( final String colCsv, final int len ) {
		// 色の数を、len にあわせる必要があります。
		final String[] mkCols = new String[len];

		// cols を元に、ColorMap から色配列を取得します。
		final String[] cols = ColorMap.getColorKeys( colCsv );

		// 色配列に順番に割り当てますが、色が足りない場合は、初期値の色をセットします。
		final int min = Math.min( mkCols.length , cols.length );
		for( int i=0; i<min; i++ ) {
			mkCols[i] = cols[i];
		}
		for( int i=min; i<mkCols.length; i++ ) {
			mkCols[i] = cols[0];					// 色コードの最初の色
		}

		return mkCols ;
	}

	/**
	 * jsChartData情報をﾘｽﾄに追加します。
	 *
	 * @og.rev 6.7.5.0 (2017/03/10) ﾘｽﾄの初期化方法を変更します。
	 *
	 * @param jsData jsChartData情報
	 */
	protected void addJsChartData( final JsChartDataV3 jsData ) {
		jsChartData.add( jsData );
	}

	/**
	 * 登録済みのjsChartData情報の個数を返します。
	 *
	 * @og.rev 6.7.7.0 (2017/03/31) 新規登録
	 *
	 * @return 登録済みのjsChartData情報の個数
	 */
	protected int getJsChartDataSize() {
		return jsChartData.size();
	}

	/**
	 * borderColorとbackgroundColorに色を１色しか使用できないかどうかを返します。
	 *
	 * chartType に応じて、色配列が使用できないタイプがあります。
	 *    line/radar が true  （１色しか使用できない）
	 *    それ以外（bar/horizontalBar/polarArea/pie/doughnut）が false （色配列が使用できる）
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 新規登録
	 *
	 * @return 登録済みのjsChartData情報の個数
	 */
	protected boolean isOneColor() {
		// line/radar が true  （１色しか使用できない）
		return CTYPE_LINE.equalsIgnoreCase( chartType ) || CTYPE_RADAR.equalsIgnoreCase( chartType );
	}

	// =================================================================================

	/**
	 * 【TAG】ﾁｬｰﾄの種類を指定します[line/bar/radar/polarArea/pie/doughnut/bubble/scatter](必須)。
	 *
	 * @og.tag
	 * コンフィグ属性の type 定義です。
	 * なお、複合グラフ時には、この値を、"bar" にしておかないと、きちんと表示しないようです。
	 *
	 * 8.0.0.0 (2021/08/31)
	 *  chartTypeが、bubbleとscatterの場合は、y:データ、r:データを varColumns で
	 *  指定します。詳細は、varColumns の説明をご確認ください。
	 *
	 *  horizontalBar 廃止 → indexAxis="y" 指定 (当面は互換性の関係で残しますが、廃止予定です)
	 *  verticalLine 相当の表示も indexAxis="y" 指定
	 *
	 * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
	 *
	 * @param cType ﾁｬｰﾄﾀｲﾌﾟ [line/bar/radar/polarArea/pie/doughnut/bubble/scatter]
	 */
	public void setChartType( final String cType ) {
		chartType = nval( getRequestParameter( cType ) , null );

		// 8.0.0.0 (2021/08/31) 互換性の関係で、少し残す。
		if( "horizontalBar".equalsIgnoreCase( chartType ) ) {
			indexAxis = "y";
			chartType = CTYPE_BAR ;
			final String errMsg = "chartTypeのhorizontalBarは廃止されました。代わりに、indexAxis='y'を指定してください。" ;
			System.err.println( errMsg );
			return ;
		}

		if( !check( chartType, CTYPE_SET ) ) {
			final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE )
				.append( "指定のチャートタイプは実行できません。"        ).append( CR )
				.append( "chartType=[" ).append( chartType ).append( ']' ).append( CR )
				.append( CTYPE_SET );	// org.opengion.fukurou.util.ArraySet の toStringメソッド
			throw new HybsSystemException( errMsg.toString() );
		}
	}

	/**
	 * 【TAG】ﾗﾍﾞﾙのｶﾗﾑ名を指定します(表示名称）(必須)。
	 *
	 * @og.tag
	 * 表示名称に使用するﾃﾞｰﾀﾍﾞｰｽの検索時のカラムを指定します。
	 *
	 * @param lblclm ﾗﾍﾞﾙｶﾗﾑ
	 */
	public void setLabelColumn( final String lblclm ) {
		labelColumn = nval( getRequestParameter( lblclm ),labelColumn );
	}

	/**
	 * 【TAG】canvasﾀｸﾞのidを指定します(初期値:hybscanvas)。
	 *
	 * @og.tag
	 * canvasﾀｸﾞのidに設定します。
	 *
	 * @param id canvasﾀｸﾞのid
	 */
	@Override
	public void setId( final String id ) {
		this.id = nval( getRequestParameter( id ),this.id );
	}

	/**
	 * 【TAG】ﾁｬｰﾄの高さを指定します(初期値:400px)。
	 *
	 * @og.tag
	 * canvasﾀｸﾞの高さに設定します。
	 *
	 * @param hei 設定する高さ
	 */
	public void setHeight( final String hei ) {
		height = nval( getRequestParameter( hei ),height );
	}

	/**
	 * 【TAG】ﾁｬｰﾄの幅を指定します(初期値:400px)。
	 *
	 * @og.tag
	 * canvasﾀｸﾞの横幅を設定します。
	 *
	 * @param wid 設定する横幅
	 */
	public void setWidth( final String wid ) {
		width = nval( getRequestParameter( wid ),width );
	}

	/**
	 * 【TAG】プラグイン定義された関数を指定します。
	 *
	 * @og.tag
	 * コンフィグ属性の type 定義です。
	 *
	 * プラグインは、plugins: [pinFunc], 形式で追加されます。
	 * この属性での指定時は、[]は、不要で、CSV形式の関数名を並べます。
	 * 外部に、const pinFunc = { afterDatasetsDraw: function(chart, options) { ･･･ } };
	 * 形式のプラグインを指定することで、個別に読ませることが可能です。
	 * なお、すべてのチャートに、同一のプラグインを指定する場合は、この属性ではなく、
	 * Chart.plugins.register({ afterDatasetsDraw: function(chart, options) { ･･･ } });
	 * 形式で、プラグイン登録
	 *
	 * ※ options:plugins: 属性とは異なります。
	 *
	 * @og.rev 6.9.9.2 (2018/09/18) プラグイン定義された関数を指定します。
	 *
	 * @param attri 追加属性の値
	 */
	public void setPlugins( final String attri ) {
		plugins = nval( getRequestParameter( attri ),plugins );
	}

	// =================================================================================

	/**
	 * 【TAG】"y" を指定することで、horizontalBar や verticalLine を実現する。
	 *
	 * @og.tag
	 * options: 以下の属性
	 *  horizontalBar が廃止され、同様の機能は、indexAxis="y" 指定で実現できます。
	 *  verticalLine 相当の表示も indexAxis="y" 指定で実現します。
	 *
	 * @og.rev 8.0.0.0 (2021/08/31) horizontalBar 廃止 → indexAxis="y" 指定
	 *
	 * @param indx 軸の方向('x','y')
	 */
	public void setIndexAxis( final String indx ) {
		indexAxis = nval( getRequestParameter( indx ),null );
	}

	/**
	 * 【TAG】棒線の横幅を指定します(初期値:0.8, typeがbarの場合に有効)。
	 *
	 * @og.tag
	 * options: 以下の属性
	 *  options:xAxes:categoryPercentage → option:categoryPercentage の 要素の属性です。
	 *
	 * ※ 階層変更による対応のため、chartType による属性の出力制御は廃止しました。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 *
	 * @param widthPer 棒線の横幅
	 */
	public void setBarWidthPer( final String widthPer ) {
		barWidthPer = nval( getRequestParameter( widthPer ),barWidthPer );
	}

	/**
	 * 【TAG】簡易的にアニメーションのON/OFFを設定(true/false)します(初期値::null=true)(options:animation)。
	 *
	 * @og.tag
	 * options: 以下の属性
	 *  options:animation の 要素の属性です。
	 *
	 * ※ 簡易的に、false を指定すると、アニメーションが OFF になります。
	 *    各種属性が登録できるように、文字列を自由に登録できます。
	 *
	 * @og.rev 8.0.0.0 (2021/08/31) optionAttributesで設定していた項目を属性追加
	 *
	 * @param flag アニメーションのON/OFFを設定(true/false)
	 */
	public void setAnimation( final String flag ) {
		animation = nval( getRequestParameter( flag ), animation );
	}

	/**
	 * 【TAG】ﾁｬｰﾄｸﾘｯｸ時のｲﾍﾞﾝﾄを指定します。
	 *
	 * @og.tag
	 * options: 以下の属性
	 * 下記の値が引数として渡されます。
	 * " onClick:function(event,obj){" +  onClick + '}'
	 * に変換されてセットされます。
	 *   event:ｲﾍﾞﾝﾄ情報
	 *   obj:ｸﾘｯｸされたｵﾌﾞｼﾞｪｸﾄの情報
	 *
	 * 例)
	 *   onClick="clickLink( event,obj,'result_sample2.jsp?command=RENEW&amp;CLM={CLM}&amp;VAL={VAL}&amp;IDX={IDX}' );"
	 *   onClick="updatechart(obj,'SubChart');"
	 *   onClick="clickLink( event, obj,'index.jsp?chartTitle={LBL}&amp;markValues={CLM}' , parent );"
	 *
	 * 基本的には、外部関数を呼び出す設定を行い、実際の動作は外部関数側で行います。
	 *
	 * @param click チャートクリック時のイベントを指定
	 */
	public void setOnClick( final String click ) {
		onClick = nval( getRequestParameter( click ),null );
	}

	// =================================================================================

	/**
	 * 【TAG】ﾀｲﾄﾙ、またはﾀｲﾄﾙ要素を指定します。
	 *
	 * @og.tag
	 * options:title:text → options:plugins:title:text の 要素の属性です。
	 * "タイトル" または "{display:true,text:'ﾀｲﾄﾙ',color:'blue',font:{size:15},}" 形式で指定します。
	 * options:plugins:titleの属性に、その他ｵﾌﾟｼｮﾝを追加するのと同じ動きになります。
	 * 判定方法は、先頭に 『{』が存在するかどうかです。
	 * タイトルに配列を渡すと、改行表示します。
	 * ['タイトル','改行','するのか？'] の形式なので、先頭に 『[』が存在するか判定します。
	 *
	 * <pre>
	 *   display:true/false,   初期値:false
	 *   text   :チャートタイトル(string |,string[])
	 *   color  :タイトルの色
	 *   font   :{ family:フォント,size:サイズ,style:スタイル,weight:太さ,lineHeight:1行の高さ }
	 *   padding:パディング
	 *   align  :表示位置。'start'(開始側), 'center'(中央), 'end'(終了側)のいずれか。デフォルトは 'center'
	 *   position:表示位置。'top'(上部), 'left'(左側), 'bottom'(下部), 'right'(右側)のいずれか。デフォルトは 'top'
	 *   fullSize:フルサイズで表示するか否か。デフォルトは true
	 *
	 * </pre>
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 8.0.0.0 (2021/09/30) タイトル要素も指定できるように変更
	 *
	 * @param title ﾀｲﾄﾙ
	 */
	public void setTitle( final String title ) {
		this.title = nval( getRequestParameter( title ),this.title );
	}

	/**
	 * 【TAG】ﾀｲﾄﾙの表示位置[top/right/bottom/left]を指定します(初期値:top)。
	 *
	 * @og.tag
	 *  options:title:position → options:plugins:title:position の 要素の属性です。
	 * title 属性に、ﾀｲﾄﾙ要素({…}書式)を設定した場合は、positionは無効です。
	 *
	 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#title">とほほ → チャートタイトル </a>
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 *
	 * @param position ﾀｲﾄﾙの表示位置 [top/right/bottom/left]
	 */
	public void setTitlePosition( final String position ) {
		titlePosition = nval( getRequestParameter( position ),titlePosition );

		checkPara( titlePosition, SET_POSITION, "titlePosition" );
	}

	/**
	 * 【TAG】凡例を表示するか[true/false]を指定します。
	 *
	 * @og.tag
	 * options:legend:display → options:plugins:legend:display の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 *
	 * @param display 凡例を表示するか [true/false]
	 */
	public void setLegendDisplay( final String display ) {
		legendDisplay = nval( getRequestParameter( display ),legendDisplay );

		if( legendDisplay != null ) {
			checkPara( legendDisplay, SET_BOOLEAN, "legendDisplay" );
			useLegend = true;
		}
	}

	/**
	 * 【TAG】凡例の表示位置[top/right/bottom/left]を指定します(初期値:top)。
	 *
	 * @og.tag
	 *  options:legend:position → options:plugins:legend:position の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 *
	 * @param position 凡例の表示位置 [top/right/bottom/left]
	 */
	public void setLegendPosition( final String position ) {
		legendPosition = nval( getRequestParameter( position ),legendPosition );

		if( legendPosition != null ) {
			checkPara( legendPosition, SET_POSITION, "legendPosition" );
			useLegend = true;
		}
	}

	/**
	 * 【TAG】凡例のスタイル属性を使用するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * 凡例のスタイルを、jsChartDataタグのpointStyle属性で指定した形状に変更します。
	 * 複数データの場合、片方だけ指定したい場合は、usePointStyle="true" にしておき、
	 * 指定したいほうだけ、jsChartDataタグ側で、pointStyle属性を設定してください。
	 * <del>options:legend:labels属性のusePointStyle です。</del>
	 * options:legend:labels:usePointStyle → options:plugins:legend:labels:usePointStyle の 要素の属性です。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param usePstyle 凡例のスタイル属性を使用するかどうか [true:使用する/false:使用しない]
	 */
	public void setUsePointStyle( final String usePstyle ) {
		final String useStyle = nval( getRequestParameter( usePstyle ),null );

		if( useStyle != null ) {
			usePointStyle = Boolean.parseBoolean( useStyle );
			useLegend = true;		// パラメータの設定が行われた場合のみ、設定します。
		}
	}

	//========================================================================================

	/**
	 * 【TAG】x軸のｽｹｰﾙﾀｲﾌﾟ[category/linear/time]を指定します(初期値:category)。
	 *
	 * @og.tag
	 *  8.0.0.0 (2021/08/31)
	 *  chartTypeが、bubbleとscatterの場合は、xscaleType は、初期値:category に
	 *  しておいてください。内部で、x: y: r: 等のﾃﾞｰﾀの割り当てを行います。
	 * options:scales:xAxes:type → options:scales:x:type の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xscaleType x軸のｽｹｰﾙﾀｲﾌﾟ [category/linear/time]
	 */
	public void setXscaleType( final String xscaleType ) {
		this.xscaleType = nval( getRequestParameter( xscaleType ) , this.xscaleType );

		// プラグインなどで独自の type を指定することがあるため、警告だけにします。
		try {
			checkPara( this.xscaleType, SET_XSCALE, "xscaleType" );
		}
		catch( final HybsSystemException ex ) {
			System.err.println( ex.getMessage() );
		}

		jsXAxis.addAxis( "type" , this.xscaleType , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】x軸の表示位置[top/right/bottom/left]を指定します(初期値:bottom)。
	 *
	 * @og.tag
	 * <del>horizontalBar を指定した場合は、left になります。</del>
	 * 8.0.0.0 (2021/08/31) horizontalBar は廃止
	 * 初期値(null)は、下(bottom)に表示されます。
	 * <del>options:scales:xAxes の 要素の属性です。</del>
	 * options:scales:xAxes:position → options:scales:x:position の 要素の属性です。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 新規登録
	 *
	 * @param pos x軸の表示位置 [top/right/bottom/left]
	 */
	public void setXposition( final String pos ) {
		xposition = nval( getRequestParameter( pos ),null );

		checkPara( xposition, SET_POSITION, "position" );
	}

	/**
	 * 【TAG】x軸の最大値を指定します(xscaleTypeがlinearの場合に有効)。
	 *
	 * @og.tag
	 *  options:scales:xAxes:ticks:max → options:scales:x:max の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xmax x軸の最大値
	 */
	public void setXmax( final String xmax ) {
		jsXAxis.addAxis( "max" , nval( getRequestParameter( xmax ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】x軸の最小値を指定します(xscaleTypeがlinearの場合に有効)。
	 *
	 * @og.tag
	 *  options:scales:xAxes:ticks:min → options:scales:x:min の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xmin x軸の最小値
	 */
	public void setXmin( final String xmin ) {
		jsXAxis.addAxis( "min" , nval( getRequestParameter( xmin ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】x軸のラベルを指定します。
	 *
	 * @og.tag
	 *  options:scales:xAxes:scaleLabel:labelString → options:scales:x:title:text の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xlabel x軸のラベル
	 */
	public void setXlabel( final String xlabel ) {
		final String lbl = nval( getRequestParameter( xlabel ),null );
		if( lbl != null ) {
			final String scLbl = "display:true,text:'" + lbl + "'" ;		// ラストの ',' は、addAxis 側で付ける。
			jsXAxis.addAxis( JsChartDataV3.TITLE , scLbl );
		}
	}

	/**
	 * 【TAG】x軸ｺｰﾙﾊﾞｯｸを指定します。
	 *
	 * @og.tag
	 * x軸のメモリ編集用スケールバックを設定します。
	 *  options:scales:xAxes:ticks:callback → options:scales:x:ticks:callback の 要素の属性です。
	 *  callback:function(value,index,[tick objects]) {
	 *    return '$' + value;
	 *  }
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param callback x軸ｺｰﾙﾊﾞｯｸ
	 */
	public void setXscaleCallback( final String callback ) {
		jsXAxis.addTicks( "callback" , nval( getRequestParameter( callback ),null ) , NO_QUOTE );	// ファンクションは、クオートしない
	}

	/**
	 * 【TAG】x軸を０から書き始まるかどうか(xscaleTypeがlinearの場合に有効)(初期値:null)。
	 *
	 * @og.tag
	 * options:scales:xAxes:ticks:beginAtZero → options:scales:x:beginAtZero の 要素の属性です。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xZero x軸のゼロ開始
	 */
	public void setXbeginAtZero( final String xZero ) {
		final String beginAtZero =  nval( getRequestParameter( xZero ),null );
		checkPara( beginAtZero, SET_BOOLEAN, "xbeginAtZero" );
		jsXAxis.addAxis( "beginAtZero" , beginAtZero , NO_QUOTE );		// 数値(boolean)
	}

	/**
	 * 【TAG】x軸のメモリ幅を指定します(xscaleTypeがlinearの場合に有効)。
	 *
	 * @og.tag
	 *  options:scales:xAxes:ticks:stepSize → options:scales:x:ticks:stepSize の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param xstepSize x軸のメモリ幅
	 */
	public void setXstepSize( final String xstepSize ) {
		jsXAxis.addTicks( "stepSize" , nval( getRequestParameter( xstepSize ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】optionsの属性に、その他ｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * optionsの属性に、その他ｵﾌﾟｼｮﾝを追加します。
	 * 指定する際の、前後の『{}』は、不要です。
	 *
	 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#options">とほほ → オプション </a>
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性名変更
	 *
	 * @param attri オプションの値
	 */
	public void setOptOptions( final String attri ) {
		optOptions = nval( getRequestParameter( attri ),null );
	}

	/**
	 * 【TAG】options:pluginsの要素に、その他ｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * options:pluginsの要素に、その他ｵﾌﾟｼｮﾝを追加します
	 * 指定する際の、前後の『{}』は、不要です。
	 * plugins には、legend(凡例),title(ﾀｲﾄﾙ),tooltip(ﾂｰﾙﾁｯﾌﾟ),decimation(間引き),filler(塗りつぶし)
	 * の属性を指定できるが、元々のこれらを単独で設定できる属性も持っており、
	 * データ的にはマージされますが、同じキーを指定した場合にどのような動きになるかは保証できません。
	 *
	 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#plugins">とほほ → プラグイン </a>
	 *
	 * @og.rev 8.0.0.0 (2021/09/30) 新規追加
	 *
	 * @param attri plugins要素
	 */
	public void setOptPlugins( final String attri ) {
		optPlugins = nval( getRequestParameter( attri ),null );
	}

	/**
	 * 【TAG】options:plugins:tooltipの要素に、その他ｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * options:plugins:tooltipの属性に、その他ｵﾌﾟｼｮﾝを追加します
	 * 指定する際の、前後の『{}』は、不要です。
	 * tooltip には、多数の要素が設定可能なので、外部で定義したｵﾌﾞｼﾞｪｸﾄを
	 * 指定するのが良いと思います。
	 *
	 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#tooltip">とほほ → ツールチップ </a>
	 *
	 * @og.rev 8.0.0.0 (2021/09/30) 新規追加
	 *
	 * @param attri tooltip要素
	 */
	public void setOptTooltip( final String attri ) {
		optTooltip = nval( getRequestParameter( attri ),null );
	}

	/**
	 * 【TAG】options:plugins:legendの要素に、その他ｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * options:plugins:legendの属性に、その他ｵﾌﾟｼｮﾝを追加します
	 * 指定する際の、前後の『{}』は、不要です。
	 * legend には、多数の要素が設定可能なので、外部で定義したｵﾌﾞｼﾞｪｸﾄを
	 * 指定するのが良いと思います。
	 *
	 * legend 関係の属性として、legendDisplay、legendPosition、usePointStyle を定義しています。
	 * optLegend属性を設定した場合、これらの属性とマージされるため、同じキーワードが存在した場合の
	 * 動作は、不明です。
	 *
	 * <a href="https://www.tohoho-web.com/ex/chartjs-params.html#legend">とほほ → 凡例(レジェンド) </a>
	 *
	 * @og.rev 8.0.0.0 (2021/09/30) 新規追加
	 *
	 * @param attri legend要素
	 */
	public void setOptLegend( final String attri ) {
		optLegend = nval( getRequestParameter( attri ),null );
		if( optLegend != null ) {
			useLegend = true;
		}
	}

	/**
	 * 【TAG】その他options:scales:xのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * <del>options:scales:xAxes の 要素の属性です。</del>
	 * options:scales:xAxes → options:scales:x の 要素の属性です。
	 *  ※ chartJS上は、Axes(axisの複数形)と、Axis を使い分けていますが、属性は、axis で統一します。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
	 *
	 * @param attri その他options:scales:xAxesのｵﾌﾟｼｮﾝ
	 */
	public void setOptAxis( final String attri ) {
		jsXAxis.addAxis( JsChartDataV3.AXIS , nval( getRequestParameter( attri ),null ) );
	}

	/**
	 * 【TAG】その他options:scales:x:ticksのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * <del>options:scales:xAxes:ticks の 要素の属性です。</del>
	 * options:scales:xAxes:ticks → options:scales:x:ticks の 要素の属性です。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
	 *
	 * @param attri その他options:scales:xAxes:ticksのｵﾌﾟｼｮﾝ
	 */
	public void setOptTicks( final String attri ) {
		jsXAxis.addAxis( JsChartDataV3.TICKS , nval( getRequestParameter( attri ),null ) );
	}

	/**
	 * 【TAG】その他options:scales:x:titleのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * <del>options:scales:xAxes:scaleLabel の 要素の属性です。</del>
	 * options:scales:xAxes:scaleLabel → options:scales:x:title の 要素の属性です。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
	 *
	 * @param title options:scales:x:title要素
	 */
	public void setOptTitle( final String title ) {
		jsXAxis.addAxis( JsChartDataV3.TITLE , nval( getRequestParameter( title ),null ) );
	}

	/**
	 * 【TAG】その他options:scales:x:gridのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * <del>options:scales:xAxes:gridLines の 要素の属性です。</del>
	 *  options:scales:xAxes:gridLines → options:scales:x:grid の 要素の属性です。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
	 *
	 * @param grid options:scales:x:gridの属性
	 */
	public void setOptGrid( final String grid ) {
		jsXAxis.addAxis( JsChartDataV3.GRID , nval( getRequestParameter( grid ),null ) );
	}

	/**
	 * 【TAG】x軸のﾀｲﾑの単位[year/quarter/month/week/day/hour/minute/second/millisecond]を指定します。
	 *
	 * @og.tag
	 * (xscaleTypeがtimeの場合に有効。指定しない場合は自動)
	 * options:scales:x:unit
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param tunit x軸のﾀｲﾑの単位 [year/quarter/month/week/day/hour/minute/second/millisecond]
	 */
	public void setTimeUnit( final String tunit ) {
		final String timeUnit = nval( getRequestParameter( tunit ),null );

		checkPara( timeUnit, SET_TIMEUNIT, "timeUnit" );

		jsXAxis.addTime( "unit" , timeUnit , USE_QUOTE );	// 文字列
	}

	/**
	 * 【TAG】x軸のﾀｲﾑの単位幅を指定します(xscaleTypeがtimeの場合に有効)。
	 *
	 * @og.tag
	 *  options:scales:x:time:unitStepSize → options:scales:x:time:stepSize の 要素の属性です。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param tunitStepSize x軸のﾀｲﾑの単位幅
	 */
	public void setTimeUnitStepSize( final String tunitStepSize ) {
		jsXAxis.addTime( "stepSize" , nval( getRequestParameter( tunitStepSize ),null ) , NO_QUOTE );	// 数値
	}

	/**
	 * 【TAG】x軸の設定するﾀｲﾑ(入力ﾃﾞｰﾀ)のﾌｫｰﾏｯﾄを指定します(xscaleTypeがtimeの場合に有効)。
	 *
	 * @og.tag
	 * ﾌｫｰﾏｯﾄは、chartjs-adapter-date-fns.bundle.min.js の定義を使用します。
	 * <a href="https://github.com/chartjs/chartjs-adapter-date-fns">chartjs-adapter-date-fns</a>
	 * <a href="https://zenn.dev/snjssk/articles/f05d1bcfeb9604#format">date-fns format</a>
	 * 例：yyyyMMddHHmmss
	 *
	 * 8.0.0.0 (2021/08/31)
	 *  代わりに、options:scales:x:time.parser で指定します。
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 * @og.rev 8.0.0.0 (2021/08/31) timeSetFormat → timeParser 変更
	 *
	 * @param tFormat x軸の設定するﾀｲﾑのﾌｫｰﾏｯﾄ処理
	 */
	public void setTimeParser( final String tFormat ) {
		jsXAxis.addTime( "parser" , nval( getRequestParameter( tFormat ),null ) , USE_QUOTE );	// 文字列
	}

	/**
	 * 【TAG】x軸の表示するﾀｲﾑのﾌｫｰﾏｯﾄを指定します(xscaleTypeがtimeの場合に有効)。
	 *
	 * @og.tag
	 * 8.0.0.0 (2021/08/31)
	 *   Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
	 *  <a href="https://date-fns.org/v2.23.0/docs/format">date-fns format</a>
	 *  ※ yyyy が、YYYY になっているが、よく分からない。
	 *
	 * 基本形：yyyyMMddHHmmss
	 * options:scales:x:time:displayFormats
	 *
	 * <table class="plain">
	 *   <caption>ﾀｲﾑのﾌｫｰﾏｯﾄ(抜粋)</caption>
	 *	 <tr><th>Pattern	</th><th>Result examples					</th><th>Unit				</th></tr>
	 *	 <tr><td>yyyy		</td><td>0044, 0001, 1900, 2017				</td><td>Calendar year		</td></tr>
	 *	 <tr><td>M			</td><td>1, 2, ..., 12						</td><td>Month (formatting) </td></tr>
	 *	 <tr><td>MM			</td><td>01, 02, ..., 12					</td><td>Month (formatting) </td></tr>
	 *	 <tr><td>MMM		</td><td>Jan, Feb, ..., Dec					</td><td>Month (formatting) </td></tr>
	 *	 <tr><td>MMMM		</td><td>January, February, ..., December	</td><td>Month (formatting) </td></tr>
	 *	 <tr><td>d			</td><td>1, 2, ..., 31						</td><td>Day of month		</td></tr>
	 *	 <tr><td>dd			</td><td>01, 02, ..., 31					</td><td>Day of month		</td></tr>
	 *	 <tr><td>H			</td><td>0, 1, 2, ..., 23					</td><td>Hour [0-23]		</td></tr>
	 *	 <tr><td>HH			</td><td>00, 01, 02, ..., 23				</td><td>					</td></tr>
	 *	 <tr><td>m			</td><td>0, 1, ..., 59						</td><td>Minute 			</td></tr>
	 *	 <tr><td>mm			</td><td>00, 01, ..., 59					</td><td>					</td></tr>
	 *	 <tr><td>s			</td><td>0, 1, ..., 59						</td><td>Second 			</td></tr>
	 *	 <tr><td>ss			</td><td>00, 01, ..., 59					</td><td>					</td></tr>
	 *	 <tr><td>S			</td><td>0, 1, ..., 9						</td><td>Fraction of second </td></tr>
	 *	 <tr><td>SS			</td><td>00, 01, ..., 99					</td><td>					</td></tr>
	 *	 <tr><td>SSS		</td><td>000, 001, ..., 999					</td><td>					</td></tr>
	 * </table>
	 *
	 * timeLblFormatが指定されている場合、全てのdisplayFormatsにtimeLblFormatを設定する
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) xscaleType の time 属性廃止。
	 * @og.rev 6.9.9.4 (2018/10/01) nvalを入れて、属性復活。
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param tLblFormat x軸の表示するﾀｲﾑのﾌｫｰﾏｯﾄ
	 * @see		#setTimeParser(String)
	 */
	public void setTimeLblFormat( final String tLblFormat ) {
		final String timeFmt = nval( getRequestParameter( tLblFormat ),null );
		if( timeFmt != null ) {
			final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
					.append(  "{year:'"		).append( timeFmt )
					.append( "',quarter:'"	).append( timeFmt )
					.append( "',month:'"	).append( timeFmt )
					.append( "',week:'"		).append( timeFmt )
					.append( "',day:'"		).append( timeFmt )
					.append( "',hour:'"		).append( timeFmt )
					.append( "',minute:'"	).append( timeFmt )
					.append( "',second:'"	).append( timeFmt )
					.append( "'}" );

			jsXAxis.addTime( "displayFormats" , buf.toString() , NO_QUOTE );	// ｵﾌﾞｼﾞｪｸﾄなので、クオートなし
		}
	}

	/**
	 * 【TAG】x軸の時間のﾂｰﾙﾁｯﾌﾟに使用するﾌｫｰﾏｯﾄ(ﾀｲﾑｽｹｰﾙ用)を指定します(xscaleTypeがtimeの場合に有効)。
	 *
	 * @og.tag
	 * 8.0.0.0 (2021/08/31)
	 *   Moment.js の依存関係が切れ、openGionV8では、date-fns を使用します。
	 *  <a href="https://date-fns.org/v2.23.0/docs/format">date-fns format</a>
	 *
	 * 基本形：yyyyMMddHHmmss
	 * options:scales:x:time:tooltipFormat
	 *
	 * ﾌｫｰﾏｯﾄは、timeLblFormat (内部的には、time:displayFormats)と同じ
	 *
	 * @og.rev 7.0.1.0 (2018/10/15) 時間のﾂｰﾙﾁｯﾌﾟに使用するﾌｫｰﾏｯﾄ(ﾀｲﾑｽｹｰﾙ用)
	 * @og.rev 7.0.1.1 (2018/10/22) JsChartDataV3ｵﾌﾞｼﾞｪｸﾄを使用。
	 *
	 * @param tipFormat x軸の表示するﾀｲﾑのﾌｫｰﾏｯﾄ
	 * @see		#setTimeParser(String)
	 */
	public void setTooltipFormat( final String tipFormat ) {
		jsXAxis.addTime( "tooltipFormat" , nval( getRequestParameter( tipFormat ),null ) , USE_QUOTE );	// 文字列
	}

	//========================================================================================

	/**
	 * 【TAG】y軸に横マーカーラインの設定値をCSV形式で複数指定します。
	 *
	 * @og.tag
	 * X軸に平行に固定値の線を引きます。線の値を、CSV形式で指定します。
	 * annotation:annotations オプションに名前付きで設定した中に yMin,yMax を定義します。
	 * 以前は、value に値をセットしていましたが、,yMin:値,yMax:値 にセットします。
	 *
	 * 8.0.0.0 (2021/08/31)
	 *	chartjs-plugin-annotation を使用します。
	 *	配列ではなく、名前付きの設定になります。(下記の例では、ymark0:)
	 *  options::plugins:annotation:annotations:ymark0:{
	 *      type:'line',                    ← 固定です。
	 *      borderWidth:2,                  ← markWidthの値(ﾗｲﾝ共通 初期値="2")
	 *      borderDash:[5,2],               ← markDashの値(ﾗｲﾝ共通  初期値=null)
	 *      yMin:値,yMax:値,                ← markValuesの値
	 *      borderColor: '#FF0000',         ← markColorsの値
	 *      label:{
	 *          enabled:'true',position:'start',    ← 固定です。
	 *          backgroundColor:'rgba(0,0,0,0)',    ← 固定です。
	 *          font:{ size:10 },                   ← markFontSizeの値(ﾗｲﾝ共通  初期値=10)
	 *          content:'基準値',       ← markLblsの値
	 *          yAdjust:-6,             ← markAdjustの値
	 *          color:'#FF0000',        ← markColorsの値
	 *          … ,
	 *      },
	 *  },
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 * @og.rev 8.0.0.0 (2021/08/31) chartJs V3 で大きく変更されています。
	 *
	 * @param mkVals y軸に横マーカーラインの設定値(CSV形式)
	 */
	public void setMarkValues( final String mkVals ) {
		markValues = nval( getRequestParameter( mkVals ) , markValues );
	}

	/**
	 * 【TAG】y軸に横マーカーラインの色をCSV形式で複数指定します。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に borderColor を定義します。
	 *
	 * X軸に平行に固定値の線を引きます。線の色を、CSV形式で指定します。
	 * markValues が指定されており、markColorsが指定されていない場合は、青色(BLUE)になります。
	 * 色指定に、VIVID,PASTEL を使えるようにします。
	 *
	 * 詳細は、markValues の説明をご確認願います。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 * @og.rev 7.0.1.3 (2018/11/12) 色指定に、VIVID,PASTEL を使えるようにします。
	 *
	 * @param mkCols y軸に横マーカーラインの色(CSV形式)
	 * @see	#setMarkValues(String)
	 */
	public void setMarkColors( final String mkCols ) {
		markColors = nval( getRequestParameter( mkCols ) , markColors );
	}

	/**
	 * 【TAG】y軸に横マーカーラインのラベルをCSV形式で複数指定します。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に
	 * label:content を定義します。
	 *
	 * label 属性の enabled:'true',position:'start',backgroundColor:'rgba(0,0,0,0)',
	 * font:{ size:10 } は固定で、color は、markColors 属性で指定した
	 * y軸に横マーカーラインの色を使用します。
	 * 色指定に、VIVID,PASTEL を使えるようにします。
	 *
	 * 詳細は、markValues の説明をご確認願います。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param mklbls y軸に横マーカーラインのラベル(CSV形式)
	 * @see	#setMarkValues(String)
	 */
	public void setMarkLbls( final String mklbls ) {
		markLbls = nval( getRequestParameter( mklbls ) , markLbls );
	}

	/**
	 * 【TAG】y軸に横マーカーラインのラベル表示位置の上下方向を調整します(初期値:-6)。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に
	 * label:yAdjust を定義します。
	 *
	 * これは、ラインに対するラベルの位置を表します。＋で、下側、－で上側に表示します。
	 * 初期値は、－６ で、ラインの上側に来るように調整しています。
	 *
	 * 詳細は、markValues の説明をご確認願います。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param mkAjst y軸に横マーカーラインのラベル表示位置の上下方向調整
	 * @see	#setMarkValues(String)
	 */
	public void setMarkAdjust( final String mkAjst ) {
		markAdjust = nval( getRequestParameter( mkAjst ) , markAdjust );
	}

	/**
	 * 【TAG】x軸に横マーカーラインのラベルをCSV形式で複数指定します。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に
	 * label:content を定義します。
	 *
	 * label 属性の enabled:'true',position:'end',backgroundColor:'white',
	 * font:{ size:10 } は固定で、color は、markColors 属性で指定した
	 * x軸に横マーカーラインの色を使用します。
	 * 色指定に、VIVID,PASTEL を使えるようにします。
	 *
	 * 詳細は、xmarkValues の説明をご確認願います。
	 *
	 * @og.rev 8.0.0.0 (2021/09/30) 新規追加
	 *
	 * @param mklbls x軸に横マーカーラインのラベル(CSV形式)
	 * @see	#setMarkValues(String)
	 */
	public void setXmarkLbls( final String mklbls ) {
		xmarkLbls = nval( getRequestParameter( mklbls ) , xmarkLbls );
	}

	/**
	 * 【TAG】x軸に縦マーカーラインの設定値をCSV形式で複数指定します。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に xMin,xMax を定義します。
	 *
	 * Y軸に平行に固定値の縦線を引きます。線の値を、CSV形式で指定します。
	 * 以前は、value に値をセットしていましたが、,xMin:値,xMax:値 にセットします。
	 *
	 * type:'line',borderWidth:2,scaleID:'x0Ax', 固定です。
	 *	chartjs-plugin-annotation を使用します。
	 *	配列ではなく、名前付きの設定になります。(下記の例では、xmark0:)
	 *
	 *  options:plugins:annotation:annotations:xmark0:{
	 *      type:'line',                    ← 固定です。
	 *      borderWidth:2,                  ← markWidthの値(ﾗｲﾝ共通 初期値="2")
	 *      borderDash:[5,2],               ← markDashの値(ﾗｲﾝ共通  初期値=null)
	 *      xMin:値,xMax:値,                ← xmarkValuesの値
	 *      borderColor:'#FF0000',          ← xmarkColorsの値
	 *  },
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
	 *
	 * @param mkVals x軸に縦マーカーラインの設定値(CSV形式)
	 * @see	#setMarkValues(String)
	 */
	public void setXmarkValues( final String mkVals ) {
		xmarkValues = nval( getRequestParameter( mkVals ) , xmarkValues );
	}

	/**
	 * 【TAG】x軸に縦マーカーラインの色をCSV形式で複数指定します。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に borderColor を定義します。
	 *
	 * Y軸に平行に固定値の縦線を引きます。線の色を、CSV形式で指定します。
	 * xmarkValues が指定されており、xmarkColorsが指定されていない場合は、青色(BLUE)になります。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) xmarkValues,xmarkColors属性の追加
	 * @og.rev 7.0.1.3 (2018/11/12) 色指定に、VIVID,PASTEL を使えるようにします。
	 *
	 * @param mkCols x軸に縦マーカーラインの色(CSV形式)
	 * @see	#setXmarkValues(String)
	 */
	public void setXmarkColors( final String mkCols ) {
		xmarkColors = nval( getRequestParameter( mkCols ) , xmarkColors );
	}

	/**
	 * 【TAG】x軸,y軸全マーカーライン共通のラインの幅を指定します:borderWidth(初期値:2)。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に borderWidth を定義します。
	 *
	 * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
	 *
	 * @param width マーカーライン共通のラインの幅
	 * @see	#setMarkValues(String)
	 */
	public void setMarkWidth( final String width ) {
		markWidth = nval( getRequestParameter( width ) , markWidth );
	}

	/**
	 * 【TAG】x軸,y軸全マーカーライン共通のラインに点線を指定([5,2]など)します:borderDash(初期値:null)。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に borderDash を定義します。
	 *
	 * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
	 * markDash="[5,2]" とすれば、線の長さが5px , 線と線の間が2px になります。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
	 *
	 * @param dash マーカーライン共通のラインの点線の形状
	 * @see	#setMarkValues(String)
	 */
	public void setMarkDash( final String dash ) {
		markDash = nval( getRequestParameter( dash ) , markDash );
	}

	/**
	 * 【TAG】x軸,y軸全マーカーライン共通のラベルのフォントサイズを指定します:label:font:size(初期値:10)。
	 *
	 * @og.tag
	 * annotation:annotations オプションに名前付きで設定した中に
	 * label:font:size を定義します。
	 *
	 * この値は、x軸,y軸関係なく、マーカーラインの順番も関係なく、共通設定になります。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) markWidth,markDash,markFontSize属性の追加
	 *
	 * @param size マーカーライン共通のフォントサイズ
	 * @see	#setMarkValues(String)
	 */
	public void setMarkFontSize( final String size ) {
		markFontSize = nval( getRequestParameter( size ) , markFontSize );
	}

	//========================================================================================

	/**
	 * 【TAG】すべてのﾃﾞｰﾀが０の場合、使用しないかどうか[true:除外する/false:除外しない]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * JSON データを作成して、JsChartV3に渡しますが、このフラグを true に設定すると
	 * 0 または、null（空文字列）のデータを出力しません。  6.8.3.0 (2017/11/27)
	 * グラフ系で、0 が、ありえない値として設定されている場合に、使用すると、
	 * 出力するデータ量を抑えることが出来ます。
	 *
	 * @og.rev 6.7.7.0 (2017/03/31) useZeroDataOmit属性の追加
	 *
	 * @param useZeroOmit ﾃﾞｰﾀが０の場合の使用可否 [true:除外する/false:除外しない]
	 */
	public void setUseZeroDataOmit( final String useZeroOmit ) {
		useZeroDataOmit = nval( getRequestParameter( useZeroOmit ) , useZeroDataOmit );
	}

	/**
	 * 【TAG】JSON出力で、値出力にレンデラを利用するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * JSONのデータのレンデラー変換を行うかどうか。
	 * 数値部分にはレンデラー変換は行いません。ラベル文字に行います。
	 * 指定しない場合は使用しない(false)です。
	 *
	 * @og.rev 6.7.9.0 (2017/04/28) useRenderer 追加
	 *
	 * @param	usernd レンデラーを利用するかどうか [true/false]
	 */
	public void setUseRenderer( final String usernd ) {
		useRenderer = nval( getRequestParameter( usernd ) , useRenderer );
	}

	/**
	 * 【TAG】検索結果をこのカラムでソートし直します(初期値:null)。
	 *
	 * @og.tag
	 * query で検索した結果を、JsChartV3で利用する場合、チャート上のソート順と、
	 * リストや、別のチャートでの表示準が異なる場合に、このカラムで、ソートしなおします。
	 * 通常は、labelColumn と同じ値でソートすることで、X軸の順番に表示されます。
	 *
	 * @og.rev 6.8.0.0 (2017/06/02) sortColumn 追加
	 *
	 * @param	sortClm このカラムでソートし直す
	 */
	public void setSortColumn( final String sortClm ) {
		sortColumn = nval( getRequestParameter( sortClm ) , sortColumn );
	}

	/**
	 * 【TAG】値の前後にクオートをはさむかどうか[true/false]指定します(初期値:false)。
	 *
	 * @og.tag
	 * 以前は、yscaleType="category" のときに、値が、文字列のため、クオートで囲う判断をしていました。
	 * その属性は、JsChartDataV3Tag に移ったため、新たなパラメータを用意します。
	 * 将来的に、自動判定にするか、JsChartDataV3Tag から情報を取得するかもしれません。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 新規登録
	 *
	 * @param flag 値の前後にクオートをはさむかどうか [true/false]
	 */
	public void setValueQuot( final String flag ) {
		valueQuot = nval( getRequestParameter( flag ),valueQuot );
	}

	/**
	 * 【TAG】WheelZoom処理を使用するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * plugins:zoom に、zoom:{wheel,pinch} と pan を定義します。(chartJs V3 の変更点)
	 * これは、chartjs-plugin-zoom.js を使用します。
	 * マウスホイールで、zoom処理、右クリックで移動(pan)します。
	 * ダブルクリックで元の状態に戻します。
	 * useDragZoom と同時指定した場合は、useZoom が優先されます。
	 *
	 * 初期値は、false:使用しないです。
	 *
	 * <ul>
	 *   <li>zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},</li>
	 *   <li>pan:{mode:'xy',enabled:true,},</li>
	 *   <li>canvasをクリックでzoomリセット	</li>
	 * </ul>
	 *
	 *  options:plugins:zoom:{
	 *      zoom:{mode:'xy',wheel:{enabled:true,},pinch:{enabled:true,},},
	 *      pan:{mode:'xy',enabled:true,},
	 *  },
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param flag WheelZoom処理を使用するかどうか [true:使用する/false:使用しない]。
	 */
	public void setUseZoom( final String flag ) {
		useZoom = nval( getRequestParameter( flag ) , useZoom );
	}

	/**
	 * 【TAG】DragZoom処理を使用するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * plugins:zoom に zoom:{drag} と pan:{modifierKey: 'ctrl',} を定義します。(chartJs V3 の変更点)
	 * これは、chartjs-plugin-zoom.js を使用します。
	 * 右クリックで範囲指定で、zoom処理、CTRLボタンを押しながら、右クリックで移動(pan)します。
	 * ダブルクリックで元の状態に戻します。
	 * useDragZoom と同時指定した場合は、useZoom が優先されます。
	 *
	 * 初期値は、false:使用しないです。
	 *
	 * <ul>
	 *   <li>zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)'},},</li>
	 *   <li>pan:{mode:'xy',enabled:true,modifierKey: 'ctrl',},</li>
	 *   <li>canvasをクリックでzoomリセット	</li>
	 * </ul>
	 *
	 *  options:plugins:zoom:{
	 *      zoom:{drag:{enabled:true,borderColor:'rgb(54,162,235)',borderWidth:1,backgroundColor:'rgba(54,162,235,0.3)'},},
	 *      pan:{mode:'xy',enabled:true,modifierKey: 'ctrl',},
	 *  },
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param flag DragZoom処理を使用するかどうか [true:使用する/false:使用しない]。
	 */
	public void setUseDragZoom( final String flag ) {
		useDragZoom = nval( getRequestParameter( flag ) , useDragZoom );
	}

	/**
	 * 【TAG】TableModelの指定のカラム(CSV形式)をconstの配列変数として出力します。
	 *
	 * @og.tag
	 * これは、指定のカラムのデータをJavaScriptのconst変数定義で配列として出力します。
	 * labelColumn や、JsChartDataV3Tag の chartColumn と同じ方法です。
	 *
	 * 例えば、TableModelを、sortColumn でソートすると、JsChartDataV3Tag の pointBGColor
	 * の配列順も変わりますので、ソートされた状態で出力したいことがあると思います。
	 *
	 * 8.0.0.0 (2021/08/31)
	 *  chartTypeが、bubble の場合、
	 *    x:は、jsChartData の chartColumn
	 *    y:は、varColumns で指定した1番目のカラム
	 *    r:は、varColumns で指定した2番目のカラム
	 *  scatter の場合は、y:の1番目のカラムのみ使用します。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 新規登録
	 * @og.rev 8.0.0.0 (2021/08/31) BUBBLEとSCATTERの追加
	 *
	 * @param clms 指定のカラム(CSV形式)をconstの配列変数として出力
	 */
	public void setVarColumns( final String clms ) {
		varColumns = nval( getRequestParameter( clms ) , varColumns );
	}

//	/**
//	 * 【TAG】const定義するJavaScript変数に使用できるかどうか[true/false]指定します。
//	 *
//	 * @og.tag
//	 * const定義するJavaScript変数に使用できる文字は、決まっています。
//	 *
//	 * 1文字目は数字と、特殊記号(アンダーバー(_)、ドル記号($)を除く)、をチェックします。
//	 * 厳密には、予約文字が使えなかったりするが、簡易ﾁｪｯｸとする。
//	 * 前後の空白文字は除外、それ以外の特殊記号は、アンダーバー(_)に変換します。
//	 * 初期値[false]
//	 *
//	 * @og.rev 8.0.0.0 (2021/09/30) 新規登録
//	 *
//	 * @param flag JavaScript変数に使用できるかどうか[true/false]指定
//	 */
//	public void setUseVarCheck( final String flag ) {
//		useVarCheck = nval( getRequestParameter( flag ) , useVarCheck );
//	}

	//========================================================================================

	/**
	 * 【TAG】(通常は使いません)sessionから所得する DBTableModelオブジェクトの ID。
	 *
	 * @og.tag
	 *
	 * @og.rev 6.9.9.3 (2018/09/25) nvalを入れて、初期値を設定します。
	 *
	 * @param tableId テーブルID
	 */
	public void setTableId( final String tableId ) {
		this.tableId = nval( getRequestParameter( tableId ) , this.tableId );
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
				.append( "X_AXIS=" ).append( jsXAxis ).append( CR );

		jsChartData.forEach( js -> buf.append( "Y_AXIS=" ).append( jsXAxis ).append( CR ) );

		return ToString.title( this.getClass().getName() )
			.println( "VERSION"				, VERSION				)
			.println( "id"					, id					)
			.println( "tableId"				, tableId				)
			.println( "chartType"			, chartType				)
			.println( "width"				, width					)
			.println( "height"				, height				)
			.println( "barWidthPer"			, barWidthPer			)
			.println( "title"				, title					)
			.println( "titlePosition"		, titlePosition			)
			.println( "legendPosition"		, legendPosition		)
			.println( "legendDisplay"		, legendDisplay			)
			.println( "xscaleType"			, xscaleType			)
			.println( "optOptions"			, optOptions			)	// 7.0.1.2 (2018/11/04)
//			.println( "optChart"			, optChart				)	// 7.0.1.2 (2018/11/04)
			.fixForm().println()
			.println( buf ).toString();
	}
}
