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 */
016package org.opengion.plugin.io;
017
018import java.io.BufferedReader;
019import java.io.IOException;
020
021import org.opengion.fukurou.util.StringUtil;
022import org.opengion.hayabusa.common.HybsSystem;
023import org.opengion.hayabusa.common.HybsSystemException;
024import org.opengion.hayabusa.db.DBTableModelUtil;
025import org.opengion.hayabusa.io.AbstractTableReader;
026
027/**
028 * 指定の区切り記号(初期値:タブ区切り)ファイルの読み取りクラスです。
029 *
030 * 名前,データの入力部のみオーバーライドすれば,各種入力フォーマットに合わせた
031 * サブクラスを実現する事が可能です。
032 *
033 * @og.group ファイル入力
034 *
035 * @version  4.0
036 * @author   Kazuhiko Hasegawa
037 * @since    JDK5.0,
038 */
039public class TableReader_Default extends AbstractTableReader {
040        //* このプログラムのVERSION文字列を設定します。   {@value} */
041        private static final String VERSION = "5.2.1.0 (2010/10/01)" ;
042
043        /**
044         * DBTableModel から 各形式のデータを作成して,BufferedReader より読み取ります。
045         * コメント/空行を除き、最初の行は、必ず項目名が必要です。
046         * それ以降は、コメント/空行を除き、データとして読み込んでいきます。
047         * このメソッドは、EXCEL 読み込み時に使用します。
048         *
049         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
050         * @see #isExcel()
051         */
052        @Override
053        public void readDBTable() {
054                String errMsg = "このクラスでは実装されていません。";
055                throw new UnsupportedOperationException( errMsg );
056        }
057
058        /**
059         * DBTableModel から 各形式のデータを作成して,BufferedReader より読み取ります。
060         * コメント/空行を除き、最初の行は、必ず項目名が必要です。
061         * それ以降は、コメント/空行を除き、データとして読み込んでいきます。
062         *
063         * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。
064         * @og.rev 3.5.4.2 (2003/12/15) writer の null チェックを廃止します。
065         * @og.rev 3.5.4.3 (2004/01/05) 引数に、BufferedReader を受け取ル要に変更します。
066         * @og.rev 3.5.4.5 (2004/01/23) カラム名の外部指定を優先して使用する。
067         * @og.rev 5.1.6.0 (2010/05/01) readDBTableのエラーチェック強化
068         * @og.rev 5.1.6.0 (2010/05/01) skipRowCountの追加
069         * @og.rev 5.2.0.0 (2010/09/01) ""で囲われているデータに改行が入っていた場合の対応
070         * @og.rev 5.2.1.0 (2010/10/01) AbstractTableReader.java と重複している箇所の対応
071         *
072         * @param   reader BufferedReaderオブジェクト
073         */
074        @Override
075        public void readDBTable( final BufferedReader reader ) {
076                try {
077                        String line;
078                        String[] names = null;
079                        int numberOfRows = 0;
080//                      char  sepa = separator.charAt( 0 );
081                        char  sepa = getSeparator().charAt( 0 );        // 5.2.0.0 (2010/09/01)
082
083                        boolean nameNoSet = true;
084                        table = DBTableModelUtil.newDBTable();
085
086                        // 3.5.4.5 (2004/01/23) カラム名の外部指定を優先して使用する。
087                        if( columns != null && columns.length() > 0 ) {
088                                names = StringUtil.csv2Array( columns );
089                                table.init( names.length );
090                                setTableDBColumn( names ) ;
091                                nameNoSet = false;
092                        }
093
094//                      int skip = skipRowCount;                                                // 5.1.6.0 (2010/05/01)
095                        int skip = getSkipRowCount();                                   // 5.2.0.0 (2010/09/01)
096                        while((line = reader.readLine()) != null) {
097                                // 5.2.0.0 (2010/09/01) ""で囲われているデータに改行が入っていた場合の対応
098//                              int quotCount = StringUtil.countChar( line, '"' );
099//                              if( quotCount % 2 == 1 ) {
100//                                      String addLine = null;
101//                                      while(quotCount % 2 == 1 && (addLine = reader.readLine()) != null) {
102//                                              line +=  HybsSystem.CR + addLine;
103//                                              quotCount += StringUtil.countChar( addLine, '"' );
104//                                      }
105//                              }
106                                // 5.2.1.0 (2010/10/01) findbugs 対策(文字列の + 連結と、奇数判定ロジック)
107                                int quotCount = StringUtil.countChar( line, '"' );
108                                if( quotCount % 2 != 0 ) {
109                                        String addLine = null;
110                                        StringBuilder buf = new StringBuilder( line );
111                                        while(quotCount % 2 != 0 && (addLine = reader.readLine()) != null) {
112                                                buf.append( HybsSystem.CR ).append( addLine );
113                                                quotCount += StringUtil.countChar( addLine, '"' );
114                                        }
115                                        line = buf.toString();
116                                }
117
118                                if( skip > 0 ) { skip--; continue; }         // 5.1.6.0 (2010/05/01)
119                                if( line.length() == 0 ) { continue; }
120                                if( line.charAt( 0 ) == '#' ) {
121                                        String key = line.substring( 0,5 );
122                                        if( nameNoSet && ( key.equalsIgnoreCase( "#NAME" ) )) {
123                                                // 超イレギュラー処理 最初の TAB_SEPARATOR 以前の文字は無視する。
124                                                String line2 = line.substring( line.indexOf( sepa )+1 );
125                                                names = StringUtil.csv2Array( line2 ,sepa );
126                                                table.init( names.length );
127                                                setTableDBColumn( names ) ;
128                                                nameNoSet = false;
129                                        }
130                                        else  { continue; }
131                                }
132                                else {
133                                        if( nameNoSet ) {
134                                                String errMsg = "#NAME が見つかる前にデータが見つかりました。";
135                                                throw new HybsSystemException( errMsg );
136                                        }
137                                        if( numberOfRows < getMaxRowCount() ) {
138                                                setTableColumnValues( readData( line,names.length ) );          // 5.2.1.0 (2010/10/01)
139//                                              table.addColumnValues( readData( line,names.length ) );
140                                                numberOfRows ++ ;
141                                        }
142                                        else {
143                                                table.setOverflow( true );
144                                        }
145                                }
146                        }
147
148                        // 5.1.6.0 (2010/05/01) readDBTableのエラーチェック強化
149                        if( nameNoSet ) {
150                                String errMsg = "ファイルから有効なデータが見つかりませんでした。";
151                                throw new HybsSystemException( errMsg );
152                        }
153                }
154                catch ( IOException ex ) {
155                        String errMsg = "ファイル読込みエラー[" + reader + "]"  ;
156                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
157                }
158        }
159}