001    /*
002     * Copyright (c) 2009 The openGion Project.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013     * either express or implied. See the License for the specific language
014     * governing permissions and limitations under the License.
015     */
016    package org.opengion.plugin.view;
017    
018    import org.opengion.hayabusa.common.HybsSystem;
019    import org.opengion.hayabusa.common.HybsSystemException;
020    import org.opengion.fukurou.util.StringUtil;
021    
022    import java.util.Calendar;
023    import java.util.Map;
024    import java.util.TreeMap;
025    import java.util.Collection;
026    import java.util.Locale ;
027    import java.util.Date;
028    import java.text.DateFormat;
029    import java.text.SimpleDateFormat;
030    
031    import java.awt.Graphics2D;
032    import java.awt.Color;
033    import java.awt.FontMetrics;
034    import java.awt.Stroke;
035    import java.awt.BasicStroke;
036    import java.awt.image.BufferedImage;
037    
038    import javax.imageio.ImageIO;
039    import java.io.File;
040    import java.io.IOException;
041    
042    
043    /**
044     * キー、日時?状況コードを持つ稼働状況?表示を行うクラスです?
045     *
046     * パラメータが?な場合?、ViewTimeBarParamTag を使用してください?
047     *
048     * パラメータが設定されて???合?、ViewForm_ImageTimeBar の初期値が使用されます?
049     * (パラメータを使用するには、viewタグのuseParam 属?をtrueに設定する?があります?)
050     *
051     * SELECT??、キー、日時?状況コードが、???で、カラ??並び??、完?に固定です?
052     * よって、カラ?置を指定する??ありませんが?SELECT?自由に設定すること?
053     * 出来ませんので、ご注意く???
054     * こ?固定化に伴??WRITABLE ?も使用できません。(そもそも書き込み不可です?
055     * それ以降?カラ?つ?は、?部処?しては、使用して?せん?
056     * ただし?パラメータで、カラー色??ラベル表記部、イメージ重?合わせ?
057     * ポップア??表記?リンク表記に使えます?
058     *
059     * ??タの並び?ORDER BY)も?キー、日時?にしてください?
060     * ??タは、キー単位に?レコード作?されます??キーブレイク?その間?日時?に
061     * ??タを??ます?
062     *
063     * ??タの表示は、今?レコード?日時から?次のレコード?日時までを?の状態と
064     * して表します?今?レコードを表示するには、次のレコードが?になります?
065     * 画面表示は、表示開始日?minStartTime) から 表示期間(timeSpan)?表示します?
066     * 通常?始時刻は、表示開始時刻より前より始まり?次のレコードで、終?刻が決?
067     * されます?????タは、期間??で続いて?と仮定されます?
068     * ??タが存在しな??であれば、?存在しな?ータ」を作?してください?
069     * 
070     * ImageTimeBar では、キーでまとめた値につ?、各状況コードをカラー化し、積み上げ
071     * 帯グラフ形式でPNG画像化します?
072     * こ?画像を、読み込?HTML を?力することで、画面上に、積み上げ帯グラフを表示します?
073     * 状況コードに対応する色は、標準では自動作?ですが、外部から色??(colorClm)を与えることで
074     * 自由に?する事も可能です?
075     *
076     * ポップア??表?tipsClm)、リンク表?linkClm)は、この画像に対するエリア?タグを?力する事で実現します?
077     * 画像ファイルは、???タに対して?画像だけなので、サイズは大きくなりますが?レコー?
078     * 単位に画像を作?しな?め?レスポンスは向上します?
079     * それぞれ、viewMarker , viewLink を利用することが可能です?特に、リンク表?linkClm) につ?は?
080     * linkタグの hrefTarget 属??true に設定することで適用できます?
081     *
082     * 画像ファイルは、java.io.File.createTempFile( File ) で作?するため、JavaVM(=Tomcat)?
083     * 正常終?るときに、削除されます?異常終?には残りますが、temp フォル?定期?
084     * 整?れ?、それほど大量?ファイルが残ることはな?思われます?
085     *
086     * ??タは、イベント発生時に作?されると仮定して?す?つまり?書き込まれた日時から?
087     * 状況コードに対応する状況が発生し、次の状???レコードまで継続して?と?ます?
088     * よって、データを?中で?出す?合??出す?の前?状態が?になります?
089     * ???の状態??不?" として扱?す??空?白色??
090     *
091     * @og.rev 5.5.5.6 (2012/08/31) 新規追?
092     * @og.group 画面表示
093     *
094     * @version  4.0
095     * @author       Kazuhiko Hasegawa
096     * @since    JDK5.0,
097     */
098    public class ViewForm_ImageTimeBar extends ViewForm_HTMLTable {
099            //* こ?プログラ??VERSION??を設定します?       {@value} */
100            private static final String VERSION = "5.6.5.0 (2013/06/07)" ;
101    
102            private static final Color LABEL_COLOR = Color.BLACK;           // ラベル記述時?色
103            private static final Color NULL_COLOR  = Color.WHITE;           // 5.6.1.1 (2013/02/08) 不?(空?時?色
104    
105            private long startDate          ;       // タイ?ーブルの表示開始日時から求め?long 値(1=??
106            private long timeSpan           ;       // タイ?ーブルの表示期間。?は時間?であるが??位で持つ?1=??
107    
108            private boolean useLegend       ;       // カラーの凡例を使用するかど?[true/false]
109            private int maxLabelWidth       ;       // ラベル表記部の?サイズをpxで??何もなければ、可変長サイズ
110            private int maxTimeWidth        ;       // タイ?記部の?サイズをpxで??
111            private int chartHeight         ;       // ?レコード?チャート?間隔をpxで??実際の??、CHART_HEIGHT?MARGIN??
112            private int chartPadding        ;       // イメージ作?の 全体テーブルの隙間
113            private int recodeMargin        ;       // ?コード??等??の間隔
114            private boolean useLastData     ;       // 5.6.1.1 (2013/02/08) 行?????が?継続して?として使?ど?[true/false]
115    
116            private String tempDir          ;       // 画像ファイルを作?する?ポラリ?レクトリ(相対パス)
117            private String tempUrl          ;       // 作?した画像ファイルを取得するときに使用するURL(コン?ス?相対パス)
118    
119            // SELECT??、キー、日時?状況コードが、???
120            private static final int        keyClmNo        = 0;    // ヘッ??1?キーカラ?o
121            private static final int        dyClmNo         = 1;    // ヘッ??2?日時カラ?o
122            private static final int        fgjClmNo        = 2;    // ヘッ??3?状況コードカラ?o
123    
124            private int[] labelClmsNo       = null;                         // 初期値は、キーカラ?
125            private int[] maxClmWidth       = null;                         // labelClms 単位????長
126            private int   colClmNo          = -1;                           // カラーコード直接?する?合に色??を指定するカラ?o
127            private int   tipsClmNo         = -1;                           // マウスオーバ?時?Tips表示を行うカラ?o
128            private int   linkClmNo         = -1;                           // クリ?ブルリンクを設定するカラ?o
129    
130            private int str2DateTime        ;       // getStr2Date(String)処?おこなった時の、引数の時刻??(??をセ?する?ポラリ変数?
131            private int startTime           ;       // startDate の時刻??。上記??、startDate ?getStr2Date(String) 処?たとき?値を持っておくための変数?
132    
133            private int MAX_X       ;       // イメージの?横?X)方向?サイズpx。chartPadding*2 + maxLabelWidth + maxTimeWidth
134            private int MAX_Y       ;       // イメージの?縦?Y)方向?サイズpx。chartPadding*2 + (chartHeight+recodeMargin*2)*(レコード数???ー数)
135    
136            /**
137             * ?をクリア(初期?します?
138             *
139             */
140    //      @Override
141    //      public void clear() {
142    //              super.clear();
143    //      }
144    
145            /**
146             * DBTableModel から HTML??を作?して返します?
147             * startNo(表示開始位置)から、pageSize(表示件数)までのView??を作?します?
148             * 表示残り??タ?pageSize 以下?場合?,残りの??タをすべて出力します?
149             *
150             * @og.rev 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
151             * @og.rev 5.6.1.1 (2013/02/08) 初期値の色を?直接の値ではなく?static final で定義された色を使用する。色自体?変えて?せん
152             * @og.rev 5.6.1.1 (2013/02/08) useLastData 追?
153             * @og.rev 5.6.3.0 (2013/04/01) tipsのシングルクォー??ション のエスケー?
154             * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?lt;span>タグが付与される値から、spanタグを削除します?
155             *
156             * @param  startNo        表示開始位置
157             * @param  pageSize   表示件数
158             *
159             * @return      DBTableModelから作?され?HTML??
160             */
161            @Override
162            public String create( final int startNo, final int pageSize )  {
163                    if( getRowCount() == 0 ) { return ""; } // 暫定?置
164    
165                    // パラメータの??を?期化??得します?
166                    paramInit();
167    
168                    int lastNo = getLastNo( startNo, pageSize );
169    
170                    // イメージの ???サイズを求め、結果を?MAX_X,MAX_Y 変数に設定する?
171                    calcImageSize( startNo,lastNo );
172    
173                    BufferedImage img = new BufferedImage( MAX_X, MAX_Y, BufferedImage.TYPE_INT_ARGB);
174                    Graphics2D g2 = img.createGraphics();
175    
176                    // chartPadding を?慮した領域のクリ???クリ??外にDrowされても無視されます???
177                    g2.setClip( chartPadding , chartPadding , MAX_X-chartPadding*2+1 , MAX_Y-chartPadding*2+1 );    // ?? 座?y 座??高さ) ?1?罫線??
178    
179                    StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );
180    
181                    String oldKeyVal = "";                          // 初期値。1回目にキーブレイクさせる?
182                    long   oldTime   = 0L;                          // 日付?目の?前?値
183    
184    //              Color  oldColor  = Color.WHITE;         // 色の?前?値(初期値)
185                    Color  oldColor  = NULL_COLOR;          // 5.6.1.1 (2013/02/08) 不?(空?時?色(初期値)
186    
187                    ColorMap colMap = new ColorMap();       // 状況コード?ラベル、カラーを管?るクラス
188    
189                    int rowCnt = (useLegend) ? 2 : 1;               // 凡?useLegend)を使?true)場合??行?、使わな??合?、??ーの?行が初期値
190                    int imgX   = 0;                                                 // イメージ出力時の X軸の左端 px数
191                    int imgY   = 0;                                                 // イメージ出力時の Y軸の上端 px数
192                    int imgW   = 0;                                                 // イメージ出力時の ?fillRectで使用)
193                    int imgH   = chartHeight;                               // イメージ出力時の 高さ(fillRectで使用)
194                    int rowH   = chartHeight+recodeMargin*2;        // 罫線?力時の高さ(drawRectで使用)
195    
196                    double timeScale = (double)maxTimeWidth/(double)timeSpan;
197                    boolean useTipsLink = (tipsClmNo >= 0 || linkClmNo >= 0) ;                // tipsClm ?linkClm かどちらかを使用する場合?true
198                    for( int row=startNo; row<lastNo; row++ ) {
199                            // キーブレイクの判?
200                            String keyVal  = getValue( row,keyClmNo );
201                            String dyVal   = getValue( row,dyClmNo );
202    
203                            // キーブレイク判定?キーブレイクは、?初めから来る?
204                            if( !oldKeyVal.equals( keyVal ) ) {
205                                    // キーブレイクで??に行うのは、前のレコード?未出力?の処???行目は、???
206                                    if( row > startNo ) {
207                                            imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale);
208                                            imgW = (int)((timeSpan-oldTime)*timeScale) ;
209    
210                                            // ?0以上?場合?み描画する?
211                                            if( imgW > 0 ) {
212                                                    // 5.6.1.1 (2013/02/08) useLastData 追?
213                                                    if( useLastData ) { g2.setColor( oldColor ); }                                  // 色の設定?、旧色を使?
214                                                    else {                          g2.setColor( NULL_COLOR ); }                            // NULL色を使?
215                                                    g2.fillRect( imgX , imgY+recodeMargin , imgW, imgH );                   // (実際の状?左端x,上端y,?,高さh
216    
217                                                    // tipsClm ?linkClm を使用する?
218                                                    // 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
219    //                                              if( useTipsLink ) {
220    //                                              if( useTipsLink && row > 0 ) {
221                                                    if( useLastData && useTipsLink && row > 0 ) {        // 5.6.1.1 (2013/02/08) useLastData 追?
222                                                            // tips ?link は、?とつ前???タで作?する?がある?row-1)
223                                                            String tips = (tipsClmNo >= 0) ? getValueLabel( row-1,tipsClmNo ) : getValueLabel( row-1,fgjClmNo ) ;
224                                                            if( tips != null && tips.indexOf( "'" ) >= 0 ) {     // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
225                                                                    tips = tips.replaceAll( "'","&#39;" );
226                                                            }
227                                                            tips = StringUtil.spanCut( tips );                                      // 5.6.3.1 (2013/04/05) spanタグを削除
228    
229                                                            out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
230                                                            if( linkClmNo >= 0 ) {
231                                                                    String hrefVal = getValueLabel( row-1,linkClmNo );
232                                                                    if( hrefVal != null && hrefVal.startsWith( "href" ) ) {         // linkClmの値の先?が?html の場合?み追?る?
233                                                                            out.append( hrefVal );
234                                                                    }
235                                                            }
236                                                            out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," );               // 左端x1,上端y1
237                                                            out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" );                      // 右端x2,下段y2
238                                                    }
239                                            }
240                                    }
241    
242                                    // 次に、新しい行?出力(ラベルは、ブレイク時に出力しておきます???
243                                    oldKeyVal = keyVal;                     // null は来な???
244                                    imgY = chartPadding+(rowH)*rowCnt ;
245                                    rowCnt++ ;
246    
247                                    // レコード?ラベル?け?繰返し描画する?
248                                    int clmSu = labelClmsNo.length;
249                                    int posX  = chartPadding ;                                              // ラベル??の書き?し位置の初期値
250                                    int posY2 = imgY+chartHeight+recodeMargin ;             // ラベルのY軸基準?
251                                    g2.setColor( LABEL_COLOR );
252                                    for( int col=0; col<clmSu; col++ ) {
253                                            String lbl = getValueLabel( row,labelClmsNo[col] );             // そ?行?値のRenderer値
254                                            lbl = StringUtil.spanCut( lbl );                                                // 5.6.3.1 (2013/04/05) spanタグを削除
255                                            g2.drawString( lbl , posX + recodeMargin, posY2 );              // ??,ベ?スラインのx座?y座?
256                                            posX += recodeMargin*2 + maxClmWidth[col] ;                             // 次の書き?し位置は、文字最大長??ージン
257                                    }
258    
259                                    // レコード???
260                                    g2.drawRect( chartPadding , imgY , MAX_X-chartPadding*2 , rowH );               // (レコード枠)左端x,上端y,?,高さh
261    
262                                    oldTime = 0L;                           // キーブレイクによる初期?
263    //                              oldColor= Color.WHITE;          // キーブレイクによる初期?
264                                    oldColor= NULL_COLOR;           // 5.6.1.1 (2013/02/08) キーブレイクによる初期?不?(空?時?色
265                            }
266    
267                            long newTime = getStr2Date( dyVal ) - startDate;                // 次の時刻
268                            if( newTime < oldTime ) { newTime = oldTime; }                       // 前?時刻より小さ??合?、前の時刻まで??めておく?
269    
270                            imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale);         // old時刻から書き始め?左端x)
271                            imgW = (int)((newTime-oldTime)*timeScale) ;                                                     // 差??け描画する?
272    
273                            // ?0以上?場合?み描画する?
274                            if( imgW > 0 ) {
275                                    g2.setColor( oldColor );                                                                                // 色の設?
276                                    g2.fillRect( imgX , imgY+recodeMargin , imgW, chartHeight );    // (実際の状?左端x,上端y,?,高さh
277    
278                                    // tipsClm ?linkClm を使用する?
279                                    // 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
280    //                              if( useTipsLink ) {
281                                    if( useTipsLink && row > 0 ) {
282                                            // tips ?link は、?とつ前???タで作?する?がある?row-1)
283                                            String tips = (tipsClmNo >= 0) ? getValueLabel( row-1,tipsClmNo ) : getValueLabel( row-1,fgjClmNo ) ;
284                                            if( tips != null && tips.indexOf( "'" ) >= 0 ) {     // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
285                                                    tips = tips.replaceAll( "'","&#39;" );
286                                            }
287                                            tips = StringUtil.spanCut( tips );                                      // 5.6.3.1 (2013/04/05) spanタグを削除
288    
289                                            out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
290                                            if( linkClmNo >= 0 ) {
291                                                    String hrefVal = getValueLabel( row-1,linkClmNo );
292                                                    if( hrefVal != null && hrefVal.startsWith( "href" ) ) {         // linkClmの値の先?が?html の場合?み追?る?
293                                                            out.append( hrefVal );
294                                                    }
295                                            }
296                                            out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," );               // 左端x1,上端y1
297                                            out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" );                      // 右端x2,下段y2
298                                    }
299                            }
300    
301                            oldTime   = newTime ;
302    
303                            String fgjVal  = getValue( row,fgjClmNo );                      // 状況コード?キー
304                            String fgjLbl  = getValueLabel( row,fgjClmNo );         // 状況コード?ラベル
305                            if( colClmNo >= 0 ) {
306                                    oldColor  = colMap.getColor( fgjVal,fgjLbl,getValue( row,colClmNo ) );          // 色??を指定する??
307                            }
308                            else {
309                                    oldColor  = colMap.getColor( fgjVal,fgjLbl );                                                           // 色??を指定しな??動設?
310                            }
311                    }
312    
313                    // レコード??ばん最後?出力???ジャスト?場?oldTime == maxEdTime)は、??な?
314                    // 5.6.1.1 (2013/02/08) レコード??ばん最後?出力?、NULL色を使??変更
315                    if( oldTime < timeSpan ) {
316                            imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale);
317                            imgW = (int)((timeSpan-oldTime)*timeScale) ;
318                            // 5.6.1.1 (2013/02/08) useLastData 追?
319                            if( useLastData ) { g2.setColor( oldColor ); }                                  // 色の設定?、旧色を使?
320                            else {                          g2.setColor( NULL_COLOR ); }                            // NULL色を使?
321                            g2.fillRect( imgX , imgY+recodeMargin , imgW, chartHeight );    // (実際の状?左端,上端,?高さ
322    
323                            // tipsClm ?linkClm を使用する?
324    //                      if( useTipsLink ) {
325                            if( useLastData && useTipsLink ) {                      // 5.6.1.1 (2013/02/08) useLastData 追?
326                                    // tips ?link ??出力?、最後???タなので、lastNo-1 となる?
327                                    String tips = (tipsClmNo >= 0) ? getValueLabel( lastNo-1,tipsClmNo ) : getValueLabel( lastNo-1,fgjClmNo ) ;
328                                    if( tips != null && tips.indexOf( "'" ) >= 0 ) {     // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
329                                            tips = tips.replaceAll( "'","&#39;" );
330                                    }
331                                    tips = StringUtil.spanCut( tips );                                      // 5.6.3.1 (2013/04/05) spanタグを削除
332    
333                                    out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
334                                    if( linkClmNo >= 0 ) {
335                                            String hrefVal = getValueLabel( lastNo-1,linkClmNo );
336                                            if( hrefVal != null && hrefVal.startsWith( "href" ) ) {         // linkClmの値の先?が?html の場合?み追?る?
337                                                    out.append( hrefVal );
338                                            }
339                                    }
340                                    out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," );               // 左端x1,上端y1
341                                    out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" );                      // 右端x2,下段y2
342                            }
343                    }
344    
345                    // ヘッ????のイメージを作?します?
346                    imageHeaderPaint( g2 , timeScale , colMap );
347    
348                    // イメージファイルを?力し、URLを返します?
349                    File file = null;
350                    try {
351                            File dir = new File( tempDir );         // 画像ファイル出力?のフォル?
352                            dir.mkdirs();                                           // なければ作?する?
353    
354                            file = File.createTempFile( "Img",".png", dir );        // ?ポラリファイルの作?
355                            file.deleteOnExit();                                                            // JavaVM 停止時に?ポラリファイルの削除
356    
357                            ImageIO.write(img, "PNG", file );
358                            g2.dispose();
359                    }
360                    catch( IOException ex ) {
361                            System.out.println( "エラー:" + ex );
362                    }
363    
364                    // imgタグを作?します?
365                    int width  = MAX_X;
366                    int height = MAX_Y;
367    
368                    StringBuilder out2 = new StringBuilder( HybsSystem.BUFFER_LARGE );
369                    out2.append( "<img id='ImageTimeBar' alt='ImageTimeBar' border='0'" );
370                    out2.append( " width='" ).append( width ).append( "px' height='" ).append( height ).append( "px'" );
371                    out2.append( " src='" ).append( tempUrl ).append( file.getName() ).append( "'" );
372    
373                    // area タグの??タが作?されて?ば、?力します?
374                    if( out.length() > 0 ) {
375                            out2.append( " usemap='#TimeBarMap' />" );   // img タグにusemap 属?を追?て、終??追?
376    
377                            out2.append( "<map name='TimeBarMap'>" );
378                            out2.append( out );
379                            out2.append( "</map>" );
380                    }
381                    else {
382                            out2.append( " />" );                                                // img タグの終??追?
383                    }
384    
385                    return out2.toString();
386            }
387    
388            /**
389             * パラメータ?を?期化します?
390             *
391             * @og.rev 5.6.1.1 (2013/02/08) useLastData 追?
392             */
393            private void paramInit() {
394                    String s_startDate      = getParam( "START_DATE"                );      // タイ?ーブルの表示開始日時をセ?しま?初期値:??タの?日??
395                    int timeSpanHour        = getIntParam( "TIME_SPAN"              );      // タイ?ーブルの表示期間を時間で?しま?初期値:{@og.value TIME_SPAN})?
396    
397                    String[] s_labelClms    = StringUtil.csv2Array( getParam( "LABEL_CLMS" ) );     // ?表のラベル表示部に表示するカラ?をCSV形式で?します?
398                    String s_colClm                 = getParam( "COLOR_CLM"         );      // レコードに付ける色を色??で?する?合?カラ?を指定します?
399                    String s_tipsClm                = getParam( "TIPS_CLM"          );      // レコード単位に、?ウスオーバ?時?Tips表示を行うカラ?を指定します?
400                    String s_linkClm                = getParam( "LINK_CLM"          );      // レコード単位に、クリ?ブルリンクを設定するカラ?を指定します?
401    
402                    useLegend               = getBoolParam( "USE_LEGEND"            );      // カラーの凡例を使用するかど?[true/false]
403                    maxLabelWidth   = getIntParam( "MAX_LABEL_WIDTH"        );      // ラベル表記部の?サイズをpxで??何もなければ、可変長サイズ
404                    maxTimeWidth    = getIntParam( "MAX_TIME_WIDTH"         );      // タイ?記部の?サイズをpxで??
405                    chartHeight             = getIntParam( "CHART_HEIGHT"           );      // ?レコード?チャート?間隔をpxで??実際の??、CHART_HEIGHT?MARGIN??
406                    chartPadding    = getIntParam( "CHART_PADDING"          );      // イメージ作?の 全体テーブルの隙間
407                    recodeMargin    = getIntParam( "RECODE_MARGIN"          );      // ?コード??等??の間隔
408                    useLastData             = getBoolParam( "USE_LAST_DATA"         );      // 5.6.1.1 (2013/02/08) 行?????が?継続して?として使?ど?[true/false]
409    
410                    tempDir                 = getParam( "TEMP_DIR"                          );      // 画像ファイルを作?する?ポラリ?レクトリ(相対パス)
411                    tempUrl                 = getParam( "TEMP_URL"                          );      // 作?した画像ファイルを取得するときに使用するURL(コン?ス?相対パス)
412    
413                    startDate               = getStr2Date( s_startDate );                   // ?位に変換する?
414                    startTime               = str2DateTime ;                                                // 開始日時?時刻??(??の値。str2DateTime は、getStr2Date(String)メソ?実行後にセ?される?
415                    timeSpan                = timeSpanHour * 60L ;                                  // ?位に変換する?
416    
417                    int len = s_labelClms.length;
418                    if( len > 0 ) {
419                            labelClmsNo = new int[len];
420                            for( int i=0; i<len; i++ ) {
421                                    labelClmsNo[i] = getColumnNo( s_labelClms[i] );
422                            }
423                    }
424                    else {
425                            labelClmsNo = new int[] { keyClmNo };           // 初期値は、キーカラ?
426                    }
427    
428                    // ??カラ?に対するカラ?号を取得?なければ?1 を設定しておく?
429                    if( s_colClm  != null ) { colClmNo  = getColumnNo( s_colClm  ); }                       // レコードに付ける色を色??で?する?合?カラ?o
430                    if( s_tipsClm != null ) { tipsClmNo = getColumnNo( s_tipsClm ); }                       // レコード単位に、?ウスオーバ?時?Tips表示を行うカラ?o
431                    if( s_linkClm != null ) { linkClmNo = getColumnNo( s_linkClm ); }                       // レコード単位に、クリ?ブルリンクを設定するカラ?o
432            }
433    
434            /**
435             * イメージの ??サイズを求め、結果を?MAX_X,MAX_Y 変数に設定します?
436             *
437             * また?ラベル??の?長が指定されて???合?axLabelWidth == -1?最大長を?動計算し、maxLabelWidth変数にセ?します?
438             *
439             * maxLabelWidth : -1 の場合?、ラベル??の?長を求めて、この値を計算する?= (recodeMargin*2 + ラベル??の?長)
440             * MAX_X : イメージの?横?X)方向?サイズpx。chartPadding*2 + maxLabelWidth + maxTimeWidth
441             * MAX_Y : イメージの?縦?Y)方向?サイズpx。chartPadding*2 + (chartHeight+recodeMargin*2)*(レコード数???ー数)
442             *
443             * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?span>タグが付与される値から、spanタグを削除します?
444             * 
445             * @param       startNo 計算?開始?番号
446             * @param       lastNo  計算?終??番号
447             */
448            private void calcImageSize( final int startNo , final int lastNo ) {
449                    String oldKeyVal = "";  // 初期値。1回目にキーブレイクさせる?
450    
451                    int clmSu = labelClmsNo.length;
452                    maxClmWidth = new int[clmSu];
453    
454                    int rowCnt = (useLegend) ? 2 : 1;               // 凡?useLegend)を使?true)場合??行?、使わな??合?、??ーの?行が初期値
455    
456                    // ラベル領域の長さを?ベル長を積み上げて計算する?
457                    if( maxLabelWidth < 0 ) {
458                            // FontMetrics を取得する為?の BufferedImage
459                            BufferedImage img = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_ARGB);
460                            Graphics2D g2 = img.createGraphics();
461                            FontMetrics fontM = g2.getFontMetrics();
462    
463                            // 初期値の計算?、??ーのラベルの?使用する?
464                            for( int col=0; col<clmSu; col++ ) {
465                                    String lbl = getColumnLabel( labelClmsNo[col] );        // ヘッ??のラベル
466                                    lbl = StringUtil.spanCut( lbl );                                        // 5.6.3.1 (2013/04/05) spanタグを削除
467                                    maxClmWidth[col] = fontM.stringWidth( lbl );            // ?値の初期値として、??ーラベルの?セ?しておく?
468                            }
469    
470                            for( int row=startNo; row<lastNo; row++ ) {
471                                    // キーブレイク判定?キーブレイクは、?初めから来る?
472                                    String keyVal = getValue( row,keyClmNo );
473                                    if( !oldKeyVal.equals( keyVal ) ) {
474                                            oldKeyVal = keyVal;
475                                            rowCnt++;                               // レコード数
476    
477                                            // ラベルは、キーブレイク時?値のみ採用する?
478                                            for( int col=0; col<clmSu; col++ ) {
479                                                    String lbl = getValueLabel( row,labelClmsNo[col] );     // そ?行?値のRenderer値
480                                                    lbl = StringUtil.spanCut( lbl );                                        // 5.6.3.1 (2013/04/05) spanタグを削除
481                                                    int fontW = fontM.stringWidth( lbl );
482                                                    if( maxClmWidth[col] < fontW ) { maxClmWidth[col] = fontW; }
483                                            }
484                                    }
485                            }
486                            g2.dispose();
487    
488                            // ?ラベル??、各ラベルの?値?(?ージン?2)*カラ?
489                            maxLabelWidth = recodeMargin * 2 * clmSu ;
490                            for( int col=0; col<clmSu; col++ ) {
491                                    maxLabelWidth += maxClmWidth[col];
492                            }
493                    }
494                    else  {
495                            for( int row=startNo; row<lastNo; row++ ) {
496                                    // キーブレイク判定?キーブレイクは、?初めから来る?
497                                    String keyVal = getValue( row,keyClmNo );
498                                    if( !oldKeyVal.equals( keyVal ) ) {
499                                            oldKeyVal = keyVal;
500                                            rowCnt++;                               // レコード数
501                                    }
502                            }
503    
504                            // ?ラベル??、均等割り付け。端数は無視(ど?、ラベル部は、maxLabelWidth で計算する?で。?
505                            int clmWidth = ( maxLabelWidth - recodeMargin * 2 * clmSu ) / clmSu ;
506                            for( int col=0; col<clmSu; col++ ) {
507                                    maxClmWidth[col] = clmWidth;
508                            }
509                    }
510    
511                    MAX_X = chartPadding*2 + maxLabelWidth + maxTimeWidth ;
512                    MAX_Y = chartPadding*2 + (chartHeight+recodeMargin*2)*rowCnt ;
513            }
514    
515            /**
516             * ヘッ????のイメージを作?します?
517             *
518             * 全体??ここで作?しておきます?
519             * イメージは、キーカラ??ラベルと、時間軸になります?時間軸は縦方向にすべて線を引きます?
520             * 時間軸の間隔は、timeScale によって、?り替わります?
521             * 凡例を使??合?seLegend=true??、引数の ColorMap を利用して作?します?
522             *
523             * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?span>タグが付与される値から、spanタグを削除します?
524             * @og.rev 5.6.5.0 (2013/06/07) 年月日??を表示します?なお?日単位?場合?、年月?省略します?
525             *
526             * @param       g2                      描画するGraphics2Dオブジェク?
527             * @param       timeScale       時間(?当たり?ピクセル数
528             * @param       colMap          状況コードに対応したカラーマッ?
529             */
530            private void imageHeaderPaint( final Graphics2D g2 , final double timeScale , final ColorMap colMap ) {
531    
532                    int posY1 = chartPadding  ;
533                    int posY2 = chartPadding+chartHeight+recodeMargin ;
534    
535                    // 凡例を使???
536                    if( useLegend && colMap != null ) {
537                            // 凡例を並べる間隔を求める?
538                            FontMetrics fontM = g2.getFontMetrics();
539                            int maxSize = fontM.stringWidth( colMap.getMaxLengthLabel() ) ;         // ??の?長ラベルの?
540                            int imgW  = chartHeight ;                               // 凡例■の?高さと同じにして?ので真四?
541                            int mgnW  = recodeMargin ;                              // 凡例■から?までの?
542                            int spanW = maxSize + recodeMargin ;    // 凡例■から凡例■までの間隔。文字最大長?α
543    
544                            int legX  = chartPadding ;
545                            for( Object[] obj : colMap.values() ) {
546                                    String lbl = (String)obj[0];
547                                    Color  col = (Color)obj[1];
548    
549                                    g2.setColor( col );                                                                                             // 凡例■の色
550                                    g2.fillRect( legX , posY1+recodeMargin , imgW , chartHeight );  // (実際の状?左端x,上端y,?,高さh
551    
552                                    legX += imgW + mgnW ;
553                                    g2.setColor( LABEL_COLOR );
554                                    g2.drawString( lbl , legX , posY2 );            // ??,ベ?スラインのx座?y座?
555    
556                                    legX += spanW ;
557                            }
558                            posY1 += chartHeight+recodeMargin*2 ;   // ?レコード?の高さを加算しておく?
559                            posY2 += chartHeight+recodeMargin*2 ;   // ?レコード?の高さを加算しておく?
560                    }
561    
562                    // まず?、?体???描画
563                    g2.setColor( LABEL_COLOR );
564                    g2.drawRect( chartPadding, posY1, MAX_X-chartPadding*2, MAX_Y-posY1-chartPadding );                             // 左端,上端,?高さ
565    
566                    // ヘッ??のラベル?け?繰返し描画する?
567                    int clmSu = labelClmsNo.length;
568                    int posX  = chartPadding ;              // ラベル??の書き?し位置の初期値
569                    for( int col=0; col<clmSu; col++ ) {
570                            String lbl = getColumnLabel( labelClmsNo[col] );                        // ヘッ??のラベル
571                            lbl = StringUtil.spanCut( lbl );                                                        // 5.6.3.1 (2013/04/05) spanタグを削除
572                            g2.drawString( lbl , posX + recodeMargin, posY2 );                      // ??,ベ?スラインのx座?y座?
573                            posX += recodeMargin*2 + maxClmWidth[col] ;                                     // 次の書き?し位置は、文字最大長??ージン*2
574                            g2.drawLine( posX, posY1, posX, MAX_Y-chartPadding );           // 始点(x 座?y 座?,終点(x 座?y 座?
575                    }
576    
577                    int step = TimeScaleStep.getStep( timeScale );                  // 時間スケールに対応したSTEP数
578    
579                    // 日付??ー部の描画のためのカレン??
580                    Calendar cal = Calendar.getInstance();
581                    cal.setTimeInMillis( startDate * 60000L );
582    
583                    int week = cal.get( Calendar.DAY_OF_WEEK );     // 開始曜日
584    
585                    String fmt = ( step < 1440 ) ? "yyyy/MM/dd(EE)" : "dd" ;             // 上段フォーマット?、時間?ースの場合??yyyy/MM/dd(EE)" 、日ベ?スの場合??dd"
586                    DateFormat format1 = new SimpleDateFormat( fmt,Locale.JAPAN );
587    
588                    // グラフ?域?日付??ー部の描画
589                    g2.setStroke( DSAH_STROK );                             // 日付部は、??
590                    posX = chartPadding+maxLabelWidth ;             // グラフ?域?、chartPadding+maxLabelWidth から?
591                    for( int tm = 0; tm < timeSpan; tm+=step ) {
592    
593                            int offset = chartHeight / 2 + recodeMargin;    // ヘッ??の表示基準?オフセ??チャート??半???
594    
595                            // 上段???ー出?
596                            if( ( tm % 1440 ) == 0 ) {
597                                    Date dt = new Date( (startDate + tm) * 60000L );
598                                    g2.drawString( format1.format( dt ) , posX + recodeMargin , posY2-offset );                     // ??,ベ?スラインのx座?y座?
599                                    offset = 0;             // ヘッ??を表示する場合?み上まで線を引く?
600                            }
601    
602                            g2.drawString( getTime2Str(startTime+tm,step,week) , posX + recodeMargin , posY2 );             // ??,ベ?スラインのx座?y座?
603                            g2.drawLine( posX, posY1+offset, posX, MAX_Y-chartPadding );                                                    // 始点(x 座?y 座?,終点(x 座?y 座?
604    
605    //                      g2.drawString( getTime2Str(startTime+tm,step) , posX + recodeMargin , posY2 );  // ??,ベ?スラインのx座?y座?
606    //                      g2.drawLine( posX, posY1-10, posX, MAX_Y-chartPadding-10 );                                             // 始点(x 座?y 座?,終点(x 座?y 座?
607                            posX += (int)(step*timeScale);
608                    }
609            }
610    
611            // imageHeaderPaintメソ?で使用する 破線?定義
612            private static final Stroke DSAH_STROK = new BasicStroke(
613                                    1.0f                                            , // BasicStroke の?
614                                    BasicStroke.CAP_BUTT            , // 両端の?
615                                    BasicStroke.JOIN_MITER          , // 輪郭線セグメント?接合部の?
616                                    1.0f                                            , // 接合トリミングの制限?
617                                    new float[] {2.0f, 1.0f}        , // 破線パターンを表す??
618                                    0.0f                                              // 破線パターン開始位置のオフセ?
619            );
620    
621            /**
622             * 時間スケールに対応したSTEP数を管?るため??クラス
623             *
624             * 時間ヘッ??を表示する場合?ある程度意味のある間隔でラベル表示した?思います?
625             * 全体?描画領域の長さと、時間当たり?スケールファクター?ピクセル数?から?
626             * ラベルの描画間隔を求めます?
627             * 意味のある間隔は、STEPS で定義し?10?30?60?1/4日,1/2日,1日 まで定義して?す?
628             * ?大きな単位以上?場合?、その?単位?整数倍を返します?
629             *
630             * ?間当たり?表示?、MIN_PX として?す?で、この値以下?間隔では描画されません?
631             * 初期値は?00px ?24時間表示できる 600px/24h = 25px にして?す?
632             */
633            private static final class TimeScaleStep {
634                                                                                                            // ?  ?  ?  1/4   1/2  ?日
635                    private static final int[] STEPS = new int[] { 10 , 30 , 60 , 360 , 720 , 1440 };
636                    private static final int MIN_PX = 25;           // スケールに対する??
637    
638                    /**
639                     * 時間を意味のある?の整数として返します?
640                     *
641                     * 全体?描画領域の長さと、時間当たり?スケールファクター?ピクセル数?から?
642                     * 10?30?60?1/4日,1/2日,1日 までの整数値で返します?
643                     * ?大きな単位以上?場合?、その?単位?整数倍を返します?
644                     *
645                     * @param       timeScale       時間(?当たり?ピクセル数
646                     * @return      時間スケールに対応した意味のある?の整数
647                     */
648                    public static final int getStep( final double timeScale ) {
649                            int tmStep = (int)Math.ceil(MIN_PX/(timeScale));        // 整数?上げ
650    
651                            for( int i=0; i<STEPS.length; i++ ) {
652                                    if( tmStep <= STEPS[i] ) { return STEPS[i]; }        // 配?の数字に?上げ
653                            }
654    
655                            // 未設定?場合?、最上位?値の整数倍に?上げ
656                            return (int)Math.ceil( tmStep / STEPS[STEPS.length-1] ) * STEPS[STEPS.length-1];
657                    }
658            }
659    
660            /**
661             * 状況コード?ラベル、色を管?るため??クラス
662             *
663             * 状況に応じたコード?ラベル、色を管?ます?
664             * これは、getColor(状況コー?ラベル) また?、getColor(状況コー?ラベル,色??) で
665             * 要求された??を?部で管?、同じコード?場合に同じ色を返します?
666             * また?凡例作?用に、最も文字数が長?ベルを管?ます?
667             * 色??を指定した?合でも???に要求された状況コードに対応する色を返します?
668             * これは、同?況コードで色違いを作?することができな?とを意味します?
669             * 色??を指定しな??合?、?部の色配?から??番に色を割り当てます?
670             * 色を割り当てる?番は、状況コード?発生?です?よって、検索条件によって?
671             * 状況コード?現れる?が異なると、色も毎回異なることになります?
672             *
673             * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW 
674             * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
675             * よって、どのような色になるかは全くわかりません?
676             */
677            private static final class ColorMap {
678                    private static final Color[] CLR_ARY = new Color[] {
679                                    Color.BLUE      ,Color.CYAN   ,Color.GRAY ,Color.GREEN ,Color.LIGHT_GRAY ,Color.MAGENTA ,
680                                    Color.DARK_GRAY ,Color.ORANGE ,Color.PINK ,Color.RED   ,Color.YELLOW
681                    };
682                    private int lastCnt = 0;
683                    private final Map<String,Object[]> colMap = new TreeMap<String,Object[]>();
684                    private String maxLabel = "" ;          // ?長のラベル
685                    private int    maxlen   = -1 ;          // ?長のラベルのlength()
686    
687                    /**
688                     * 状況コードに対応した色オブジェクトを返します?
689                     *
690                     * 状況コードが初めて?された場合???番に?の色を割り当てます?
691                     * また?そ?時?ラベルも管?ます?ラベルと色のセ?は、?例作?時に利用されます?
692                     *
693                     * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW 
694                     * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
695                     * よって、どのような色になるかは全くわかりません?
696                     *
697                     * @param       fgj     状況コー?
698                     * @param       lbl     状況コード?ラベル
699                     * @return      状況コードに対応した色オブジェク?
700                     */
701                    public Color getColor( final String fgj,final String lbl ) {
702                            return getColor( fgj,lbl,null );
703                    }
704    
705                    /**
706                     * 状況コードに対応した色オブジェクトを返します?
707                     *
708                     * 状況コードが初めて?された場合?、引数の色??の色を割り当てます?
709                     * また?そ?時?ラベルも管?ます?ラベルと色のセ?は、?例作?時に利用されます?
710                     *
711                     * 色??を指定した?合でも???に要求された状況コードに対応する色を返します?
712                     * これは、同?況コードで色違いを作?することができな?とを意味します?
713                     * 色?? ?null の場合?、?動割り当てのメソ?と同じです?
714                     * よって、色??の?と、?動割り当てが同時に発生すると、異なる状況コードで
715                     * 同じ色が指定される可能性があります?で、混在して使用しな?ください?
716                     *
717                     * @param       fgj             状況コー?
718                     * @param       lbl             状況コード?ラベル
719                     * @param       colStr  状況コードに対応した色??(nullの場合?、?動割り当て)
720                     * @return      状況コードに対応した色オブジェク?
721                     */
722                    public Color getColor( final String fgj,final String lbl,final String colStr ) {
723                            if( fgj == null ) { return LABEL_COLOR; }
724                            if( lbl != null ) {
725                                    int len = lbl.length();
726                                    if( len > maxlen ) { maxLabel = lbl; maxlen = len; }
727                            }
728    
729                            Object[] obj = colMap.get( fgj );
730                            if( obj == null ) {
731                                    obj = new Object[2];
732                                    obj[0] = lbl;
733                                    obj[1] = (colStr != null) ? StringUtil.getColorInstance( colStr ) : uniqColor();
734    
735                                    colMap.put( fgj,obj );
736                            }
737    
738                            return (Color)obj[1] ;
739                    }
740    
741                    /**
742                     * ?のシーケンスに対応した?ユニ?クな色オブジェクトを返します?
743                     *
744                     * ?カウンターを+?しながら、?部の色オブジェクトを返します?
745                     *
746                     * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW 
747                     * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
748                     * よって、どのような色になるかは全くわかりません?
749                     *
750                     * @return      ユニ?クな色オブジェク?
751                     */
752                    public Color uniqColor() {
753                            Color col = null;
754                            if( lastCnt < CLR_ARY.length ) {
755                                    col = CLR_ARY[lastCnt++];
756                            }
757                            else {
758                                    int R=(int)(Math.random()*256);
759                                    int G=(int)(Math.random()*256);
760                                    int B=(int)(Math.random()*256);
761                                    col = new Color(R,G,B);
762                            }
763    
764                            return col;
765                    }
766    
767                    /**
768                     * ?で管?て?、ラベル(String)と色オブジェク?Color)の コレクションを返します?
769                     *
770                     * ?で管?て?コレクションです?
771                     * こ?コレクションは、状況コードでソートされて?す?
772                     * コレクションの中身は、オブジェクト?列となっており、[0]は、String型?ラベル、[1]は?
773                     * Color型?色です?
774                     *
775                     * @return      ラベル(String)と色オブジェク?Color)の コレクション
776                     */
777                    public Collection<Object[]> values() {
778                            return colMap.values();
779                    }
780    
781                    /**
782                     * 登録されたラベル??で、最も文字数が長?ベルを返します?
783                     *
784                     * 凡例で、ラベルの?長を求める?に利用できます?
785                     * ただし?簡易的に、length() 計算して??なので、英語?日本語混在??
786                     * プロポ?ショナルフォント使用時?厳??長の??ではありません?
787                     *
788                     * @return      ??数が長?ベル
789                     */
790                    public String getMaxLengthLabel() { return maxLabel; }
791            }
792    
793            /**
794             * 時間??を数字に変換します?
795             *
796             * "0800" は?80に?2100" は?260 に変換します?
797             * つまり??位?値に変換します?秒?単位?、?り捨てます?
798             * ここでは、時間文字?が?08:00 の様に?:" を含??合?、削除し?
799             * ?ケタ以上?場合?、前から?ケタ?使?す?
800             * ?ケタ以下(1,2,3ケタ?でも?先?に 0 埋めで、時間文字?にします?
801             * ?ケタ、およ?、null の場合?、defTm 初期値 を返します?
802             *
803             * @param       val     時間??の値(0800 など)
804             * @param       defTm   引数の時間???null の場合?初期値
805             *
806             * @return      時間??を数字に変換した結果( 80 など)
807             */
808            private int getStr2Time( final String val , final int defTm ) {
809                    if( val == null || val.isEmpty() ) { return defTm; }
810    
811                    // 桁数によって、???仕方が変わるため?
812                    int rtnInt = 0;
813                    switch( val.length() ) {
814                            case    1:
815                            case    2:      rtnInt = Integer.parseInt( val ); break;
816                            case    3:      rtnInt = Integer.parseInt( val.substring( 0,1 ) )*60 + Integer.parseInt( val.substring( 1,3 ) ); break;
817                            default  :      rtnInt = Integer.parseInt( val.substring( 0,2 ) )*60 + Integer.parseInt( val.substring( 2,4 ) ); break;
818                    }
819    
820                    return rtnInt ;
821            }
822    
823            /**
824             * 日時文字?を数字に変換します?
825             *
826             * 日時文字?は、yyyyMMdd また?、yyyyMMddhhmmss 形式とします?
827             * これを?エポックタイ?ら?経過時間の ?位?値を求めます?
828             * 具体的には、Calendar オブジェクト? getTimeInMillis() の結果を?
829             * 60000 で割り算した?を作?します?
830             * よって、Calendar オブジェクト作?時も、秒?単位??捨てます?
831             * 引数?null の場合?、現在時刻より、作?します?
832             *
833             * @param       val     日時文字?の値(yyyyMMdd また?、yyyyMMddhhmmss 形?など)
834             *
835             * @return      日時文字?を?換算した数?
836             */
837            private long getStr2Date( final String val ) {
838                    Calendar cal = Calendar.getInstance();
839                    str2DateTime = 0;
840                    if( val == null ) {
841                            cal.set( Calendar.HOUR_OF_DAY, 0 );             // 5.3.5.0 (2011/05/01) 時間の解決規則が適用されるため??時」?は、setメソ?で 0 にセ?する?
842                            cal.clear( Calendar.MINUTE );
843                            cal.clear( Calendar.SECOND );
844                            cal.clear( Calendar.MILLISECOND );
845                    }
846                    else if( val.length() == 8 ) {
847                            cal.clear();
848                            cal.set( Integer.parseInt( val.substring( 0,4 ) ) ,                     // 年
849                                             Integer.parseInt( val.substring( 4,6 ) ) - 1,          // ?0から始ま?
850                                             Integer.parseInt( val.substring( 6,8 ) )                       // 日
851                            );
852                    }
853                    else {
854                            cal.clear();
855                            cal.set( Integer.parseInt( val.substring( 0,4 ) ) ,                     // 年
856                                             Integer.parseInt( val.substring( 4,6 ) ) - 1,          // ?0から始ま?
857                                             Integer.parseInt( val.substring( 6,8 ) ) ,                     // 日
858                                             Integer.parseInt( val.substring( 8,10 ) ) ,            // ?
859                                             Integer.parseInt( val.substring( 10,12 ) )             // ?
860                            );
861                            str2DateTime = Integer.parseInt( val.substring( 8,10 ) ) * 60 + Integer.parseInt( val.substring( 10,12 ) ) ;
862                    }
863                    return (cal.getTimeInMillis() / 60000L);                // ?位に変換する?
864            }
865    
866            // 5.6.5.0 (2013/06/07) 曜日??タを?列で持っておきます?
867            private static final String[] DAY_OF_WEEK_ja = new String[] { "?,"日","?,"火","水","木","?,"? };    // [0]="? は??? の余計算で?7=0 になる為?
868    
869            /**
870             * 数??を時間文字?に変換します?
871             *
872             * 480 は?08" に?260 は?21" に変換します?
873             * 引数の時間は、?を表す整数です??4時間表記であれば? ??1440 の?で収まりますが?
874             * 期間が長??合?、その値を?ます?また??4時間を?る?合?? に戻ります?
875             * ??にする場合??単位???なので?0(?で割り算して、余?、?り捨てます?
876             * step は?0(?単位?表示時に飛?す数です?step=1 なら?60(?単位?step=2 なら?120(?
877             * 単位となります?stepが?24 以下?場合?、そのまま?4時間表記で構いませんが?
878             * それを?ると時間ではなく?日数表記に?替わります?
879             *
880             * @og.rev 5.6.5.0 (2013/06/07) 月単位?場合?、曜日を表示します?
881             *
882             * @param       timeVal 引数の時間整数(?
883             * @param       step    60?位?ス?プ数( 10,30,60,720,1440 単位となるよ?調整)
884             * @param       week    カレン?ラスの曜日フィール?DAY_OF_WEEK)
885             *
886             * @return      数字を時間??に変換した結果( "08" など)
887             */
888    //      private String getTime2Str( final int timeVal, final int step ) {
889            private String getTime2Str( final int timeVal, final int step, final int week ) {
890    
891                    int dtm = (timeVal / 60 / 24 );                 // 日
892                    int htm = ((timeVal / 60) % 24 );               // ??4時間制)
893                    int mtm = (timeVal % 60 );                              // ??0?制)
894    
895                    StringBuilder rtn = new StringBuilder();
896    
897                    if( step >= 1440 ) {
898    //                      rtn.append( dtm ).append( "d" );                                                        // 5.6.5.0 (2013/06/07) 相対日付?
899                            rtn.append( DAY_OF_WEEK_ja[ ( dtm + week ) % 7 ] );                     // 曜日を表示
900                    }
901                    else {
902                            if( htm < 10 ) { rtn.append( "0" ); }
903                            rtn.append( htm );
904    
905                            if( step < 60 ) { 
906                                    rtn.append( ":" );
907                                    if( mtm < 10 ) { rtn.append( "0" ); }
908                                    rtn.append( mtm );
909                            }
910                    }
911    
912                    return rtn.toString();
913            }
914    
915            // 引数に?を追?る?
916    
917            /**
918             * 表示?の編?並び替?が可能かど?を返しま?
919             *
920             * @return      表示?の編?並び替?が可能かど?(false:不可能)
921             */
922            @Override
923            public boolean isEditable() {
924                    return false;
925            }
926    }