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.hayabusa.io;
017    
018    import java.sql.Connection;
019    // import java.sql.Date;
020    import java.sql.ResultSet;
021    import java.sql.ResultSetMetaData;
022    import java.sql.SQLException;
023    import java.sql.Statement;
024    // import java.sql.Types;
025    // import java.util.Locale;
026    
027    import org.opengion.fukurou.util.Closer;
028    import org.opengion.fukurou.util.LogWriter;
029    
030    import org.jfree.data.time.TimeSeriesCollection;
031    import org.jfree.data.time.TimeSeries;
032    import org.jfree.data.time.RegularTimePeriod;
033    // import org.jfree.data.time.Year;                             // Year  (int year) 
034    // import org.jfree.data.time.Month;                    // Month (int month, int year) 
035    // import org.jfree.data.time.Day;                              // Day   (int day, int month, int year)
036    // import org.jfree.data.time.Hour;                             // Hour  (int hour, int day, int month, int year)
037    // import org.jfree.data.time.Minute;                   // Minute(int minute, int hour, int day, int month, int year)
038    import org.jfree.data.time.Second;                      // Second(int second, int minute, int hour, int day, int month, int year) 
039    
040    /**
041     * HybsTimeSeriesCollection は、org.jfree.data.time.TimeSeriesCollection を継承したサブクラスでã€?
042     * オブジェクト作æ?とともに JDBC接続して、TimeSeries ãƒ??タを作æ?しã?セãƒ?ƒˆしますã?
043     * TimeSeriesCollection は、XYDataset のサブクラスですã?
044     *
045     * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合ã?縦持ですã?
046     *  ?‘.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処ç�?
047     * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合ã?横持ですã?
048     *  ?’.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横æŒ?
049     * series のキーブレイク処ç�?�•れますã?
050     *
051     * Stacked**** は、各シリーズのy(値)をã?次ã€?�«åŠ?®—しますã?å�?™‚間で実績数をセãƒ?ƒˆしã?æœ?µ‚時刻に
052     * どれだけå?来上がったかを表示するのに便利ですã?
053     *
054     * @og.rev 5.6.1.0 (2013/02/01) 新規作æ?
055     *
056     * @version  0.9.0  2001/05/05
057     * @author   Kazuhiko Hasegawa
058     * @since    JDK1.1,
059     */
060    public class HybsTimeSeriesCollection extends TimeSeriesCollection {
061            private static final long serialVersionUID = 561020130201L ;
062    
063            private final boolean vhFlag ;          // selectæ–?�§ series を縦持V(true)か横持H(false)かをæŒ?®šã?
064            private final boolean isStacked ;       // ãƒ??タのåŠ?®—å?ç�?‚’行うかどã�?�‹??  true:行う/false:行わなã�?
065    
066            /**
067             * チャートタイプを引数にとるã?コンストラクター
068             *
069             * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合ã?縦持ですã?
070             *  ?‘.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処ç�?
071             * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合ã?横持ですã?
072             *  ?’.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横æŒ?
073             * series のキーブレイク処ç�?�•れますã?
074             *
075             * Stacked**** は、各シリーズのy(値)をã?次ã€?�«åŠ?®—しますã?å�?™‚間で実績数をセãƒ?ƒˆしã?æœ?µ‚時刻に
076             * どれだけå?来上がったかを表示するのに便利ですã?
077             *
078             * @param type  チャートタイãƒ?
079             */
080            public HybsTimeSeriesCollection( final String type ) {
081                    super();
082                    vhFlag    = ( type.endsWith( "V" ) ) ;                          // V:縦æŒ?= true / H:横æŒ?= false
083                    isStacked = ( type.startsWith( "Stacked" ) ) ;          // Stacked:積み上げ = true
084            }
085    
086            /**
087             * HybsTimeSeriesCollection オブジェクトã?å†?ƒ¨に、DB検索結果のãƒ??タを設定しますã?
088             *
089             * こã?メソãƒ?ƒ‰は、series の 縦æŒ?横持を、コンストラクターで判定してã�?�¾すã?
090             * TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合ã?縦持ですã?
091             *  ?‘.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処ç�?
092             * TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合ã?横持ですã?
093             *  ?’.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横æŒ?
094             * series のキーブレイク処ç�?�•れますã?
095             *
096             * @param con  the connection.
097             * @param query  the query.
098             *
099             */
100            public void executeQuery( final Connection con, final String query ) throws SQLException {
101                    if( vhFlag ) { innerQueryV( con,query ); }
102                    else             { innerQueryH( con,query ); }
103            }
104    
105            /**
106             * HybsTimeSeriesCollection オブジェクトã?å†?ƒ¨に、DB検索結果のãƒ??タを設定しまã�?縦æŒ?ã€?
107             * こã?メソãƒ?ƒ‰が呼ばれるのは、TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合ですã?
108             *
109             * こã?メソãƒ?ƒ‰は、series の 縦持を想定してã�?�¾すã?
110             *  ?‘.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処ç�?
111             * series のキーブレイク処ç�?�•れますã?
112             *
113             * @param con  the connection.
114             * @param query  the query.
115             *
116             */
117            private void innerQueryV( final Connection con, final String query ) throws SQLException {
118    
119                    Statement statement = null;
120                    ResultSet resultSet = null;
121                    try {
122                            statement = con.createStatement();
123                            resultSet = statement.executeQuery(query);
124                            ResultSetMetaData metaData = resultSet.getMetaData();
125    
126                            int columnCount = metaData.getColumnCount();
127    
128                            if(columnCount < 3) {
129                                    String errMsg = "HybsTimeSeriesCollection.innerQueryV() : 実行できませんã€?n"
130                                                            + "select series,x(時間),y(値) は、最低å¿?¦�ですã?それ以降ã?無視しますã?"
131                                                            + " SQL=" + query ;
132                                    throw new SQLException( errMsg );
133                            }
134    
135                            String bkSeries = null;         // キーブレイクのための過去のSeries
136                            double bkyn     = 0.0;
137    
138                            TimeSeries timeSeries = null;
139                            while (resultSet.next()) {
140                                    // first column contains the row key...
141                                    String seriVal  = resultSet.getString(1);                                               // 縦持ちの場合ã?、データの値がシリーズ名になるã?
142                                    if( seriVal != null && !seriVal.equals( bkSeries ) ) {
143                                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセãƒ?ƒˆ
144                                            timeSeries = new TimeSeries( seriVal );
145                                            bkSeries = seriVal ;
146                                            bkyn     = 0.0;
147                                    }
148    
149                                    String dateVal  = resultSet.getString(2);                       // x(時間)
150                                    RegularTimePeriod timep = getTimePeriod( dateVal );
151    
152                                    double yn = resultSet.getDouble(3);                                     // y(値)
153                                    bkyn = ( isStacked ) ? bkyn + yn : yn ;                         // isStacked = true の場合ã?、加算してã�?��
154    
155                                    timeSeries.add( timep, bkyn );
156                            }
157                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセãƒ?ƒˆ
158                    }
159                    finally {
160                            Closer.resultClose( resultSet ) ;
161                            Closer.stmtClose( statement ) ;
162                    }
163            }
164    
165            /**
166             * HybsTimeSeriesCollection オブジェクトã?å†?ƒ¨に、DB検索結果のãƒ??タを設定しまã�?横æŒ?ã€?
167             * こã?メソãƒ?ƒ‰が呼ばれるのは、TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合ですã?
168             *
169             * こã?メソãƒ?ƒ‰は、series の 横持を想定してã�?�¾すã?
170             *  ?’.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横æŒ?
171             * で、y1, y2 ・・・ ã�?series として処ç�?�•れますã?
172             * series のラベルは、y1, y2 ・・・のカラãƒ?��になりますã?
173             *
174             * @param con  the connection.
175             * @param query  the query.
176             */
177            private void innerQueryH( final Connection con, final String query ) throws SQLException {
178    
179                    Statement statement = null;
180                    ResultSet resultSet = null;
181                    try {
182                            statement = con.createStatement();
183                            resultSet = statement.executeQuery(query);
184                            ResultSetMetaData metaData = resultSet.getMetaData();
185    
186                            int columnCount = metaData.getColumnCount();
187    
188                            if(columnCount < 2) {
189                                    String errMsg = "HybsTimeSeriesCollection.innerQueryH() : 実行できませんã€?n"
190                                                            + "select x(時間),y1(値),y2(値) , ・・・・ は、最低å¿?¦�ですã?"
191                                                            + " SQL=" + query ;
192                                    throw new SQLException( errMsg );
193                            }
194    
195                            // å�?‚·リーズに対するカラãƒ?‚¿イプを先に求めておく
196                            int seriSu = columnCount-1;                             // カラãƒ?•°-1( x(時間) )
197                            TimeSeries[] timeSeries = new TimeSeries[seriSu];
198                            double[]     bkyn       = new double[seriSu];
199                            for( int j=0; j<seriSu; j++ ) {
200                                    timeSeries[j] = new TimeSeries( metaData.getColumnLabel(j+2) );         // 横持ã?場合ã?、カラãƒ?��をシリーズ名にするã€?
201                                    bkyn[j]       = 0.0;
202                            }
203    
204                            while (resultSet.next()) {
205                                    // first column contains the row key...
206                                    String dateVal  = resultSet.getString(1);                       // x(時間)
207                                    RegularTimePeriod timep = getTimePeriod( dateVal );
208    
209                                    for( int j=0; j<seriSu; j++ ) {
210                                            double yn = resultSet.getDouble(j+2);
211                                            bkyn[j] = ( isStacked ) ? bkyn[j] + yn : yn ;   // isStacked = true の場合ã?、加算してã�?��
212                                            timeSeries[j].add( timep, bkyn[j] );
213                                    }
214                            }
215    
216                            for( int j=0; j<seriSu; j++ ) {
217                                    addSeries( timeSeries[j] );
218                            }
219                    }
220                    finally {
221                            Closer.resultClose( resultSet ) ;
222                            Closer.stmtClose( statement ) ;
223                    }
224            }
225    
226            /**
227             * 日付文字å? から、RegularTimePeriodオブジェクãƒ?を生成しますã?
228             *
229             * こã?メソãƒ?ƒ‰では、日付文字å? としてã€?yyyyMMdd" 形式と "yyyyMMddhhmmss" 形式ã?み認めてã�?�¾すã?
230             *  ?‘.8文字以上あるå?合ã?yyyyMMdd 部åˆ?‚’åˆ?‚Š出して、年月日æƒ??を作æ?しますã?
231             *  ?’.14文字以上あるå?合ã?残りの、hhmmss 部åˆ?‚’åˆ?‚Š出して、時åˆ?§’情報を作æ?しますã?
232             *  ?“.それ以外ã?場合ã?ã€?20100101000000" として、å?ç�?�—ますã?
233             *
234             * @param       dateVal 日付文字å?(yyyyMMddhhmmss 形å¼?
235             *
236             * @return      RegularTimePeriodオブジェクãƒ?Secondオブジェクãƒ?
237             */
238            private RegularTimePeriod getTimePeriod( final String dateVal ) {
239                    int second=0, minute=0, hour=0, day=1, month=1, year=2010 ;
240                    if( dateVal != null ) {
241                            if( dateVal.length() >= 8 ) {
242                                    year  = Integer.parseInt( dateVal.substring( 0,4 ) );
243                                    month = Integer.parseInt( dateVal.substring( 4,6 ) );
244                                    day   = Integer.parseInt( dateVal.substring( 6,8 ) );
245                            }
246                            if( dateVal.length() >= 14 ) {
247                                    hour   = Integer.parseInt( dateVal.substring( 8,10 ) );
248                                    minute = Integer.parseInt( dateVal.substring( 10,12 ) );
249                                    second = Integer.parseInt( dateVal.substring( 12,14 ) );
250                            }
251                    }
252    
253                    return new Second( second,minute,hour,day,month,year ) ;
254            }
255    
256    //      private Number getNumber( final Object objVal , final int columnType ) {
257    //              Number value = null;
258    //
259    //              switch (columnType) {
260    //                      case Types.TINYINT:
261    //                      case Types.SMALLINT:
262    //                      case Types.INTEGER:
263    //                      case Types.BIGINT:
264    //                      case Types.FLOAT:
265    //                      case Types.DOUBLE:
266    //                      case Types.DECIMAL:
267    //                      case Types.NUMERIC:
268    //                      case Types.REAL: {
269    //                              value = (Number)objVal;
270    //                              break;
271    //                      }
272    //                      case Types.DATE:
273    //                      case Types.TIME:
274    //                      case Types.TIMESTAMP: {
275    //                              Date date = (Date) objVal;
276    //                              value = Long.valueOf(date.getTime());
277    //                              break;
278    //                      }
279    //                      case Types.CHAR:
280    //                      case Types.VARCHAR:
281    //                      case Types.LONGVARCHAR: {
282    //                              String string = (String)objVal;
283    //                              try {
284    //                                      value = Double.valueOf(string);
285    //                              }
286    //                              catch (NumberFormatException ex) {
287    //      //                              LogWriter.log( ex );
288    //                                      // suppress (value defaults to null)
289    //                              }
290    //                              break;
291    //                      }
292    //                      default:
293    //                              // not a value, can't use it (defaults to null)
294    //                              break;
295    //              }
296    //              return value;
297    //      }
298    }