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