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    }