001package org.opengion.hayabusa.taglib;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005import java.util.List;
006import java.util.concurrent.ConcurrentHashMap;
007import java.util.concurrent.ConcurrentMap;
008import java.util.regex.Matcher;
009import java.util.regex.Pattern;
010
011import org.opengion.hayabusa.common.HybsSystem;
012import org.opengion.hayabusa.common.HybsSystemException;
013import org.opengion.hayabusa.db.DBTableModel;
014import org.opengion.hayabusa.html.ViewForm;
015import org.opengion.hayabusa.html.ViewFormFactory;
016import org.opengion.hayabusa.html.ViewJsonParam;
017import org.opengion.hayabusa.io.JsChartData;
018import static org.opengion.fukurou.util.StringUtil.nval;
019
020/**
021 * JsChart は、JavascriptのjsChart用のスクリプトを出力するクラスです。
022 * 複数の JsChartData オブジェクトを合成することも、ここで行っています。
023 * ChartJSを利用しているため、標準属性以外の項目をセットする場合はoptionAttributesで行ってください。
024 * 例えばアニメーションをOFFにする場合はanimation:falseをセットします。
025 * 
026 * 出力されるスクリプトでは、idを指定しない場合はhybscanvas[tableId]が利用されます。
027 * 複数のグラフを同一画面で出力する場合はidかtableIdを変えてください。
028 * チャートオブジェクトはchart_[id]という名前で作成されるため、ajax等でコントロールが必要な場合は利用してください。
029 * 
030 * @og.formSample
031 * ●形式:<og:column chartType="…" ... />
032 * ●body:あり(EVAL_BODY_BUFFERED:BODYを評価し、{$#064;XXXX} を解析します)
033 * 
034 * ●Tag定義:
035 *  <og:jsChart
036 *      chartType       ○【TAG】チャートの種類を指定します。(必須)
037 *      id                【TAG】canvasタグのidを指定します。(初期値:hybscanvas)
038 *      height            【TAG】チャートの高さを指定します。(初期値:400)
039 *      width             【TAG】チャートの幅を指定します。(初期値:400)
040 *      labelColumn       【TAG】ラベルのカラム名を指定します。(表示名称)
041 *      title             【TAG】タイトルを指定します。
042 *      titlePosition     【TAG】タイトルの表示位置[top/right/bottom/left]を指定します。(初期値:top)
043 *      ylabel            【TAG】x軸のラベルを指定します。
044 *      xlabel            【TAG】y軸のラベルを指定します。
045 *      legendPosition    【TAG】凡例の表示位置[top/right/bottom/left]を指定します。(初期値:top)
046 *      legendDisplay     【TAG】凡例を表示するか[true/false]を指定します。
047 *      xscaleCallback    【TAG】x軸コールバックを指定します。
048 *      yscaleCallback    【TAG】y軸コールバックを指定します。
049 *      xscaleType        【TAG】x軸のスケールタイプ[category/time/linear]を指定します。(初期値:category)
050 *      xscaleTimeType    【TAG】x軸の型[string/int]を指定します。xscaleTypeにtimeを指定した場合に利用します。(初期値:string) 
051 *      xmax              【TAG】x軸の最大値を指定します。(xscaleTypeがlinearの場合に有効)
052 *      xmin              【TAG】x軸の最小値を指定します。(xscaleTypeがlinearの場合に有効)
053 *      xstepSize         【TAG】x軸のメモリ幅を指定します。(xscaleTypeがlinearの場合に有効)
054 *      timeUnit          【TAG】x軸のタイムの単位[year/quarter/month/week/day/hour/minute/second/millsecond]を指定します。(xscaleTypeがtimeの場合に有効。指定しない場合は自動)
055 *      timeUnitStepSize  【TAG】x軸のタイムの単位幅を指定します。(xscaleTypeがtimeの場合に有効)
056 *      timeSetFormat     【TAG】x軸の設定するタイムのフォーマットを指定します。(xscaleTypeがtimeの場合に有効)
057 *      timeLblFormat     【TAG】x軸の表示するタイムのフォーマットを指定します。(xscaleTypeがtimeの場合に有効)
058 *      timeMax           【TAG】x軸のタイムの最大値を指定します。(xscaleTypeがtimeの場合に有効)
059 *      timeMin           【TAG】x軸のタイムの最小値を指定します。(xscaleTypeがtimeの場合に有効)
060 *      yscaleType        【TAG】y軸のスケールタイプ[linear/category]を指定します。(初期値:linear)
061 *      ycategoryList     【TAG】y軸のメモリリストをカンマ区切りで指定します。(xscaleTypeがlinearの場合に有効)
062 *      max               【TAG】y軸の最大値を指定します。(xscaleTypeがlinearの場合に有効)
063 *      min               【TAG】y軸の最小値を指定します。(xscaleTypeがlinearの場合に有効)
064 *      stepSize          【TAG】y軸のメモリ幅を指定します。(xscaleTypeがlinearの場合に有効)
065 *      barWidthPer       【TAG】棒線の横幅を指定します。(初期値:0.8, typeがbar,horizontalBarの場合に有効)
066 *      onClick           【TAG】チャートクリック時のイベントを指定します。
067 *      tableid           【TAG】(通常使いません)sessionから所得する DBTableModelオブジェクトの ID
068 *      scope             【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
069 *      widthEventColumn  【TAG】横幅を動機に設定するカラムのIDを指定します。
070 *      heightEventColumn 【TAG】縦幅を動的に設定するカラムのIDを指定します。
071 *      minEventColumn    【TAG】minを動的に設定するカラムのIDを指定します。 
072 *      maxEventColumn    【TAG】maxを動的に設定するカラムのIDを指定します。 
073 *      optionAttributes  【TAG】その他オプションを指定します。
074 *  >   ... Body ...
075 *  </og:jsChart>
076 * ●使用例
077 *      <og:jsChart
078 *          chartType      = "bar"
079 *          labelColumn    = "LDATA"
080 *          id             = "canvasid"
081 *          height         = "500"
082 *          width          = "800"
083 *          labelColumn    = "LCLM"
084 *          title          = "タイトル"
085 *          titlePosition  = "bottom"
086 *          ylabel         = "給料"
087 *          xlabel         = "名称"
088 *          legendPosition = "right"
089 *          legendDisplay  = "true"
090 *          xsclaeCallback = "function(value){return value + ' 様';}"
091 *          ysclaeCallback = "function(value){return value.toLocaleString();}"
092 *          xscaleType     = "time"
093 *          max            = "1000000"
094 *          min            = "100000"
095 *          stepSize       = "10000"
096 *          barWidthPer    = "0.4"
097 *      >
098 *          <og:jsChartData ... />
099 *      </og:jsChart>
100 *      
101 * @og.group 画面表示
102 * 
103 * @version     5.9.17.2        2017/02/08
104 * @og.rev 5.9.19.0             2017/04/07      T.OTA 61200-170316-02   チャートサイズ・max・minの動的変更対応
105 * 
106 * @author      T.OTA
107 * @since       JDK7.0
108 *
109 */
110public class JsChartTag extends CommonTagSupport {
111        //* このプログラムのVERSION文字列を設定します。{@value} */
112        private static final String             VERSION                         = "5.9.17.2 (2017/02/07)";
113        private static final long               serialVersionUID        = 1631345224410617801L;
114        /** chartType 引数に渡す事の出来る アクション 折れ線 **/
115        public static final String              CTYPE_LINE                      = "line";
116        /** chartType 引数に渡す事の出来る アクション 棒線 **/
117        public static final String              CTYPE_BAR                       = "bar";
118        /** chartType 引数に渡す事の出来る アクション 横棒線 **/
119        public static final String              CTYPE_HBAR                      = "horizontalBar";
120        /** chartType 引数に渡す事の出来る アクション レイダー **/
121        public static final String              CTYPE_RADAR                     = "radar";
122        /** chartType 引数に渡す事の出来る アクション ポーラエリア **/
123        public static final String              CTYPE_PA                        = "polarArea";
124        /** chartType 引数に渡す事の出来る アクション 円 **/
125        public static final String              CTYPE_PIE                       = "pie";
126        /** chartType 引数に渡す事の出来る アクション ドーナツ **/
127        public static final String              CTYPE_DOUGHNUT          = "doughnut";
128        /** chartType 引数に渡す事の出来る アクション リスト */
129        private static final String[]   CTYPE_LIST                      = new String[] { CTYPE_LINE, CTYPE_BAR, CTYPE_HBAR, CTYPE_RADAR, CTYPE_PA, CTYPE_PIE, CTYPE_DOUGHNUT };
130        /** chartType が円形のリスト */
131        private static final String[]   CTYPE_CI                        = new String[] { CTYPE_RADAR, CTYPE_PA, CTYPE_PIE, CTYPE_DOUGHNUT };
132        private static final String[]   TYPE_POSITION           = new String[] { "top", "right", "bottom", "left" };
133        private static final String[]   TYPE_TIMEUNIT           = new String[] { "year", "quarter", "month", "week", "day", "hour", "minute", "second", "millsecond" };
134        private static final String[]   TYPE_XSCALE                     = new String[] { "category", "time", "linear" };
135        private static final String[]   TYPE_YSCALE                     = new String[] { "linear", "category" };
136        private static final String[]   TYPE_BOOLEAN            = new String[] { "true", "false" };
137        
138        private static final String     CANVAS_NAME                     = "hybscanvas";
139        
140        // 変数宣言
141        private String                                  id                                      = null;                                                                                                                                                                         // canvasタグのid
142        private String                                  height                          = "400";                                                                                                                                                                                                // canvasタグのheight
143        private String                                  width                           = "400";                                                                                                                                                                                                // canvasタグのwidth
144        private String                                  chartType                       = null;                                                                                                                                                                                         // チャートタイプ
145        private String                                  labelColumn                     = null;                                                                                                                                                                                         // ラベルカラム
146        private String                                  ylabel                          = null;                                                                                                                                                                                         // y軸ラベル
147        private String                                  xlabel                          = null;                                                                                                                                                                                         // x軸ラベル
148//      private String                                  scope                           = "session";                                                                                                                                                                                    // スコープ
149        private String                                  tableId                         = HybsSystem.TBL_MDL_KEY;                                                                                                                                                               // テーブルid
150        private List<JsChartData>         jsChartData                     = null;                                                                                                                                                                                         // jsChartDataのリスト
151        private transient DBTableModel  table                           = null;                                                                                                                                                                                         // DBTableModelクラス
152        private String                                  onClick                         = null;                                                                                                                                                                                         // クリックイベント
153        private String                                  title                           = null;                                                                                                                                                                                         // タイトル
154        private String                                  titlePosition           = null;                                                                                                                                                                                         // タイトル位置
155        private String                                  legendPosition          = null;                                                                                                                                                                                         // 凡例位置
156        private String                                  legendDisplay           = null;                                                                                                                                                                                         // 凡例表示フラグ
157        private String                                  barWidthPer                     = null;                                                                                                                                                                                         // 棒線の横幅(パーセント)
158        private String                                  xscaleCallback          = null;                                                                                                                                                                                         // x軸のメモリ編集用コールバック
159        private String                                  yscaleCallback          = null;                                                                                                                                                                                         // y軸のメモリ編集用コールバック
160        private String                                  xscaleType                      = null;                                                                                                                                                                                         // x軸のスケールタイプ
161        private String                                  xmax                            = null;                                                                                                                                                                                         // x軸の最大値(リニアスケール用)
162        private String                                  xmin                            = null;                                                                                                                                                                                         // x軸の最小値(リニアスケール用)
163        private String                                  xstepSize                       = null;                                                                                                                                                                                         // x軸のメモリ幅(リニアスケール用)
164        private String                                  yscaleType                      = null;                                                                                                                                                                                         // y軸のスケールタイプ
165        private String                                  ycategoryList           = null;                                                                                                                                                                                         // y軸のカテゴリーリスト(カテゴリースケール用)
166        private String                                  max                                     = null;                                                                                                                                                                                         // y軸の最大値(リニアスケール用)
167        private String                                  min                                     = null;                                                                                                                                                                                         // y軸の最小値(リニアスケール用)
168        private String                                  stepSize                        = null;                                                                                                                                                                                         // y軸のメモリ幅(リニアスケール用)
169        private String                                  timeUnit                        = null;                                                                                                                                                                                         // 時間の単位(タイムスケール用)
170        private String                                  timeUnitStepSize        = null;                                                                                                                                                                                         // 時間のメモリ幅(タイムスケール用)
171        private String                                  timeSetFormat           = null;                                                                                                                                                                                         // 時間の入力フォーマット(タイムスケール用)
172        private String                                  timeLblFormat           = null;                                                                                                                                                                                         // 時間の表示フォーマット(タイムスケール用)
173        private String                                  timeMax                         = null;                                                                                                                                                                                         // 最大の時間(タイムスケール用)
174        private String                                  timeMin                         = null;                                                                                                                                                                                         // 最小の時間(タイムスケール用)
175        private String                                  widthEventColumn        = null;                                                                                                                                                                                         // 横幅の動的参照カラム   2017/03/28 ADD
176        private String                                  heightEventColumn       = null;                                                                                                                                                                                         // 縦幅の動的参照カラム   2017/03/28 ADD
177        private String                                  minEventColumn          = null;                                                                                                                                                                                         // 最小値の動的参照カラム  2017/03/28 ADD
178        private String                                  maxEventColumn          = null;                                                                                                                                                                                         // 最大値の動的参照カラム  2017/03/28 ADD
179        private boolean useRenderer                     ;                                                       // 5.9.20.1 (2017/05/12) useRenderer 追加(6.7.7.0)
180        private String                                  optionAttributes        = null;                                                                                                                                                                                         // オプション
181        
182        // 5.10.3.2 (2018/09/28)
183        private static final String TYPE_STRING                 = "string";
184        private static final String TYPE_INT                    = "int";
185        private static final String[] XSCALEDATATYPE_LIST = new String[] {TYPE_STRING, TYPE_INT};
186        private String                                  xscaleTimeType          = TYPE_STRING;
187
188        /**
189         * タグリブオブジェクトをリリースします。
190         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
191         * 
192         * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02  チャートサイズ・max・minの動的変更対応
193         * @og.rev 5.9.20.1 (2017/05/12) useRenderer追加
194         * @og.rev 5.10.3.2 (2018/09/28) xscaleTimeType追加
195         */
196        @Override
197        protected void release2() {
198                super.release2();
199                id = null;
200                height = "400";
201                width = "400";
202                chartType = null;
203                labelColumn = null;
204//              scope = "session";
205                tableId = HybsSystem.TBL_MDL_KEY;
206                jsChartData = null;
207                table = null;
208                optionAttributes = null;
209                onClick = null;
210                title = null;
211                titlePosition = null;
212                xlabel = null;
213                ylabel = null;
214                legendPosition = null;
215                legendDisplay = null;
216                barWidthPer = null;
217                xscaleCallback = null;
218                yscaleCallback = null;
219                xscaleType = null;
220                yscaleType = null;
221                ycategoryList = null;
222                max = null;
223                min = null;
224                stepSize = null;
225                timeUnit = null;
226                timeUnitStepSize = null;
227                timeSetFormat = null;
228                timeLblFormat = null;
229                timeMax = null;
230                timeMin = null;
231                xmax = null;
232                xmin = null;
233                xstepSize = null;
234                widthEventColumn = null;                // 5.9.19.0     
235                heightEventColumn = null;               // 5.9.19.0     
236                maxEventColumn = null;                  // 5.9.19.0     
237                minEventColumn = null;                  // 5.9.19.0     
238                useRenderer                     = false;        // 5.9.20.1 (2017/05/12) useRenderer 追加(6.7.9.0)
239                xscaleTimeType = TYPE_STRING;   // 5.10.3.2 (2018/09/28)
240        }
241
242        /**
243         * Taglibの開始タグが見つかった時に処理する doStartTag() を オーバーライドします。
244         * 
245         * @og.rev 5.9.20.1 (2017/05/12) タグの使用を決める共通属性の追加(6.7.5.0)
246         * 
247         * @return 後続処理の指示
248         */
249        @Override
250        public int doStartTag() {
251                if( !useTag() ) { return SKIP_BODY ; }          // 5.9.20.1 (2017/05/12)
252                
253                // チェック処理の実行
254                checkData();
255
256//              // スコープの設定
257//              super.setScope( scope );
258
259                // テーブル情報の取得
260                table = (DBTableModel) getObject( tableId );
261
262                return EVAL_BODY_BUFFERED; // Bodyを評価する
263        }
264
265        /**
266         * チェック処理
267         */
268        private void checkData() {
269                // xscaleTypeに「linear」、yscaleTypeに「category」を指定した場合は、エラー
270                if( "linear".equals( xscaleType ) && "category".equals( yscaleType ) ) {
271                        StringBuilder errMsg = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
272                        errMsg.append( "指定のスケールタイプの組み合わせは実行できません。" );
273                        errMsg.append( HybsSystem.CR );
274                        errMsg.append( "xscaleType:" ).append( xscaleType ).append( " yscaleType:" ).append( yscaleType );
275                        throw new HybsSystemException( errMsg.toString() );
276                }
277        }
278
279        /**
280         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
281         * 
282         * @return 後続処理の指示
283         */
284        @Override
285        public int doEndTag() {
286                debugPrint();
287
288                id = (id==null ? CANVAS_NAME + tableId : id );  // id指定なしの場合はCANVAS_NAME+tableId
289                
290                // jsChart出力
291                jspPrint( jsChartOutput() );
292
293                return EVAL_PAGE;
294        }
295
296        /**
297         * jsChart出力用
298         * jsChartTag と jsChartData を使用して、jsChart情報を出力します。
299         * 
300         * @og.rev 5.9.19.0 (2017/04/07) T.OTA 61200-170316-02  チャートサイズ・max・minの動的変更対応
301         * @og.rev 5.9.20.1 (2017/05/12) useRenderer対応
302         * @og.rev 5.9.27.0     2017/12/01      T.OTA 61200-170831-04   max,minの小数点対応 
303         * @og.rev 5.10.3.2 (2018/09/28) のxscaleType対応
304         * 
305         * @return jsChert用文字列
306         */
307        private String jsChartOutput() {
308                StringBuilder rtn = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
309                
310                // 各JavaScriptの変数名
311                String qd = "qd_" + id; //queryData
312                String cd = "cd_" + id; //chartData
313                String myChart = "chart_"+id;
314                String lblClm = labelColumn + id;
315                
316
317                // JSON形式でテーブル情報を取得
318                ViewForm form = ViewFormFactory.newInstance( "JSON" );
319                form.init( table );
320                
321                // 5.9.20.1 (2017/05/12) form にパラメータMapを与えるようにする
322                final ConcurrentMap<String,String> cMap = new ConcurrentHashMap<String,String>();
323                if( useRenderer ) {
324                        cMap.put( ViewJsonParam.JSON_RENDERER_KEY , "true" );
325                }
326                if( !cMap.isEmpty() ) {
327                        form.setParam( cMap );
328                }
329
330                // canvasタグの設定
331                rtn.append( "<canvas class=\"").append( CANVAS_NAME).append( "\" id=\"" ).append( id ).append( "\" width=\"" ).append( width ).append( "\" height=\"" ).append( height ).append( "\"><!-- --></canvas>" );
332
333                rtn.append( "<script>" );
334                // query情報の取得(JSON)
335                rtn.append( "var ").append( qd ).append(" = " ).append( form.create() );
336
337                // jsChartDataタグの変数宣言
338                for( int i = 0; i < jsChartData.size(); i++ ) {
339                        rtn.append( " var " ).append( jsChartData.get( i ).getChartColumn() ).append( " = [];" );
340                }
341                rtn.append( "var " ).append( lblClm ).append( " = [];" );
342
343                // query情報をjsChartDataの変数に入れ替え 
344                rtn.append( "for(var i=0; i < ").append( qd ).append( ".DATA.length; i++){" );
345                for( int i = 0; i < jsChartData.size(); i++ ) {
346                        String chartColumn = jsChartData.get( i ).getChartColumn();
347
348                        // x軸がlinearスケールの場合
349                        if( "linear".equals( xscaleType ) ) {
350                                // {x:ラベル, y:値}の形式で値を設定
351                                rtn.append( chartColumn ).append( "[i] = {x:").append(qd).append(".DATA[i]." ).append( labelColumn ).append( ",y:").append(qd).append(".DATA[i]." ).append( chartColumn ).append( "};" );
352                        }
353                        else {
354                                // その他は値を設定
355                                rtn.append( chartColumn ).append( "[i] = ").append(qd).append( ".DATA[i]." ).append( chartColumn ).append( ";" );
356                        }
357                }
358                // 5.10.3.2 (2018/09/28)
359//              rtn.append( lblClm ).append( "[i] = ").append( qd ).append( ".DATA[i]." ).append( labelColumn ).append( ";" );
360                rtn.append( lblClm ).append( "[i] = ");
361                // xscaleTimeTypeがint場合は数値型を設定
362                if("time".equals(this.xscaleType) && TYPE_INT.equals(this.xscaleTimeType)) {
363                        rtn.append("Number(");
364                }
365                rtn.append( qd ).append( ".DATA[i]." ).append( labelColumn );
366                // xscaleTimeTypeがint場合は数値型を設定
367                if("time".equals(this.xscaleType) && TYPE_INT.equals(this.xscaleTimeType)) {
368                        rtn.append(")");
369                }
370                rtn.append( ";" );
371
372
373                rtn.append( "}" );
374
375                // y軸にカテゴリースケールを設定した場合
376                if( "category".equals( yscaleType ) ) {
377                        rtn.append( "var ycateList = [];" );
378                        if( ycategoryList != null && ycategoryList.length() > 0 ) {
379                                // 「,」を「','」に変換して設定。(,前後の半角スペースは除去する)
380                                String regex = " *, *";
381                                Pattern p = Pattern.compile( regex );
382
383                                Matcher m = p.matcher( ycategoryList );
384                                // y軸カテゴリーリストの設定
385                                rtn.append( "ycateList = ['" ).append( m.replaceAll( "','" ) ).append( "'];" );
386                        }
387                }
388
389                // jsChartDataの設定
390                rtn.append( "var ").append( cd ).append(" = {" );
391                rtn.append( "labels:" ).append( lblClm );
392                // y軸にカテゴリースケールを設定した場合
393                if( "category".equals( yscaleType ) ) {
394                        rtn.append( ",yLabels:ycateList" );
395                }
396                rtn.append( ",datasets:[" );
397                for( int i = 0; i < jsChartData.size(); i++ ) {
398                        if( i != 0 ) {
399                                rtn.append( "," );
400                        }
401                        rtn.append( jsChartData.get( i ).getParameter() );
402                }
403                rtn.append( "]};" );
404
405                // jsChartの生成
406                rtn.append( "var ").append( myChart ).append(" = new Chart(" ).append( id ).append( ",{" );
407                rtn.append( "type:'" ).append( chartType ).append( "'" );
408                rtn.append( ",data:").append(cd);
409                rtn.append( ",options:{" );
410                rtn.append( "responsive:false" ); // レスポンシブ OFF
411//              rtn.append( ",animation:false" ); // アニメーション OFF
412
413                // クリックイベントの設定
414                if( onClick != null && onClick.length() > 0 ) {
415                        rtn.append( ",onClick:function(event,obj){" ).append( onClick ).append( "}" );
416                }
417
418                // タイトル属性の設定
419                if( title != null && title.length() > 0 ) {
420                        rtn.append( ",title:{" );
421                        rtn.append( "display:true" );
422                        setProp( rtn, ",text:'", title, "'" );
423                        setProp( rtn, ",position:'", titlePosition, "'" );
424                        rtn.append( "}" );
425                }
426
427                // メモリ属性の設定
428                rtn.append( ",legend:{" );
429                setProp( rtn, "display:", legendDisplay, "," );
430                setProp( rtn, "position:'", legendPosition, "'" );
431                rtn.append( "}" );
432
433                // chartTypeの円形チェック
434                List<String> list = Arrays.asList( CTYPE_CI );
435                if( list.contains( chartType ) ) {
436                        // 円形の場合はscale属性に値を設定
437                        rtn.append( ",scale: {ticks:{beginAtZero:true" );
438                        setProp( rtn, ",max:", max );
439                        setProp( rtn, ",min:", min );
440                        setProp( rtn, ",stepSize:", stepSize );
441                        rtn.append( "}}" );
442                }
443                else {
444                        // 円形以外の場合はscales属性に設定
445                        rtn.append( ",scales:{" );
446                        if( CTYPE_HBAR.equals( chartType ) ) {
447                                // 横棒線の場合はx軸の設定
448                                rtn.append( "xAxes" );
449                        }
450                        else {
451                                // それ以外はy軸の設定
452                                rtn.append( "yAxes" );
453                        }
454                        rtn.append( ":[{" );
455                        setProp( rtn, "type:'", yscaleType, "'," );
456                        // y軸にカテゴリースケールを設定した場合
457                        if( "category".equals( yscaleType )) {
458                                rtn.append( "position:'left'," );
459                        }
460                        if(ylabel != null && ylabel.length() > 0 ){
461                                rtn.append( "scaleLabel: {" );
462                                rtn.append( "display: true," );
463                                rtn.append( "labelString: '").append( ylabel ).append("'");
464                                rtn.append( "}," );
465                        }
466                        rtn.append( "ticks:{beginAtZero:true" );
467                        setProp( rtn, ",max:", max );
468                        setProp( rtn, ",min:", min );
469                        setProp( rtn, ",stepSize:", stepSize );
470                        setProp( rtn, ",callback:", yscaleCallback );
471                        rtn.append( "}}]," );
472
473                        if( CTYPE_HBAR.equals( chartType ) ) {
474                                // 横棒線の場合はy軸の設定
475                                rtn.append( "yAxes" );
476                        }
477                        else {
478                                // それ以外はx軸の設定
479                                rtn.append( "xAxes" );
480                        }
481                        rtn.append( ":[{" );
482                        setProp( rtn, "type:'", xscaleType, "'," );
483                        setProp( rtn, "categoryPercentage:", barWidthPer, "," );
484                        // x軸にリニアスケールを設定した場合
485                        if( "linear".equals( xscaleType ) ) {
486                                rtn.append( "position:'bottom'," );
487                        }
488                        // チャートタイプが横棒線の場合
489                        if(  CTYPE_HBAR.equals( chartType )){
490                                rtn.append( "position:'left'," );
491                        }
492                        
493                        if(xlabel != null && xlabel.length() > 0 ){
494                                rtn.append( "scaleLabel: {" );
495                                rtn.append( "display: true," );
496                                rtn.append( "labelString: '").append( xlabel ).append("'");
497                                rtn.append( "}," );
498                        }
499                        rtn.append( "time:{" );
500                        setProp( rtn, "format:'", timeSetFormat, "'," );
501                        // timeLblFormatが指定されている場合、全てのdisplayFormatsにtimeLblFormatを設定する
502                        if( timeLblFormat != null && timeLblFormat.length() > 0 ) {
503                                rtn.append( "displayFormats:{year:'" ).append( timeLblFormat ).append( "',quarter:'" ).append( timeLblFormat ).append( "',month:'" ).append( timeLblFormat ).append( "',week:'" ).append( timeLblFormat ).append( "',day:'" ).append( timeLblFormat ).append( "',hour:'" ).append( "',minute:'" ).append( timeLblFormat ).append( "',second:'" ).append( timeLblFormat ).append( "',millisecond:'" ).append( "'}," );
504                        }
505                        setProp( rtn, "max:'", timeMax, "'," );
506                        setProp( rtn, "min:'", timeMin, "'," );
507                        setProp( rtn, "unit:'", timeUnit, "'," );
508                        setProp( rtn, "unitStepSize:", timeUnitStepSize );
509                        rtn.append( "}," );
510
511                        rtn.append( "ticks:{" );
512                        setProp( rtn, "callback:", xscaleCallback, "," );
513                        // x軸にリニアスケールを設定した場合
514                        if( "linear".equals( xscaleType ) ) {
515                                rtn.append( "beginAtZero:true," );
516                                setProp( rtn, "max:", xmax, "," );
517                                setProp( rtn, "min:", xmin, "," );
518                                setProp( rtn, "stepSize:", xstepSize );
519                        }
520                        rtn.append( "}}]" );
521
522                        rtn.append( "}" );
523                }
524                setProp( rtn, ",", optionAttributes );
525
526                rtn.append( "}});" );
527                
528                // イベント設定用 5.9.19.0
529                // 5.9.27.0 (2017/12/01) MODIFY イベントにkeyupを追加
530                // widthEventColumn設定
531                if( widthEventColumn != null && widthEventColumn.length() > 0){
532                        rtn.append( "$(document).delegate('#").append( widthEventColumn ).append( "','mouseup keyup',function(){")
533                                .append( "var width = $(this).val();")
534                                .append( "$('#" ).append( id ).append( "').attr('width',width);")
535                                .append( myChart ).append( ".chart.width=width;")
536                                .append( myChart ).append( ".update();")
537                                .append( "} );")
538                                .append( "$(function( ){")
539                                .append( "var chartWidth = $('#" ).append( id ).append("').attr('width');")
540                                .append( "$('#").append( widthEventColumn ).append( "').val(chartWidth);")              // 初期値を設定
541                                .append( "});");
542                }
543                // heightEventColumn設定
544                if( heightEventColumn != null && heightEventColumn.length() > 0){
545                        rtn.append( "$(document).delegate('#").append( heightEventColumn ).append( "','mouseup keyup',function(){")
546                                .append( "var height = $(this).val();")
547                                .append( "$('#" ).append( id ).append( "').attr('height',height);")
548                                .append( myChart ).append( ".chart.height=height;")
549                                .append( myChart ).append( ".update();")
550                                .append( "} );")
551                                .append( "$(function( ){")
552                                .append( "var chartHeight = $('#" ).append( id ).append("').attr('height');")
553                                .append( "$('#").append( heightEventColumn ).append( "').val(chartHeight);")    // 初期値を設定
554                                .append( "});");
555                }
556                // minEventColumn設定
557                if( minEventColumn != null && minEventColumn.length() > 0){
558                        rtn.append( "$(document).delegate('#").append( minEventColumn ).append( "','mouseup keyup',function(){")
559                                // 5.9.27.0 (2017/12/01) MODIFY IntからFloat型に変更
560                                // .append( "var min = parseInt($(this).val());")
561                                .append( "var min = parseFloat($(this).val());")
562                                .append( myChart ).append( ".options.scales.yAxes[0].ticks.min = min;")
563                                .append( myChart ).append( ".update();")
564                                .append( "} );")
565                                .append( "$(function( ){")
566                                .append( "var chartMin = ").append( myChart ).append( ".scales['y-axis-0'].min;")
567                                .append( "$('#").append( minEventColumn ).append( "').val(chartMin);")                  // 初期値を設定
568                                .append( "});");
569                }
570                // maxEventColumn設定
571                if( maxEventColumn != null && maxEventColumn.length() > 0){
572                        rtn.append( "$(document).delegate('#").append( maxEventColumn ).append( "','mouseup keyup',function(){")
573                                // 5.9.27.0 (2017/12/01) MODIFY IntからFloat型に変更
574                                // .append( "var max = parseInt($(this).val());")
575                                .append( "var max = parseFloat($(this).val());")
576                                .append( myChart ).append( ".options.scales.yAxes[0].ticks.max = max;")
577                                .append( myChart ).append( ".update();")
578                                .append( "} );")
579                                .append( "$(function(){")               
580                                .append( "var chartMax = ").append( myChart ).append( ".scales['y-axis-0'].max;")
581                                .append( "$('#").append( maxEventColumn ).append( "').val(chartMax);")                  // 初期値を設定
582                                .append("});");
583                }
584                
585                rtn.append( "</script>" );
586
587                return rtn.toString();
588        }
589
590        /**
591         * setに値が存在する場合,
592         * sbにstr + setの形で値を追加する。
593         * 
594         * @param sb
595         * @param str
596         * @param set
597         */
598        private void setProp( StringBuilder sb, String str, String set ) {
599                if( set != null && set.length() > 0 ) {
600                        sb.append( str ).append( set );
601                }
602        }
603
604        /**
605         * setに値が存在する場合,
606         * sbにstr + set + endの形で値を追加する。
607         * 
608         * @param sb
609         * @param str
610         * @param set
611         * @param end
612         */
613        private void setProp( StringBuilder sb, String str, String set, String end ) {
614                if( set != null && set.length() > 0 ) {
615                        sb.append( str ).append( set ).append( end );
616                }
617        }
618
619        /**
620         * id を設定します。
621         * canvasタグのidに設定します。
622         * 
623         * @param id
624         */
625        public void setId( String id ) {
626                String temp = getRequestParameter( id );
627                if( temp != null && temp.length() > 0 ) {
628                        this.id = temp;
629                }
630        }
631
632        /**
633         * 高さ を設定します。
634         * canvasタグの高さに設定します。
635         * 
636         * @param hei
637         */
638        public void setHeight( final String hei ) {
639                String temp = getRequestParameter( hei );
640                if( temp != null && temp.length() > 0 ) {
641                        height = temp;
642                }
643        }
644
645        /**
646         * 横幅 を設定します。
647         * canvasタグの横幅を設定します。
648         * 
649         * @param wid
650         */
651        public void setWidth( final String wid ) {
652                String temp = getRequestParameter( wid );
653                if( wid != null && wid.length() > 0 ) {
654                        width = temp;
655                }
656        }
657
658        /**
659         * チャートタイプ を設定します。
660         * 
661         * @param cType
662         */
663        public void setChartType( final String cType ) {
664                chartType = getRequestParameter( cType );
665
666                if( chartType != null && !check( chartType, CTYPE_LIST ) ) {
667                        StringBuilder errMsg = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
668                        errMsg.append( "指定のチャートタイプは実行できません。" );
669                        errMsg.append( HybsSystem.CR );
670                        errMsg.append( "chartType=[" ).append( chartType ).append( "]" );
671                        errMsg.append( HybsSystem.CR );
672                        for( int i = 0; i < CTYPE_LIST.length; i++ ) {
673                                errMsg.append( " | " );
674                                errMsg.append( CTYPE_LIST[i] );
675                        }
676                        throw new HybsSystemException( errMsg.toString() );
677                }
678        }
679
680        /**
681         * ラベルカラムを指定します。
682         * 
683         * @param labelColumn ラベルカラム
684         */
685        public void setLabelColumn( String labelColumn ) {
686                this.labelColumn = getRequestParameter( labelColumn );
687        }
688
689//      /**
690//       * テーブルスコープを指定します。
691//       * 
692//       * @param scope テーブルスコープ
693//       */
694//      public void setScope( String scope ) {
695//              this.scope = getRequestParameter( scope );
696//      }
697
698        /**
699         * テーブルIDを指定します。
700         * 
701         * @param tableId テーブルID
702         */
703        public void setTableId( String tableId ) {
704                this.tableId = getRequestParameter( tableId );
705        }
706
707        /**
708         * チャートクリック時のイベントを指定します。
709         * 下記の値が引数として渡されます。
710         * 
711         * event:イベント情報 
712         * obj:クリックされたオブジェクトの情報
713         * 
714         * @param onClick
715         */
716        public void setOnClick( String onClick ) {
717                this.onClick = getRequestParameter( onClick );
718        }
719
720        /**
721         * メモリの最大値を指定します。
722         * 
723         * @param max メモリの最大値
724         */
725        public void setMax( String max ) {
726                this.max = getRequestParameter( max );
727        }
728
729        /**
730         * メモリの最小値を指定します。
731         * 
732         * @param min メモリの最小値
733         */
734        public void setMin( String min ) {
735                this.min = getRequestParameter( min );
736        }
737
738        /**
739         * メモリ幅を設定します。
740         * 
741         * @param stepSize
742         */
743        public void setStepSize( String stepSize ) {
744                this.stepSize = getRequestParameter( stepSize );
745        }
746
747        /**
748         * 時間の単位を設定します。
749         * 
750         * @param timeUnit
751         */
752        public void setTimeUnit( String timeUnit ) {
753                this.timeUnit = getRequestParameter( timeUnit );
754
755                checkPara( this.timeUnit, TYPE_TIMEUNIT, "timeUnit" );
756        }
757
758        /**
759         * 時間のメモリ幅を設定します。
760         * 
761         * @param timeUnitStepSize
762         */
763        public void setTimeUnitStepSize( String timeUnitStepSize ) {
764                this.timeUnitStepSize = getRequestParameter( timeUnitStepSize );
765        }
766
767        /**
768         * 時間の入力フォーマットを設定します。
769         * 
770         * @param timeSetFormat
771         */
772        public void setTimeSetFormat( String timeSetFormat ) {
773                this.timeSetFormat = getRequestParameter( timeSetFormat );
774        }
775
776        /**
777         * 時間の表示フォーマットを設定します。
778         * 
779         * @param timeLblFormat
780         */
781        public void setTimeLblFormat( String timeLblFormat ) {
782                this.timeLblFormat = getRequestParameter( timeLblFormat );
783        }
784
785        /**
786         * 時間の最大値を設定します。
787         * 
788         * @param timeMax
789         */
790        public void setTimeMax( String timeMax ) {
791                this.timeMax = getRequestParameter( timeMax );
792        }
793
794        /**
795         * 時間の最小値を設定します。
796         * 
797         * @param timeMin
798         */
799        public void setTimeMin( String timeMin ) {
800                this.timeMin = getRequestParameter( timeMin );
801        }
802
803        /**
804         * タイトルを設定します。
805         * 
806         * @param title
807         */
808        public void setTitle( String title ) {
809                this.title = getRequestParameter( title );
810        }
811
812        /**
813         * タイトル位置を設定します。
814         * 
815         * @param titlePosition
816         */
817        public void setTitlePosition( String titlePosition ) {
818                this.titlePosition = getRequestParameter( titlePosition );
819
820                checkPara( this.titlePosition, TYPE_POSITION, "titlePosition" );
821        }
822
823        /**
824         * 凡例位置を設定します。
825         * 
826         * @param legendPosition
827         */
828        public void setLegendPosition( String legendPosition ) {
829                this.legendPosition = getRequestParameter( legendPosition );
830
831                checkPara( this.legendPosition, TYPE_POSITION, "legendPosition" );
832        }
833
834        /**
835         * 凡例の表示制御を設定します。
836         * 
837         * @param legendDisplay
838         */
839        public void setLegendDisplay( String legendDisplay ) {
840                this.legendDisplay = getRequestParameter( legendDisplay );
841
842                checkPara( this.legendDisplay, TYPE_BOOLEAN, "legendDisplay" );
843        }
844
845        /**
846         * x軸のメモリ編集用スケールバックを設定します。
847         * 
848         * @param xscaleCallback
849         */
850        public void setXscaleCallback( String xscaleCallback ) {
851                this.xscaleCallback = getRequestParameter( xscaleCallback );
852        }
853
854        /**
855         * y軸のメモリ編集用スケールバックを設定します。
856         * 
857         * @param yscaleCallback
858         */
859        public void setYscaleCallback( String yscaleCallback ) {
860                this.yscaleCallback = getRequestParameter( yscaleCallback );
861        }
862
863        /**
864         * x軸のスケールタイプを設定します。
865         * 
866         * @og.tag
867         * timeとした場合はxscaleTimeTypeの設定も確認してください。
868         * 
869         * @param xscaleType
870         */
871        public void setXscaleType( String xscaleType ) {
872                this.xscaleType = getRequestParameter( xscaleType );
873
874                checkPara( this.xscaleType, TYPE_XSCALE, "xscaleType" );
875        }
876
877        /**
878         * y軸のスケールタイプを設定します。
879         * 
880         * @param yscaleType
881         */
882        public void setYscaleType( String yscaleType ) {
883                this.yscaleType = getRequestParameter( yscaleType );
884
885                checkPara( this.yscaleType, TYPE_YSCALE, "yscaleType" );
886        }
887
888        /**
889         * y軸のカテゴリー一覧を設定します。
890         * 
891         * @param ycategoryList
892         */
893        public void setYcategoryList( String ycategoryList ) {
894                this.ycategoryList = getRequestParameter( ycategoryList );
895        }
896
897        /**
898         * x軸の最大値を設定します。
899         * 
900         * @param xmax
901         */
902        public void setXmax( String xmax ) {
903                this.xmax = getRequestParameter( xmax );
904        }
905
906        /**
907         * x軸の最小値を設定します。
908         * 
909         * @param xmin
910         */
911        public void setXmin( String xmin ) {
912                this.xmin = getRequestParameter( xmin );
913        }
914
915        /**
916         * x軸のメモリ幅を設定します。
917         * 
918         * @param xstepSize
919         */
920        public void setXstepSize( String xstepSize ) {
921                this.xstepSize = getRequestParameter( xstepSize );
922        }
923
924        /**
925         * 棒線の横幅を設定します。
926         * 
927         * @param barWidthPer
928         */
929        public void setBarWidthPer( String barWidthPer ) {
930                this.barWidthPer = getRequestParameter( barWidthPer );
931        }
932
933        /**
934         * y軸のラベルを設定します。
935         * 
936         * @param ylabel
937         */
938        public void setYlabel( String ylabel ) {
939                this.ylabel = getRequestParameter( ylabel );
940        }
941
942        /**
943         * x軸のラベルを設定します。
944         * 
945         * @param xlabel
946         */
947        public void setXlabel( String xlabel ) {
948                this.xlabel = getRequestParameter( xlabel );
949        }
950        /**
951         * 横幅の動的設定カラムを設定します。
952         * 
953         * @og.rev 5.9.19.0 (2017/04/07) 追加
954         * @param widthEventColumn
955         */
956        public void setWidthEventColumn( String widthEventColumn ) {
957                this.widthEventColumn = getRequestParameter( widthEventColumn );
958        }
959        
960        /**
961         * 縦幅の動的設定カラムを設定します。
962         * 
963         * @og.rev 5.9.19.0 (2017/04/07) 追加
964         * @param heightEventColumn
965         */
966        public void setHeightEventColumn( String heightEventColumn ) {
967                this.heightEventColumn = getRequestParameter( heightEventColumn );
968        }
969        
970        /**
971         * minの動的設定カラムを設定します。
972         * 
973         * @og.rev 5.9.19.0 (2017/04/07) 追加
974         * @param minEventColumn
975         */
976        public void setMinEventColumn( String minEventColumn ) {
977                this.minEventColumn = getRequestParameter( minEventColumn );
978        }
979        
980        /**
981         * maxの動的設定カラムを設定します。
982         * 
983         * @og.rev 5.9.19.0 (2017/04/07) 追加
984         * @param maxEventColumn
985         */
986        public void setMaxEventColumn( String maxEventColumn ) {
987                this.maxEventColumn = getRequestParameter( maxEventColumn );
988        }
989        
990        /**
991         * 【TAG】JSON出力で、値出力にレンデラを利用するかどうかを指定します。
992         *
993         * @og.tag
994         * JSONのデータのレンデラー変換を行うかどうか。
995         * 指定しない場合は使用しない(false)です。
996         * 
997         * @og.rev 5.9.20.1 (2017/05/12) useRenderer 追加(6.7.9.0)
998         *
999         * @param       usernd レンデラーを利用するかどうか
1000         */
1001        public void setUseRenderer( final String usernd ) {
1002                this.useRenderer = nval( getRequestParameter( usernd ) , this.useRenderer );
1003        }
1004
1005        /**
1006         * 【TAG】オプション情報を指定します。
1007         *
1008         * @og.tag
1009         * オプションの指定。
1010         *  
1011         * @param attri オプションの値
1012         */
1013        public void setOptionAttributes( final String attri ) {
1014                optionAttributes = nval( getRequestParameter( attri ),optionAttributes );
1015        }
1016
1017        /**
1018         * 【TAG】x軸のデータ型を指定します。
1019         *
1020         * @ot.tag
1021         * X軸のデータを文字列として扱うか、数値として扱うかを指定します。(string/int)
1022         * Xが時間軸の場合に数値(UNIX時間)として扱う事で時間に沿ったスケールとなります。
1023         * 
1024         * @og.rev 5.10.3.2 (2018/09/28) 新規追加
1025         *
1026         * @param xtt string/int
1027         */
1028        public void setXscaleTimeType( final String xtt) {
1029                this.xscaleTimeType = nval( getRequestParameter( xtt ), this.xscaleTimeType ).toLowerCase();
1030                checkPara(xtt, XSCALEDATATYPE_LIST, "xscaleTimeType");
1031        }
1032
1033        /**
1034         * jsChartData情報をリストに追加します。
1035         * リストが存在しない場合は、新しく作成します。
1036         * 
1037         * @param jsData
1038         */
1039//      public void addJsChartData( final JsChartData jsData ) {
1040        protected void addJsChartData( final JsChartData jsData ) {
1041                if( jsChartData == null ) {
1042                        jsChartData = new ArrayList<JsChartData>();
1043                }
1044                jsChartData.add( jsData );
1045        }
1046
1047        /**
1048         * パラメータチェック用メソッド
1049         * 
1050         * @param trg
1051         * @param list
1052         * @param trgStr
1053         */
1054        private void checkPara( String trg, String[] list, String trgStr ) {
1055                if( trg != null && trg.length() > 0 && !check( trg, list ) ) {
1056                        StringBuilder errMsg = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
1057                        errMsg.append( "指定の" ).append( trgStr ).append( "は指定できません。" );
1058                        errMsg.append( HybsSystem.CR );
1059                        errMsg.append( trgStr ).append( "=[" ).append( trg ).append( "]" );
1060                        errMsg.append( HybsSystem.CR );
1061                        for( int i = 0; i < list.length; i++ ) {
1062                                errMsg.append( " | " );
1063                                errMsg.append( list[i] );
1064                        }
1065                        throw new HybsSystemException( errMsg.toString() );
1066                }
1067        }
1068
1069        /**
1070         * このオブジェクトの文字列表現を返します。
1071         * 基本的にデバッグ目的に使用します。
1072         * 
1073         * @return このクラスの文字列表現
1074         */
1075        public String toString() {
1076                // JSON形式でテーブル情報を取得
1077                ViewForm form = ViewFormFactory.newInstance( "JSON" );
1078                form.init( table );
1079
1080                // jsChartDataのパラメータ情報
1081                StringBuilder sb = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
1082                for( int i = 0; i < jsChartData.size(); i++ ) {
1083                        sb.append( " jsChartData" ).append( i ).append( ":" ).append( jsChartData.get( i ).getParameter() );
1084                }
1085
1086                // 2017/03/28 widthEventColumn,heightEventColumn,minEventColumn,maxEventColumnを追加
1087                return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
1088                        .println( "VERSION", VERSION )
1089                        .println( "id", id )
1090                        .println( "tableId", tableId )
1091//                      .println( "scope", scope )
1092                        .println( "chartType", chartType )
1093                        .println( "width", width )
1094                        .println( "height", height )
1095                        .println( "max", max )
1096                        .println( "min", min )
1097                        .println( "stepSize", stepSize )
1098                        .println( "barWidthPer", barWidthPer )
1099                        .println( "timeUnit", timeUnit )
1100                        .println( "timeUnitStepSize", timeUnitStepSize )
1101                        .println( "timeLblFormat", timeLblFormat )
1102                        .println( "timeSetFormat", timeSetFormat )
1103                        .println( "timeMax", timeMax )
1104                        .println( "timeMin", timeMin )
1105                        .println( "title", title )
1106                        .println( "titlePosition", titlePosition )
1107                        .println( "xlabel", xlabel )
1108                        .println( "ylabel", ylabel )
1109                        .println( "legendPosition", legendPosition )
1110                        .println( "legendDisplay", legendDisplay )
1111                        .println( "yscaleCallback", yscaleCallback )
1112                        .println( "xscaleCallback", xscaleCallback )
1113                        .println( "xscaleType", xscaleType )
1114                        .println( "xmax", xmax )
1115                        .println( "xmin", xmin )
1116                        .println( "xstepSize", xstepSize )
1117                        .println( "yscaleType", yscaleType )
1118                        .println( "ycategoryList", ycategoryList )
1119                        .println( "widthEventColumn", widthEventColumn )
1120                        .println( "heightEventColumn", heightEventColumn )
1121                        .println( "minEventColumn", minEventColumn )
1122                        .println( "maxEventColumn", maxEventColumn )
1123                        .println( "optionAttributes", optionAttributes )
1124                        .println( "JSON", form.create() )
1125                        .println( "jsChartDataPara", sb.toString() ).fixForm().toString();
1126        }
1127}