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             * @throws SQLException ãƒ??タベã?ス実行エラーが発生したå?å�?
099             *
100             */
101            public void executeQuery( final Connection con, final String query ) throws SQLException {
102                    if( vhFlag ) { innerQueryV( con,query ); }
103                    else             { innerQueryH( con,query ); }
104            }
105    
106            /**
107             * HybsTimeSeriesCollection オブジェクトã?å†?ƒ¨に、DB検索結果のãƒ??タを設定しまã�?縦æŒ?ã€?
108             * こã?メソãƒ?ƒ‰が呼ばれるのは、TimeSeriesLineV、TimeSeriesBarV、StackedTimeSeriesLineV の場合ですã?
109             *
110             * こã?メソãƒ?ƒ‰は、series の 縦持を想定してã�?�¾すã?
111             *  ?‘.select series,x(時間),y(値) from XX order by series,x(時間) の縦持ちで、series のキーブレイク処ç�?
112             * series のキーブレイク処ç�?�•れますã?
113             *
114             * @param con  the connection.
115             * @param query  the query.
116             *
117             */
118            private void innerQueryV( final Connection con, final String query ) throws SQLException {
119    
120                    Statement statement = null;
121                    ResultSet resultSet = null;
122                    try {
123                            statement = con.createStatement();
124                            resultSet = statement.executeQuery(query);
125                            ResultSetMetaData metaData = resultSet.getMetaData();
126    
127                            int columnCount = metaData.getColumnCount();
128    
129                            if(columnCount < 3) {
130                                    String errMsg = "HybsTimeSeriesCollection.innerQueryV() : 実行できませんã€?n"
131                                                            + "select series,x(時間),y(値) は、最低å¿?¦�ですã?それ以降ã?無視しますã?"
132                                                            + " SQL=" + query ;
133                                    throw new SQLException( errMsg );
134                            }
135    
136                            String bkSeries = null;         // キーブレイクのための過去のSeries
137                            double bkyn     = 0.0;
138    
139                            TimeSeries timeSeries = null;
140                            while (resultSet.next()) {
141                                    // first column contains the row key...
142                                    String seriVal  = resultSet.getString(1);                                               // 縦持ちの場合ã?、データの値がシリーズ名になるã?
143                                    if( seriVal != null && !seriVal.equals( bkSeries ) ) {
144                                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセãƒ?ƒˆ
145                                            timeSeries = new TimeSeries( seriVal );
146                                            bkSeries = seriVal ;
147                                            bkyn     = 0.0;
148                                    }
149    
150                                    String dateVal  = resultSet.getString(2);                       // x(時間)
151                                    RegularTimePeriod timep = getTimePeriod( dateVal );
152    
153                                    double yn = resultSet.getDouble(3);                                     // y(値)
154                                    bkyn = ( isStacked ) ? bkyn + yn : yn ;                         // isStacked = true の場合ã?、加算してã�?��
155    
156                                    timeSeries.add( timep, bkyn );
157                            }
158                            if( timeSeries != null ) { addSeries( timeSeries ); }           // キーブレイクでセãƒ?ƒˆ
159                    }
160                    finally {
161                            Closer.resultClose( resultSet ) ;
162                            Closer.stmtClose( statement ) ;
163                    }
164            }
165    
166            /**
167             * HybsTimeSeriesCollection オブジェクトã?å†?ƒ¨に、DB検索結果のãƒ??タを設定しまã�?横æŒ?ã€?
168             * こã?メソãƒ?ƒ‰が呼ばれるのは、TimeSeriesLineH、TimeSeriesBarH、StackedTimeSeriesLineH の場合ですã?
169             *
170             * こã?メソãƒ?ƒ‰は、series の 横持を想定してã�?�¾すã?
171             *  ?’.select x(時間),y1(値),y2(値),・・・ from XX  order by x(時間) の横æŒ?
172             * で、y1, y2 ・・・ ã�?series として処ç�?�•れますã?
173             * series のラベルは、y1, y2 ・・・のカラãƒ?��になりますã?
174             *
175             * @param con  the connection.
176             * @param query  the query.
177             */
178            private void innerQueryH( final Connection con, final String query ) throws SQLException {
179    
180                    Statement statement = null;
181                    ResultSet resultSet = null;
182                    try {
183                            statement = con.createStatement();
184                            resultSet = statement.executeQuery(query);
185                            ResultSetMetaData metaData = resultSet.getMetaData();
186    
187                            int columnCount = metaData.getColumnCount();
188    
189                            if(columnCount < 2) {
190                                    String errMsg = "HybsTimeSeriesCollection.innerQueryH() : 実行できませんã€?n"
191                                                            + "select x(時間),y1(値),y2(値) , ・・・・ は、最低å¿?¦�ですã?"
192                                                            + " SQL=" + query ;
193                                    throw new SQLException( errMsg );
194                            }
195    
196                            // å�?‚·リーズに対するカラãƒ?‚¿イプを先に求めておく
197                            int seriSu = columnCount-1;                             // カラãƒ?•°-1( x(時間) )
198                            TimeSeries[] timeSeries = new TimeSeries[seriSu];
199                            double[]     bkyn       = new double[seriSu];
200                            for( int j=0; j<seriSu; j++ ) {
201                                    timeSeries[j] = new TimeSeries( metaData.getColumnLabel(j+2) );         // 横持ã?場合ã?、カラãƒ?��をシリーズ名にするã€?
202                                    bkyn[j]       = 0.0;
203                            }
204    
205                            while (resultSet.next()) {
206                                    // first column contains the row key...
207                                    String dateVal  = resultSet.getString(1);                       // x(時間)
208                                    RegularTimePeriod timep = getTimePeriod( dateVal );
209    
210                                    for( int j=0; j<seriSu; j++ ) {
211                                            double yn = resultSet.getDouble(j+2);
212                                            bkyn[j] = ( isStacked ) ? bkyn[j] + yn : yn ;   // isStacked = true の場合ã?、加算してã�?��
213                                            timeSeries[j].add( timep, bkyn[j] );
214                                    }
215                            }
216    
217                            for( int j=0; j<seriSu; j++ ) {
218                                    addSeries( timeSeries[j] );
219                            }
220                    }
221                    finally {
222                            Closer.resultClose( resultSet ) ;
223                            Closer.stmtClose( statement ) ;
224                    }
225            }
226    
227            /**
228             * 日付文字å? から、RegularTimePeriodオブジェクãƒ?を生成しますã?
229             *
230             * こã?メソãƒ?ƒ‰では、日付文字å? としてã€?yyyyMMdd" 形式と "yyyyMMddhhmmss" 形式ã?み認めてã�?�¾すã?
231             *  ?‘.8文字以上あるå?合ã?yyyyMMdd 部åˆ?‚’åˆ?‚Š出して、年月日æƒ??を作æ?しますã?
232             *  ?’.14文字以上あるå?合ã?残りの、hhmmss 部åˆ?‚’åˆ?‚Š出して、時åˆ?§’情報を作æ?しますã?
233             *  ?“.それ以外ã?場合ã?ã€?20100101000000" として、å?ç�?�—ますã?
234             *
235             * @param       dateVal 日付文字å?(yyyyMMddhhmmss 形å¼?
236             *
237             * @return      RegularTimePeriodオブジェクãƒ?Secondオブジェクãƒ?
238             */
239            private RegularTimePeriod getTimePeriod( final String dateVal ) {
240                    int second=0, minute=0, hour=0, day=1, month=1, year=2010 ;
241                    if( dateVal != null ) {
242                            if( dateVal.length() >= 8 ) {
243                                    year  = Integer.parseInt( dateVal.substring( 0,4 ) );
244                                    month = Integer.parseInt( dateVal.substring( 4,6 ) );
245                                    day   = Integer.parseInt( dateVal.substring( 6,8 ) );
246                            }
247                            if( dateVal.length() >= 14 ) {
248                                    hour   = Integer.parseInt( dateVal.substring( 8,10 ) );
249                                    minute = Integer.parseInt( dateVal.substring( 10,12 ) );
250                                    second = Integer.parseInt( dateVal.substring( 12,14 ) );
251                            }
252                    }
253    
254                    return new Second( second,minute,hour,day,month,year ) ;
255            }
256    
257    //      private Number getNumber( final Object objVal , final int columnType ) {
258    //              Number value = null;
259    //
260    //              switch (columnType) {
261    //                      case Types.TINYINT:
262    //                      case Types.SMALLINT:
263    //                      case Types.INTEGER:
264    //                      case Types.BIGINT:
265    //                      case Types.FLOAT:
266    //                      case Types.DOUBLE:
267    //                      case Types.DECIMAL:
268    //                      case Types.NUMERIC:
269    //                      case Types.REAL: {
270    //                              value = (Number)objVal;
271    //                              break;
272    //                      }
273    //                      case Types.DATE:
274    //                      case Types.TIME:
275    //                      case Types.TIMESTAMP: {
276    //                              Date date = (Date) objVal;
277    //                              value = Long.valueOf(date.getTime());
278    //                              break;
279    //                      }
280    //                      case Types.CHAR:
281    //                      case Types.VARCHAR:
282    //                      case Types.LONGVARCHAR: {
283    //                              String string = (String)objVal;
284    //                              try {
285    //                                      value = Double.valueOf(string);
286    //                              }
287    //                              catch (NumberFormatException ex) {
288    //      //                              LogWriter.log( ex );
289    //                                      // suppress (value defaults to null)
290    //                              }
291    //                              break;
292    //                      }
293    //                      default:
294    //                              // not a value, can't use it (defaults to null)
295    //                              break;
296    //              }
297    //              return value;
298    //      }
299    }