/*
 * 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.Set;											// 6.4.3.4 (2016/03/11)
import java.util.regex.Matcher;									// 7.0.1.1 (2018/10/22)
import java.util.regex.Pattern;									// 7.0.1.1 (2018/10/22)
import java.util.Locale ;										// 8.0.0.0 (2021/08/31)

import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.io.JsChartDataV3;
import org.opengion.fukurou.util.ArraySet;						// 6.4.3.4 (2016/03/11)
import org.opengion.fukurou.util.ToString;
import org.opengion.fukurou.util.ColorMap;						// 6.7.7.0 (2017/03/31)
import org.opengion.fukurou.util.StringUtil ;

import static org.opengion.fukurou.util.StringUtil.nval ;

/**
 * 設定された値をJsChartDataV3に設定し、
 * JsChartV3TagのJsChartDataV3リストに追加するタグです。
 *
 * @og.formSample
 * ●形式：&lt;og:jsChartDataV3 chartColumn="…" … /&gt;
 * ●body:なし
 *
 * ●Tag定義：
 * &lt;og:jsChartDataV3
 *      chartColumn     ○【TAG】ﾁｬｰﾄのｶﾗﾑ名を指定します(必須)。
 *      useAxis           【TAG】y軸表示を行うかどうか[true/false]を指定します[初期値:null(=false)]
 *      id                【TAG】y軸のid(自動採番 'y'+連番)
 *  ===================    data:datasets[idx]: の 要素。y[idx]Ds 変数の最上位にセットします
 *      label             【TAG】凡例の値を指定します(label)
 *      type              【TAG】複合ﾁｬｰﾄの種類を指定します[line/bar](type)
 *      fill              【TAG】線下を塗りつぶすかどうか[true/false]を指定します(fill[初期値:false])
 *      tension           【TAG】線の伸張を指定します。0で直線になります(tension[初期値:0.0])
 * (V3) hidden            【TAG】データを表示OFFの状態にするかどうか[true/false]を指定します(hidden[初期値:false])	8.0.0.0 (2021/08/31) 新規追加
 *      backgroundColor   【TAG】ﾃﾞｰﾀの背景色を指定します(色,色番号,VIVID,PASTEL,V0～,P0～)(backgroundColor[初期値:自動])
 *      borderColor       【TAG】線の色を指定します(色,色番号,VIVID,PASTEL,V0～,P0～)(borderColor[初期値:自動])
 *      borderWidth       【TAG】線の幅を指定します(borderWidth[初期値:null(=3)])
 *      borderDash        【TAG】点線のスタイルを配列で指定します(borderDash[初期値:null(=[])])
 *      pointStyle        【TAG】点のスタイル(circle,triangle,rect,…)を指定します(pointStyle[初期値:null(=[])])
 *      pointRadius       【TAG】点の大きさを指定します(pointRadius[初期値:null(=3)])
 *      showLine          【TAG】ラインを表示するかどうか[true/false]を指定します(showLine[初期値:null(=true)])
 *      spanGaps          【TAG】データがないポイント間の処理方法[true/false]を指定します(spanGaps[初期値:null])
 *      pointBGColor      【TAG】ポイントの色を指定します(色,色番号,VIVID,PASTEL,V0～,P0～)(pointBackgroundColor[初期値:自動])
 *  ===================    options:scales:y: の 要素を指定する場合に、設定します
 *      position          【TAG】y軸の表示位置[left,right]を指定します(position[初期値:null(=left)])
 *      scaleType         【TAG】y軸のｽｹｰﾙﾀｲﾌﾟ[linear/category/time/…]を指定します(type[初期値:linear])
 *      categoryList      【TAG】y軸のﾒﾓﾘﾘｽﾄをCSV形式で指定します(scaleTypeがcategoryの場合)(labels)
 *      ylabel            【TAG】y軸に表示するﾗﾍﾞﾙ文字(title:text)
 *      beginAtZero       【TAG】y軸を０から書き始まるかどうか[true/false]を指定(beginAtZero[初期値:null(=false)])
 * (V3) grace             【TAG】y軸の最大、最小値から指定分スケールを大きくとる(grace[初期値:null])	8.0.0.0 (2021/08/31) 新規追加
 *      max               【TAG】y軸の最大値を指定します(scaleTypeがlinearの場合に有効)(max)
 *      min               【TAG】y軸の最小値を指定します(scaleTypeがlinearの場合に有効)(min)
 *  ===================    options:scales:y:ticks: の 要素を指定する場合に、設定します
 *      fontColor         【TAG】y軸のフォントの色(色,色番号,VIVID,PASTEL,V0～,P0～)(ticks:color[初期値:自動])
 *      scaleCallback     【TAG】y軸ｺｰﾙﾊﾞｯｸを指定します(ticks:callback)
 *      stepSize          【TAG】y軸のメモリ幅を指定します(scaleTypeがlinearの場合に有効)(ticks:stepSize)
 *  ===================    options:scales:y:grid: の 要素を指定する場合に、設定します
 *      gridColor         【TAG】grid:color属性( grid:{color:'red',} を生成)します(gridLinesと同時使用時は動作不定)
 *  ===================
 *      optDataset        【TAG】その他data:datasetのｵﾌﾟｼｮﾝを追加します
 *      optAxis           【TAG】その他options:scales:yのｵﾌﾟｼｮﾝを追加します
 *      optTicks          【TAG】その他options:scales:y:ticksのｵﾌﾟｼｮﾝを追加します
 * (V3) optTitle          【TAG】その他options:scales:y:titleのｵﾌﾟｼｮﾝを追加します	8.0.0.0 (2021/08/31) 新規追加
 * (V3) optGrid           【TAG】その他options:scales:y:gridのｵﾌﾟｼｮﾝを追加します	8.0.0.0 (2021/08/31) 新規追加
 *  ===================
 *      ticks             【廃止】optTicks を使用してください						8.0.0.0 (2021/08/31) 廃止
 *      gridLines         【廃止】optGrid を使用してください(旧 gridLines)			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) 廃止
 *  ===================
 *      caseKey           【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
 *      caseVal           【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
 *      caseNN            【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
 *      caseNull          【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
 *      caseIf            【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
 *      debug             【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)					// 7.0.1.1 (2018/10/22)
 *  /&gt;
 *
 * ●使用例
 * &lt;og:jsChartV3...&gt;
 *     &lt;og:jsChartDataV3
 *         chartColumn ="CLM1"
 *         label       ="ラベル"
 *         fill        ="true"
 *         tension     ="0"
 *         borderColor ="rbga(150,150,150,0.7)"
 *         borderWidth ="2"
 *     /&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 JsChartDataV3Tag extends CommonTagSupport {
	//* このプログラムのVERSION文字列を設定します。{@VALUE} */
	private static final String VERSION = "8.0.0.0 (2021/08/31)" ;
	private static final long serialVersionUID = 800020210831L ;

	private static final boolean	USE_QUOTE		= false;
	private static final boolean	NO_QUOTE		= true;		// IS_NUMBER か、!USE_QUOTE か、

	private static final Set<String> SET_TYPE		= new ArraySet<>( "line","bar" );
	private static final Set<String> SET_PSTYLE		= new ArraySet<>( "circle","triangle","rect","rectRot","cross","crossRot","star","line","dash","rectRounded" );
	private static final Set<String> SET_POSITION	= new ArraySet<>( "left","right" );
	private static final Set<String> SET_SCALE		= new ArraySet<>( "linear","logarithmic","category","time","timeseries","realtime" );	// 8.0.0.0 (2021/08/31)
	private static final Set<String> SET_BOOLEAN	= new ArraySet<>( "true","false" );

	private transient JsChartDataV3 jsData  = new JsChartDataV3();

	private String	yAxisID				;	// 7.0.1.1 (2018/10/22) y軸のid(自動採番 'y'+連番)

	// 8.0.0.0 (2021/08/31) chartJS V3 の初期値と同じになったので、直接登録します。
	private String	borderColor			;	// borderColor は、colorNo と競合するので、最後に判定します。
	private String	backgroundColor		;	// backgroundColor が未設定の場合は、borderColor を使用します。

//	private static final String D_TENSION	= "0.4";	// 7.0.1.1 (2018/10/22) 初期値
	private static final String D_TENSION	= "0.0";	// 8.0.0.0 (2021/08/31) 初期値変更(0.4 → 0.0)

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

	/**
	 * Taglibの終了タグが見つかった時に処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 6.7.6.0 (2017/03/17) タグの使用を決める共通属性の追加
	 * @og.rev 6.7.7.0 (2017/03/31) backgroundColor が未設定の場合は、borderColor を使用します。
	 * @og.rev 6.8.5.0 (2018/01/09) pointStyle , pointRadius , showLine 属性の追加。
	 * @og.rev 7.0.1.1 (2018/10/22) rightAxis 属性の追加。
	 *
	 * @return 後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();
		if( !useTag() ) { return EVAL_PAGE ; }					// 6.7.6.0 (2017/03/17)

		final JsChartV3Tag jsChartTag = (JsChartV3Tag) findAncestorWithClass( this, JsChartV3Tag.class );

		if( jsChartTag == null ) {
			final String errMsg = "jsChart タグが見つかりませんでした。";
			throw new HybsSystemException( errMsg );
		}

		final int size = jsChartTag.getJsChartDataSize();		// 登録順で、現時点で持っている個数
		if( yAxisID == null ) { yAxisID = "y" + size ; }		// 指定しない場合は、y軸のid(自動採番 'y'+連番)

		if( size == 0 ) { jsData.setUseAxis( true ); }			// 要方法検討。false でもY軸が表示されるが不完全
		jsData.setId( yAxisID );

		// borderColor と、backgroundColor の設定
		setBorderOrBackColor( jsChartTag.isOneColor() ? size : -1 );		// 7.0.1.3 (2018/11/12) 変数の集約

		// 8.0.0.0 (2021/08/31) chartJS V3 の初期値と同じになったので、直接登録します。
//		// fill は、未設定時に、false をあえて設定する必要がある。
//		jsData.addDataset( "fill" , String.valueOf( fill ) , NO_QUOTE );	// 数値(boolean)

		jsChartTag.addJsChartData( jsData );

		return EVAL_PAGE;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 6.7.7.0 (2017/03/31) jsDataのローカル変数化。
	 * @og.rev 6.8.5.0 (2018/01/09) pointStyle , pointRadius , showLine 属性の追加。
	 * @og.rev 7.0.1.1 (2018/10/22) rightAxis 属性の追加。
	 * @og.rev 7.0.1.1 (2018/10/22) 初期値は、ﾃﾞﾌｫﾙﾄ(出力しない)に変更。
	 * @og.rev 8.0.0.0 (2021/08/31) chartJS V3 の初期値と同じになったので、直接登録します。
	 */
	@Override
	protected void release2() {
		super.release2();
		jsData				= new JsChartDataV3();

		yAxisID				= null;		// 7.0.1.1 (2018/10/22) y軸のid(自動採番 'y'+連番)

//		fill				= false;	// 7.0.1.1 (2018/10/22) lineﾁｬｰﾄの下部塗りつぶし(初期値:falseが、chartJS の初期値と異なるので、後付する)
		borderColor			= null;		// borderColor は、colorNo と競合するので、最後に判定します。
		backgroundColor		= null;		// backgroundColor が未設定の場合は、borderColor を使用します。
	}

	/**
	 * borderColorとbackgroundColor の設定
	 *
	 * borderColorとbackgroundColor は、どちらか一方が設定されている場合は、
	 * もう片方も、そちらにあわせます。
	 * どちらも設定されていない場合は、ﾁｬｰﾄの番号から、色コードを自動で割り当てます。
	 * また、ｷｰﾜｰﾄﾞ PASTELとVIVID が指定された場合は、グラフごとに、色を変える配列を設定します。
	 *
	 * ※ 引数の先頭が $ の場合は、先に、JsChartV3Tag#varColumns などで、配列のオブジェクトを
	 *    作成している場合に、そのまま使用するように指示します。なお $ は外して設定します。
	 *
	 * @og.rev 7.0.1.3 (2018/11/12) 色情報を返すメソッドを集約します。
	 *
	 * @param cnt 現在のﾁｬｰﾄの番号(マイナスの場合は、JavaScript配列形式で返します。)
	 */
	private void setBorderOrBackColor( final int cnt ) {
		// 7.0.1.3 (2018/11/12) 色情報を返すメソッドを集約します。
		if( borderColor == null ) {					// borderColorが未設定
			backgroundColor = makeColor( backgroundColor , cnt );
			borderColor = backgroundColor;
		}
		else if( backgroundColor == null ) {		// backgroundColorが未設定
			borderColor		= makeColor( borderColor	 , cnt );
			backgroundColor = borderColor;
		}
		else {
			backgroundColor = makeColor( backgroundColor , cnt );
			borderColor		= makeColor( borderColor	 , cnt );
		}

		jsData.addDataset( "borderColor"		, borderColor		, NO_QUOTE );	// 文字はすでにクオート付き、配列の場合はクオート不用
		jsData.addDataset( "backgroundColor"	, backgroundColor	, NO_QUOTE );	// 文字はすでにクオート付き、配列の場合はクオート不用
	}

	/**
	 * ﾊﾟﾗﾒｰﾀﾁｪｯｸ用ﾒｿｯﾄﾞ。
	 *
	 * @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() );
		}
	}

	/**
	 * 色情報を返します。
	 *
	 * 通常の、#XXXXXX形式の16bitRGB表記や、rgb(r,g,b)や、rgba(r,g,b,a) などが設定可能です。
	 * 色の代わりに、ColorMapの色番号や色記号を指定できます。
	 *
	 * 特殊ｷｰﾜｰﾄﾞとして、VIVIDとPASTEL やビビッド、0～11 (V0～V11) , パステル、12～23 (P0～P11)
	 * を指定できます。
	 * CSV形式の場合、cnt で指定された番号の色を使用します。-1 の場合は、JavaScriptの配列文字列で返します。
	 *
	 * キーがnull の場合は、色番号から初期設定の値を返します。
	 *
	 * ※ 引数にrgbを含む場合は、無条件の元の値を返します。
	 *    これは、ColorMap.getColorKey で、CSV分解してしまうからです。
	 *
	 * ※ 引数の先頭が $ の場合は、先に、JsChartV3Tag#varColumns などで、配列のオブジェクトを
	 *    作成している場合に、そのまま使用するように指示します。なお $ は外して設定します。
	 *
	 * @og.rev 7.0.1.3 (2018/11/12) 色情報を返すメソッドを集約します。
	 * @og.rev 8.0.0.0 (2021/08/31) 引数にrgbを含む場合は、無条件の元の値を返します。
	 *
	 * @param colKey	色を表すｷｰﾜｰﾄﾞ(色,色番号,VIVID,PASTEL,V0～,P0～)
	 * @param cnt		CSV形式か、VIVID,PASTEL の場合、指定の番号の色を使用します。
	 * @return 色文字列
	 */
	private String makeColor( final String colKey, final int cnt ) {
		// cnt < 0 の場合、CSV形式なら、JavaScript配列で色を返します。
		final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );

		// 8.0.0.0 (2021/08/31) 引数にrgbを含む場合は、無条件の元の値を返します
		if( colKey != null && colKey.toUpperCase(Locale.JAPAN).contains( "RGB" ) ) {
			buf.append( '\'' ).append( colKey ).append( '\'' );
		}
		else if( colKey != null && colKey.startsWith( "$" ) ) {
			buf.append( colKey.substring(1) );				// 先頭が $ で始まる場合は、ｷｰﾜｰﾄﾞそのものを戻す。
		}
		else if( cnt < 0 ) {
			final String[] cols = ColorMap.getColorKeys( colKey );		// nullの場合は、ビビッドとパステルの全24色
			if( cols.length == 1 ) {		// 配列が1の場合、配列にせず、値をそのまま設定します。
				buf.append( '\'' ).append( cols[0] ).append( '\'' );
			}
			else {
				buf.append( "['" ).append( String.join( "','", cols ) ).append( "']" );
			}
		}
		else {
			// 色順指定されているので、1色だけ返します。
			final String[] cols = StringUtil.csv2Array( colKey );
			if( cols.length == 0 ) {		// 元のcolKeyがnullかゼロ文字列
				buf.append( '\'' ).append( ColorMap.getColorKey( cnt ) ).append( '\'' );		// cnt に応じた自動設定
			}
			else {
				final String col = cols[cnt % cols.length];					// オーバーする場合は、繰返しになります。
				buf.append( '\'' ).append( ColorMap.getColorKey( col , col ) ).append( '\'' );
			}
		}

		return buf.toString();
	}

	/**
	 * 【TAG】ﾁｬｰﾄのｶﾗﾑ名を指定します(必須)。
	 *
	 * @og.tag
	 *
	 * @param clm ﾁｬｰﾄのｶﾗﾑ名
	 */
	public void setChartColumn( final String clm ) {
		jsData.setChartColumn( nval( getRequestParameter( clm ),null ) );
	}

	/**
	 * 【TAG】このﾃﾞｰﾀのy軸を表示するかどうか[true/false]を指定します(初期値:false)。
	 *
	 * @og.tag
	 * true にセットした場合、jsChartTag で、yAxis に対して、一連の設定を行います。
	 * 初期値(false)ですが、1つのデータセットは必ず表示されるようです。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) useAxis 属性の追加。
	 *
	 * @param use 右側のy軸表示するかどうか [true:表示する/false:表示しない]
	 */
	public void setUseAxis( final String use ) {
		jsData.setUseAxis( nval( getRequestParameter( use ), false ) );
	}

	/**
	 * 【TAG】ﾃﾞｰﾀﾁｬｰﾄのIDを指定します。
	 *
	 * @og.tag
	 * 指定しない場合は、y軸のid(自動採番 'y'+連番) になります。
	 * options:scales:y の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param   id 固有の名前
	 */
	@Override
	public void setId( final String id ) {
		yAxisID  = nval( getRequestParameter( id ),null );
	}

	//===================    data:datasets[idx]: の 要素。y[idx]Ds 変数の最上位にセットします

	/**
	 * 【TAG】凡例の値を指定します。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 *
	 * @param lbl 凡例
	 */
	public void setLabel( final String lbl ) {
		jsData.addDataset( "label" , nval( getRequestParameter( lbl ),null ) , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】複合ﾁｬｰﾄの種類を指定します[line/bar]。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 *
	 * 通常は、JsChartV3TagタグのchartTypeで指定しますが、複合グラフの場合は、個々のJsChartDataV3Tag でタイプを指定します。
	 * なお、複合グラフ時には、JsChartV3TagタグのchartTypeを、"bar" にしておかないと、きちんと表示しないようです。
	 *
	 * @param type 種類 [line/bar]
	 */
	public void setType( final String type ) {
		final String ctype = nval( getRequestParameter( type ),null );

		checkPara( ctype, SET_TYPE, "type" );
		jsData.addDataset( "type" , ctype , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】線下を塗りつぶすかどうか[true/false]を指定します(fill[初期値:false])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * フィル(線より下の塗りつぶし) を設定します。
	 *
	 * @og.rev 8.0.0.0 (2021/08/31) chartJS V3 の初期値と同じになったので、直接登録します。
	 *
	 * @param flag 塗りつぶすかどうか [true/false]
	 */
	public void setFill( final String flag ) {
		// 8.0.0.0 (2021/08/31)  lineﾁｬｰﾄの下部塗りつぶし(初期値:falseが、chartJS V3 の初期値と同じになったので、後付する必要がなくなった。)
		final String fill =  nval( getRequestParameter( flag ),null );
		checkPara( fill, SET_BOOLEAN, "fill" );
		jsData.addDataset( "fill" , fill , NO_QUOTE );	// 数値(boolean)
	}

	/**
	 * 【TAG】線の伸張を指定します。0で直線になります(初期値:0.4 → 0.0)。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * 伸張 を設定します。
	 *
	 * 8.0.0.0 (2021/08/31)
	 *  以前のﾊﾞｰｼﾞｮﾝでは初期値は、0.4 でしたが、Ver3 では、0.0 になりました。
	 *  互換性は考慮しませんので、必要な場合は、各自で設定してください。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 初期値は、ﾃﾞﾌｫﾙﾄ(出力しない)に変更。
	 * @og.rev 8.0.0.0 (2021/08/31) 初期値変更(0.4 → 0.0)
	 *
	 * @param tension 線の伸張
	 */
	public void setTension( final String tension ) {
		jsData.addDataset( "tension" , nval( getRequestParameter( tension ),D_TENSION ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】データを表示OFFの状態にするかどうか[true/false]を指定します(hidden[初期値:false])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * グラフ表示後に凡例をクリックすると表示がOFFします。これを初期状態に設定します。
	 * 初回表示時に、グラフを非表示にしてあるので、必要都度表示することが可能になります。
	 *
	 * @param hide データを表示OFFかどうか [true/false]
	 */
	public void setHidden( final String hide ) {
		final String hidden =  nval( getRequestParameter( hide ),null );

		checkPara( hidden, SET_BOOLEAN, "hidden" );
		jsData.addDataset( "hidden" , hidden , NO_QUOTE );		// 数値(boolean)
	}

	/**
	 * 【TAG】ﾃﾞｰﾀの背景色を指定します(backgroundColor[初期値:自動])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * 色,色番号,VIVID,PASTEL,V0～,P0～ で指定します。
	 * backgroundColor = "BLUE" とすると、すべての背景色を指定できます。
	 * 配列で指定すると、データの順番に適用されます。
	 * 例：backgroundColor = "['#ffaaaa','#ffffaa','#aaffaa','#aaaaff','#aaaaff']"
	 *
	 * 特殊ｷｰﾜｰﾄﾞとして、PASTELとVIVID を指定することで、パステルカラーやビビッドカラーの色ｺｰﾄﾞを指定できます。
	 *
	 * ※ 引数の先頭が $ の場合は、先に、JsChartV3Tag#varColumns などで、配列のオブジェクトを
	 *    作成している場合に、そのまま使用するように指示します。なお $ は外して設定します。
	 *
	 * 背景色を指定しない場合、線の色(borderColor)を使用します。
	 *
	 * @og.rev 6.9.9.2 (2018/09/18) パステルカラーの色文字列のCSV形式文字列
	 *
	 * @param bgColor 背景色
	 * @see		#setBorderColor(String)
	 */
	public void setBackgroundColor( final String bgColor ) {
		backgroundColor = nval( getRequestParameter( bgColor ),null );
	}

	/**
	 * 【TAG】線の色を指定します(borderColor[初期値:自動])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * 色,色番号,VIVID,PASTEL,V0～,P0～ で指定します。
	 * borderColor = "BLUE" とすると、すべての線の色を指定できます。
	 * 配列で指定すると、データの順番に適用されます。
	 * 例：borderColor = "['#ffaaaa','#ffffaa','#aaffaa','#aaaaff','#aaaaff']"
	 *
	 * 色の代わりに、ColorMapの色番号を指定したい場合は、colorNo を指定します。
	 * 両方指定した場合は、borderColor が優先されます。
	 * どちらも指定しない場合は、JsChartV3Tagに登録した順番に色コードで指定されます。
	 *
	 * ※ 引数の先頭が $ の場合は、先に、JsChartV3Tag#varColumns などで、配列のオブジェクトを
	 *    作成している場合に、そのまま使用するように指示します。なお $ は外して設定します。
	 *
	 * 特殊ｷｰﾜｰﾄﾞとして、PASTELとVIVID を指定することで、パステルカラーやビビッドカラーの
	 * 色ｺｰﾄﾞ配列を指定できます。
	 *
	 * @param color 線の色
	 */
	public void setBorderColor( final String color ) {
		// colorNo で、初期値設定されている可能性があるので、nval の初期値は、borderColor にしておく。
		borderColor = nval( getRequestParameter( color ),borderColor );
	}

	/**
	 * 【TAG】線の幅を指定します(borderWidth[初期値:null(=3)])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 *
	 * @param width 線の幅
	 */
	public void setBorderWidth( final String width ) {
		jsData.addDataset( "borderWidth" , nval( getRequestParameter( width ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】点線のスタイルを配列で指定します(borderDash[初期値:null(=[])])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 *
	 * ダッシュ線のスタイルは、配列で指定します。
	 * borderDash="[5,2]" とすれば、線の長さが5px , 線と線の間が2px になります。
	 *
	 * @og.rev 7.0.1.3 (2018/11/12) 点線のスタイル追加
	 *
	 * @param dash 点線のスタイル
	 */
	public void setBorderDash( final String dash ) {
		jsData.addDataset( "borderDash" , nval( getRequestParameter( dash ),null ) , NO_QUOTE );		// 配列
	}

	/**
	 * 【TAG】点のスタイル[circle,triangle,rect,…]を指定します(pointStyle[初期値:null(=[])])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * jsChartTag で、usePointStyle = "true" をセットした場合に有効になります。
	 * 点のスタイルは、circle,triangle,rect,rectRot,cross,crossRot,star,line,dash,rectRounded
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param ptStyle 点のスタイル [circle,triangle,rect,rectRot,cross,crossRot,star,line,dash,rectRounded]
	 */
	public void setPointStyle( final String ptStyle ) {
		final String pointStyle = nval( getRequestParameter( ptStyle ),null );

		checkPara( pointStyle, SET_PSTYLE, "pointStyle" );
		jsData.addDataset( "pointStyle" , pointStyle , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】点の大きさを指定します(pointRadius[初期値:null(=3)])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * jsChartTag で、usePointStyle = "true" をセットした場合に有効になります。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param ptRadius 点の大きさを指定します。
	 */
	public void setPointRadius( final String ptRadius ) {
		jsData.addDataset( "pointRadius" , nval( getRequestParameter( ptRadius ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】ラインを表示するかどうか[true/false]を指定します(showLine[初期値:null(=true)])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * jsChartTag で、usePointStyle = "true" をセットした場合に有効になります。
	 * 初期値(null)は、showLine 属性を設定しませんが、chartJS 自体の初期値が true
	 * なので、表示されます。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param show ラインを表示するかどうか [true:表示する/false:表示しない]
	 */
	public void setShowLine( final String show ) {
		jsData.addDataset( "showLine" , nval( getRequestParameter( show ),null ) , NO_QUOTE );		// Boolean
	}

	/**
	 * 【TAG】データがないポイント間の処理方法を指定します[true/false]を指定します(spanGaps[初期値:null])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * trueの場合、データがないかnullのポイント間に線が引かれます。
	 * falseの場合、データがnullのポイントは、行に切れ目を作成します。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 新規登録
	 *
	 * @param flag データがないポイント間の処理を行うかどうか [true/false]
	 */
	public void setSpanGaps( final String flag ) {
		jsData.addDataset( "spanGaps" , nval( getRequestParameter( flag ),null ) , NO_QUOTE );		// Boolean
	}

	/**
	 * 【TAG】ポイントの色を指定します(pointBackgroundColor[初期値:自動])。
	 *
	 * @og.tag
	 * data:datasets[idx]: の 要素
	 * 色,色番号,VIVID,PASTEL,V0～,P0～ で指定します。
	 * 点の塗りつぶしの色を指定します。属性名が長いので、短縮しています。
	 * 単独文字列の場合は、すべての点を同じ色で塗ります。配列([]で囲う)の場合は、
	 * 点の並び順に応じて、色付けを行います。
	 *
	 * 配列([]で囲う)か、const定義変数を想定していますので、前後にクオートを付けません。
	 * 単独文字列を指定する場合は、"'red'" のように、クオートを付けてください。
	 * 通常は、backgroundColorが使用されますので、単独文字で色指定は行う必要はありません。
	 *
	 * ポイントの色指定に、ColorMapの色コードは使えません。
	 *
	 * @og.rev 6.8.5.0 (2018/01/09) 新規登録
	 *
	 * @param cols 点の塗りつぶしの色(単独、配列)
	 */
	public void setPointBGColor( final String cols ) {
		// 配列[]か、変数なので、クオート無しにします。
		jsData.addDataset( "pointBackgroundColor" , nval( getRequestParameter( cols ),null ) , NO_QUOTE );
	}

	//===================    options:scales:y: の 要素を指定する場合に、設定します

	/**
	 * 【TAG】y軸の表示位置[left,right]を指定します(position[初期値:null(=left)])。
	 *
	 * @og.tag
	 * options:scales:y: の 要素
	 * 複合グラフ表示で、指定のデータのy軸を、右に表示したい場合は、right を指定します。
	 * 初期値(null)は、左に表示されます。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param pos y軸の表示位置 [left,right]
	 */
	public void setPosition( final String pos ) {
		final String position = nval( getRequestParameter( pos ),null );

		checkPara( position, SET_POSITION, "position" );
		jsData.addAxis( "position" , position , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】y軸のｽｹｰﾙﾀｲﾌﾟ[linear/category/time/…]を指定します(type[初期値:linear])。
	 *
	 * @og.tag
	 * options:scales:y: の 要素
	 * 未指定(null)の場合は、linear になります。
	 * ｽｹｰﾙﾀｲﾌﾟ[linear/logarithmic/category/time/timeseries/realtime]を指定します。
	 *
	 * realtime は、chartjs-plugin-streaming を使用時の縦スクロール時のみ適用可能です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param type y軸のｽｹｰﾙﾀｲﾌﾟ [linear/logarithmic/category/time/timeseries/realtime]
	 */
	public void setScaleType( final String type ) {
		final String sType = nval( getRequestParameter( type ),null );

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

		jsData.addAxis( "type" , sType , USE_QUOTE );		// 文字
	}

	/**
	 * 【TAG】y軸のﾒﾓﾘﾘｽﾄをCSV形式で指定します(scaleTypeがcategoryの場合に有効)。
	 *
	 * @og.tag
	 * ※ 通常のCSVで指定します。
	 * options:scales:y: の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param categoryList y軸のﾒﾓﾘﾘｽﾄ
	 */
	public void setCategoryList( final String categoryList ) {
		final String lbls = nval( getRequestParameter( categoryList ),null );

		if( lbls != null ) {
			// 「,」を「','」に変換して設定。(,前後の半角ｽﾍﾟｰｽは除去する)
			final String regex = " *, *";
			final Pattern pttn = Pattern.compile( regex );
			final Matcher mtch = pttn.matcher( lbls );

			// y軸ｶﾃｺﾞﾘｰﾘｽﾄの設定
			final String labels = "['" + mtch.replaceAll( "','" ) + "']" ;

			jsData.addAxis( "labels" , labels , NO_QUOTE );		// 配列なので、クオート不用
		}
	}

	/**
	 * 【TAG】y軸に表示するﾗﾍﾞﾙ文字(title:text)を指定します(初期値:null)。
	 *
	 * @og.tag
	 * 横軸に表示する文字を指定します。
	 * options:scales:yAxes:scaleLabel:labelString → options:scales:y:title:text の 要素の属性です。
	 * title:{display:true,text:'ﾗﾍﾞﾙ文字',} がセットされます。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param label y軸に表示するﾗﾍﾞﾙ文字
	 */
	public void setYlabel( final String label ) {
		final String lbl = nval( getRequestParameter( label ),null );
		if( lbl != null ) {
			final String scLbl = "display: true,text:'" + lbl + "'" ;
			jsData.addAxis( JsChartDataV3.TITLE , scLbl );
		}
	}

	/**
	 * 【TAG】y軸を０から書き始まるかどうか[true/false]を指定します(beginAtZero[初期値:null(=false)])。
	 *
	 * @og.tag
	 * <del>ticks と同時には使用できません。</del>
	 * <del>初期値(null)は、０から書き始めます。</del>
	 * 初期値(null)は、false と同じで、最小データから書き始めます。
	 * options:scales:yAxes:ticks:beginAtZero → options:scales:y:beginAtZero の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param atZero y軸を０から書き始まるかどうか [true/false]
	 */
	public void setBeginAtZero( final String atZero ) {
		final String beginAtZero =  nval( getRequestParameter( atZero ),null );

		checkPara( beginAtZero, SET_BOOLEAN, "beginAtZero" );
		jsData.addAxis( "beginAtZero" , beginAtZero , NO_QUOTE );		// 数値(boolean)
	}

	/**
	 * 【TAG】y軸の最大、最小値から指定分スケールを大きくとる(grace[初期値:null])。
	 *
	 * @og.tag
	 * 最大値または最小値から指定した数値分、スケールを大きくとる。
	 * '20%' のように最大値(最小値)に対する割合で示すことも可。
	 * ここでは、割合を文字列で指定するのみとします。
	 *
	 * options:scales:y:grace の 要素の属性です。
	 *
	 * @og.rev 8.0.0.0 (2021/08/31) 新規追加
	 *
	 * @param size y軸を指定分スケールを大きくとる[初期値:null]
	 */
	public void setGrace( final String size ) {
		final String grace =  nval( getRequestParameter( size ),null );

		jsData.addAxis( "grace" , grace , USE_QUOTE );			// 文字
	}

	/**
	 * 【TAG】y軸の最大値を指定します(scaleTypeがlinearの場合に有効)。
	 *
	 * @og.tag
	 * options:scales:yAxes:ticks:max → options:scales:y:max の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param max メモリの最大値
	 */
	public void setMax( final String max ) {
		jsData.addAxis( "max" , nval( getRequestParameter( max ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】y軸の最小値を指定します(scaleTypeがlinearの場合に有効)。
	 *
	 * @og.tag
	 * options:scales:yAxes:ticks:max → options:scales:y:max の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param min メモリの最小値
	 */
	public void setMin( final String min ) {
		jsData.addAxis( "min" , nval( getRequestParameter( min ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】y軸のフォントの色を指定(ticks:color[初期値:自動])。
	 *
	 * @og.tag
	 * ticks と同時には使用できません。
	 * options:scales:yAxes:ticks:fontColor → options:scales:y:ticks:color の 要素の属性です。
	 *
	 * ColorMapの色コード(色,色番号,VIVID,PASTEL,V0～,P0～)が使えます。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 * @og.rev 7.0.1.3 (2018/11/12) 色情報を返すメソッドを集約します。
	 *
	 * @param fontColor y軸のフォントの色
	 */
	public void setFontColor( final String fontColor ) {
		final String col = nval( getRequestParameter( fontColor ),null );
		if( col != null ) {
			jsData.addTicks( "color" , ColorMap.getColorKey( col , col ) , USE_QUOTE );			// 文字
		}
	}

	/**
	 * 【TAG】y軸ｺｰﾙﾊﾞｯｸを指定します(ticks:callback)。
	 *
	 * @og.tag
	 * options:scales:y:ticks:callback: の 要素
	 * y軸のメモリ編集用スケールバックを設定します。
	 * callback="function(val,index){return val.toLocaleString() + '円';}"
	 * のように登録します。
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param callback y軸ｺｰﾙﾊﾞｯｸ
	 */
	public void setScaleCallback( final String callback ) {
		jsData.addTicks( "callback" , nval( getRequestParameter( callback ),null ) , NO_QUOTE );	// ファンクションは、クオートしない
	}

	/**
	 * 【TAG】y軸のメモリ幅を指定します(scaleTypeがlinearの場合に有効)(ticks:stepSize)。
	 *
	 * @og.tag
	 * options:scales:y:ticks:stepSize の 要素の属性です。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 *
	 * @param stepSize y軸のメモリ幅
	 */
	public void setStepSize( final String stepSize ) {
		jsData.addTicks( "stepSize" , nval( getRequestParameter( stepSize ),null ) , NO_QUOTE );		// 数値
	}

	/**
	 * 【TAG】gridのcolor属性( grid:{color:'red',} を生成)を設定します(初期値:null)。
	 *
	 * @og.tag
	 * options:scales:yAxes:gridLines:color → options:scales:y:grid:color の 要素の属性です。
	 * この設定と、gridLinesﾊﾟﾗﾒｰﾀ を同時に設定した場合の動作は、不定です。
	 * ※ 不定というのは、Tomcat上の属性の設定順で規定されるため、どちらの要素が使用されるのか、実装依存です。
	 *
	 * ColorMapの色コード(色,色番号,VIVID,PASTEL,V0～,P0～)が使えます。
	 *
	 * @og.rev 7.0.1.1 (2018/10/22) 属性の追加。
	 * @og.rev 7.0.1.3 (2018/11/12) 色情報を返すメソッドを集約します。
	 *
	 * @param gridColor y軸のフォントの色
	 */
	public void setGridColor( final String gridColor ) {
		final String col = nval( getRequestParameter( gridColor ),null );
		if( col != null ) {
			final String color = "color:'" + ColorMap.getColorKey( col , col ) + "'" ;
			jsData.addAxis( JsChartDataV3.GRID , color );
		}
	}

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

	/**
	 * 【TAG】その他data:datasetのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.tag
	 * その他data:datasetのｵﾌﾟｼｮﾝを追加します。
	 *
	 * @og.rev 7.0.1.2 (2018/11/04) 属性の追加。
	 *
	 * @param attri その他data:datasetのｵﾌﾟｼｮﾝ
	 */
	public void setOptDataset( final String attri ) {
		jsData.addAxis( JsChartDataV3.DATASET , nval( getRequestParameter( attri ),null ) );
	}

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

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

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

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

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
			.println( "VERSIION"			, VERSION	)
			.println( "JsChartDataV3"		, jsData	)
			.fixForm().toString();
	}
}
