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.io;
017    
018    import java.io.BufferedReader;
019    import java.io.IOException;
020    import java.io.InputStream;
021    import java.util.ArrayList;
022    import java.util.List;
023    import java.util.zip.ZipEntry;
024    import java.util.zip.ZipFile;
025    
026    import javax.xml.parsers.DocumentBuilder;
027    import javax.xml.parsers.DocumentBuilderFactory;
028    import javax.xml.parsers.ParserConfigurationException;
029    
030    import org.opengion.fukurou.util.StringUtil;
031    import org.opengion.fukurou.util.Closer;                        // 5.5.2.6 (2012/05/25)
032    import org.opengion.hayabusa.common.HybsSystem;
033    import org.opengion.hayabusa.common.HybsSystemException;
034    import org.opengion.hayabusa.db.DBTableModelUtil;
035    import org.w3c.dom.Document;
036    import org.w3c.dom.Element;
037    import org.w3c.dom.NodeList;
038    import org.xml.sax.SAXException;
039    
040    /**
041     * XMLパã?サによる、OpenOffice.org Calcの表計算ドキュメントファイルを読み取る実è£?‚¯ラスですã?
042     *
043     * â‘?‚«ラãƒ?��が指定されてã�?‚‹場å�?
044     *  #NAMEで始まる行を検索しã?そã?行ã?それぞれの値をカラãƒ?��として処ç�?�—ますã?
045     *  #NAMEで始まる行より以前ã?行につã�?�¦は、å?て無視されますã?
046     *  またã?#NAMEより前ã?カラãƒ?�Šびã€?NAMEの行ã?値がNULL(カラãƒ?��が設定されてã�?�ªã�?カラãƒ?‚‚
047     *  無視しますã?
048     *  読み飛ã?されたカラãƒ??に入力された値は取り込まれませんã€?
049     *  またã?#NAME行以降ã?#で始まる行ã?、コメント行とみなされ処ç�?�•れませんã€?
050     *
051     * ②カラãƒ?��が指定されてã�?‚‹場å�?
052     *  æŒ?®šされたカラãƒ?��に基づきã?値を取り込みますã?
053     *  カラãƒ?��のé ?•ªと、シートに記述されてã�?‚‹値のé ?•ªはä¸??してã�?‚‹å¿?¦�がありますã?
054     *  æŒ?®šされたカラãƒ?•°をè¶?�ˆるå?の値につã�?�¦は全て無視されますã?
055     *  #で始まる行ã?、コメント行とみなされ処ç�?�•れませんã€?
056     *
057     * またã?ã�?�šれã?場合も全くデータが存在してã�?�ªã�?¡Œã?読み飛ã?されますã?
058     *
059     * @og.group ファイル入åŠ?
060     *
061     * @version 4.0
062     * @author Hiroki Nakamura
063     * @since JDK5.0,
064     */
065    public class TableReader_Calc extends TableReader_Default {
066            // * こã?プログラãƒ??VERSIONæ–?­—å?を設定しますã? {@value} */
067            private static final String VERSION = "5.5.7.2 (2012/10/09)";
068    
069            private String          sheetName               = null;
070            private String          sheetNos                = null;         // 5.5.7.2 (2012/10/09)
071            private String          filename                = null;
072            private int                     numberOfRows    = 0;
073            private int                     firstClmIdx             = 0;
074            private int[]           valueClmIdx             = null;
075    
076            /**
077             * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
078             * コメンãƒ?空行を除きã?æœ??の行ã?ã€??目名がå¿?¦�ですã?
079             * (ä½?�—、カラãƒ?��を指定することでã€??目名を省略することができまã�?
080             * それ以降ã?、コメンãƒ?空行を除きã?ãƒ??タとして読み込んでã�?��ますã?
081             * こã?メソãƒ?ƒ‰は、Calc 読み込み時に使用しますã?
082             *
083             * @og.rev 4.3.5.0 (2009/02/01) toArray するときに、サイズの初期値æŒ?®šを追åŠ?
084             * @og.rev 5.5.7.2 (2012/10/09) sheetNos 追åŠ?�«よるè¤?•°シートã?マã?ジ読み取りサポã?ãƒ?
085             *
086             * @see #isExcel()
087             */
088            @Override
089            public void readDBTable() {
090    
091                    ZipFile zipFile = null;
092                    boolean errFlag = false;        // 5.0.0.1 (2009/08/15) finally ブロãƒ?‚¯の throw を避けるã€?
093                    try {
094                            // OpenOffice.org odsファイルを開ã�?
095                            zipFile = new ZipFile( filename );
096    
097                            ZipEntry entry = zipFile.getEntry( "content.xml" );
098                            if ( null == entry ) {
099                                    String errMsg = "ODSファイル中にファイルcontent.xmlが存在しませんã€?;
100                                    throw new HybsSystemException( errMsg );
101                            }
102    
103                            // content.xmlをパースしã?行ã?列単位ã?オブジェクトにåˆ?§£しますã?
104                            DomOdsParser odsParser = new DomOdsParser();
105    //                      odsParser.doParse( zipFile.getInputStream( entry ), sheetName );
106                            odsParser.doParse( zipFile.getInputStream( entry ), sheetName , sheetNos );             // 5.5.7.2 (2012/10/09) sheetNos 対å¿?
107                            List<RowInfo> rowInfoList = odsParser.getRowInfoList();
108    
109                            // 4.3.5.0 (2009/02/01) toArray するときに、サイズの初期値æŒ?®šを追åŠ?
110    //                      makeDBTableModel( rowInfoList.toArray( new RowInfo[0] ) );
111                            makeDBTableModel( rowInfoList.toArray( new RowInfo[rowInfoList.size()] ) );
112                    }
113                    catch ( IOException ex ) {
114                            String errMsg = "ファイル読込みエラー[" + filename + "]";
115                            throw new HybsSystemException( errMsg, ex );
116                    }
117                    finally {
118                            // 5.5.2.6 (2012/05/25) fukurou.util.Closer#zipClose( ZipFile ) を利用するように修正ã€?
119                            errFlag = ! Closer.zipClose( zipFile );         // OK の場合ã?true なので、反転しておくã€?
120    //                      if ( null != zipFile ) {
121    //                              try {
122    //                                      zipFile.close();
123    //                              }
124    //                              catch ( IOException ex ) {
125    //                                      errFlag = true;
126    //                              }
127    //                      }
128                    }
129    
130                    if( errFlag ) {
131                            String errMsg = "ODSファイルのクローズ中にエラーが発生しました[" + filename + "]";
132                            throw new HybsSystemException ( errMsg );
133                    }
134    
135    //              finally {
136    //                      if ( null != zipFile )
137    //                              try {
138    //                                      zipFile.close();
139    //                              }
140    //                              catch ( IOException ex ) {
141    //                                      String errMsg = "ODSファイルのクローズ中にエラーが発生しました[" + filename + "]";
142    //                                      throw new HybsSystemException ( errMsg, ex );
143    //                              }
144    //              }
145            }
146    
147            /**
148             * DBTableModel から å�?½¢式ã?ãƒ??タを作æ?して,BufferedReader より読み取りますã?
149             * こã?メソãƒ?ƒ‰は、この実è£?‚¯ラスでは使用できませんã€?
150             *
151             * @param reader å�?½¢式ã?ãƒ??タ(使用してã�?�¾せん)
152             */
153            @Override
154            public void readDBTable( final BufferedReader reader ) {
155                    String errMsg = "こã?クラスでは実è£?�•れてã�?�¾せんã€?;
156                    throw new UnsupportedOperationException( errMsg );
157            }
158    
159            /**
160             * DBTableModelのãƒ??タとしてCalcファイルを読み込ã‚?�¨きã?シート名を設定しますã?
161             * これにより、è¤?•°の形式ã?異なるデータをé?次読み込ã‚?�“とã‚??シートをæŒ?®šして
162             * 読み取ることが可能になりますã?
163             * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
164             * のでご注意くã�?�•ã�??
165             *
166             * @param sheetName シート名
167             */
168            @Override
169            public void setSheetName( final String sheetName ) {
170                    this.sheetName = sheetName;
171            }
172    
173            /**
174             * Calcファイルを読み込ã‚?�¨きã?シート番号を指定しまã�?初期値:0)ã€?
175             *
176             * Calc読み込み時にè¤?•°シートをマã?ジして取り込みますã?
177             * シート番号はã€? から始まる数字で表しますã?
178             * ヘッãƒ??は、最初ã?シートã?カラãƒ?½�置に合わせますã??ˆã?ãƒ?ƒ€ータイトルの自動認識ã?ありません。ï¼?
179             * よって、指定するシートã?、すべて同ä¸?ƒ¬イアウトでなã�?�¨取り込み時にカラãƒ??ずれが発生しますã?
180             * 
181             * シート番号のæŒ?®šã?、カンマ区åˆ?‚Šで、è¤?•°æŒ?®šできますã?またã?N-M の様にハイフンで繋げることでã€?
182             * N 番から、M 番のシートç¯?›²をä¸?‹¬æŒ?®š可能ですã?またã?"*" による、å?シート指定が可能ですã?
183             * これらã?çµ?�¿合わせも可能ですã???0,1,3,5-8,10-* ??
184             * ただしã?"*" に関しては例外的に、ä¸?–‡字だけで、すべてのシートを表すか、N-* を最後にæŒ?®šするかの
185             * どちらかですã?途中にはã€?*" は、現れませんã€?
186             * シート番号はã€?‡�è¤?1,1,2,2)ã€??転(3,2,1) でのæŒ?®šが可能ですã?これは、そのæŒ?®šé?で、読み込まれますã?
187             * sheetNos と sheetName が同時にæŒ?®šされた場合ã?、sheetNos が優先されますã?エラーにはならなã�??でご注意くã�?�•ã�??
188             * こã?メソãƒ?ƒ‰は、isExcel() == true の場合ã?み利用されますã?
189             * 
190             * 初期値はã€??ˆ第ä¸?‚·ートï¼?ですã?
191             *
192             * ※ こã?クラスでは実è£?�•れてã�?�¾せんã€?
193             *
194             * @og.rev 5.5.7.2 (2012/10/09) 新規追åŠ?
195             *
196             * @param   sheetNos Calcファイルのシート番号??から始まるï¼?
197             * @see         #setSheetName( String ) 
198             */
199            @Override
200            public void setSheetNos( final String sheetNos ) {
201                    this.sheetNos = sheetNos;
202            }
203    
204            /**
205             * こã?クラスがã?EXCEL対応機è?を持ってã�?‚‹かどã�?�‹を返しますã?
206             *
207             * EXCEL対応機è?とは、シート名のセãƒ?ƒˆ、読み込みå…?ƒ•ァイルの Fileオブジェクト取得などの、特殊機è?ですã?
208             * 本来は、インターフェースをå?けるべきとè€?�ˆますが、taglib クラス等ã? 関係があり、問ã�?�ˆわせによる条件åˆ?²�で対応しますã?
209             *
210             * @return      EXCEL対応機è?を持ってã�?‚‹かどã�?�‹(常にtrue)
211             */
212            @Override
213            public boolean isExcel() {
214                    return true;
215            }
216    
217            /**
218             * 読み取りå…?ƒ•ァイル名をセãƒ?ƒˆしますã?(DIR + Filename) これは、OpenOffice.org
219             * Calc追åŠ?©Ÿè?として実è£?�•れてã�?�¾すã?
220             *
221             * @param filename 読み取りå…?ƒ•ァイルå�?
222             */
223            @Override
224            public void setFilename( final String filename ) {
225                    this.filename = filename;
226                    if ( filename == null ) {
227                            String errMsg = "ファイル名がæŒ?®šされてã�?�¾せんã€?;
228                            throw new HybsSystemException( errMsg );
229                    }
230            }
231    
232            /**
233             * ODSファイルをパースした結果からDBTableModelを生成しますã?
234             *
235             * @og.rev 5.1.6.0 (2010/05/01) skipRowCountの追åŠ?
236             *
237             * @param rowInfoList 行オブジェクトã?配å?
238             */
239            private void makeDBTableModel( final RowInfo[] rowInfoList ) {
240                    // カラãƒ?��が指定されてã�?‚‹場合ã?、優先するã?
241                    if( columns != null && columns.length() > 0 ) {
242                            makeHeaderFromClms();
243                    }
244    
245    //              for( RowInfo rowInfo : rowInfoList ) {
246                    int skip = getSkipRowCount();                                           // 5.1.6.0 (2010/05/01)
247                    for( int row=skip; row<rowInfoList.length; row++ ) {
248                            RowInfo rowInfo = rowInfoList[row];                             // 5.1.6.0 (2010/05/01)
249                            if( valueClmIdx == null ) {
250                                    makeHeader( rowInfo );
251                            }
252                            else {
253                                    makeBody( rowInfo );
254                            }
255                    }
256    
257                    // æœ?¾Œまでã€?NAME が見つから無かったå?å�?
258                    if ( valueClmIdx == null ) {
259                            String errMsg = "æœ?¾Œまでã€?NAME が見つかりませんでしたã€? + HybsSystem.CR + "ファイルが空かã?もしくã?損傷してã�?‚‹可能性がありますã?" + HybsSystem.CR;
260                            throw new HybsSystemException( errMsg );
261                    }
262            }
263    
264            /**
265             * æŒ?®šされたカラãƒ?¸?¦§からヘッãƒ??æƒ??を生成しますã?
266             *
267             * @og.rev 5.1.6.0 (2010/05/01) useNumber の追åŠ?
268             */
269            private void makeHeaderFromClms() {
270                    table = DBTableModelUtil.newDBTable();
271                    String[] names = StringUtil.csv2Array( columns );
272                    table.init( names.length );
273                    setTableDBColumn( names ) ;
274                    valueClmIdx = new int[names.length];
275                    int adrs = (isUseNumber()) ? 1:0 ;      // useNumber =true の場合ã?ã€?¼‘件目(No)は読み飛ã?すã?
276                    for( int i=0; i<names.length; i++ ) {
277    //                      valueClmIdx[i] = i;
278                            valueClmIdx[i] = adrs++;
279                    }
280            }
281    
282            /**
283             * ヘッãƒ??æƒ??を読み取り、DBTableModelのオブジェクトを新規に作æ?しますã?
284             * ※ 他ã?TableReaderと異なりã?#NAME が見つかるまで、読み飛ã?すã?
285             *
286             * @og.rev 4.3.5.0 (2009/02/01) toArray するときに、サイズの初期値æŒ?®šを追åŠ?
287             *
288             * @param rowInfo 行オブジェクãƒ?
289             */
290            private void makeHeader( final RowInfo rowInfo ) {
291    //              int rowRepeat = rowInfo.rowRepeat;
292                    CellInfo[] cellInfos = rowInfo.cellInfos;
293    
294                    int cellLen = cellInfos.length;
295                    int runPos = 0;
296                    ArrayList<String> nameList = null;
297                    ArrayList<Integer> posList = null;
298                    for ( int idx = 0; idx < cellLen; idx++ ) {
299                            // ãƒ??ブルのヘッãƒ?#NAME)が見つかる前ã?行ã?列ã?全て無視される
300                            CellInfo cellInfo = cellInfos[idx];
301                            String text = cellInfo.text.trim();
302    
303                            for ( int cellRep = 0; cellRep < cellInfo.colRepeat; cellRep++ ) {
304                                    // 空白のヘッãƒ??無è¦?そã?列にãƒ??タがå?ってã�?�¦も読まなã�?
305                                    if ( text.length() != 0 ) {
306                                            if ( firstClmIdx == 0 && text.equalsIgnoreCase( "#NAME" ) ) {
307                                                    nameList = new ArrayList<String>();
308                                                    posList = new ArrayList<Integer>();
309                                                    table = DBTableModelUtil.newDBTable();
310                                                    firstClmIdx = idx;
311                                            }
312                                            else if ( nameList != null ) {
313                                                    nameList.add( text );
314                                                    posList.add( runPos );
315                                            }
316                                    }
317                                    runPos++;
318                            }
319                    }
320    
321    //              if ( posList != null && posList.size() > 0 ) {
322                    if ( posList != null && ! posList.isEmpty() ) {
323                            table = DBTableModelUtil.newDBTable();
324    //                      String[] names = nameList.toArray( new String[0] );
325    //                      table.init( names.length );
326                            // 4.3.5.0 (2009/02/01) サイズの初期値æŒ?®?
327                            int size = nameList.size();
328                            String[] names = nameList.toArray( new String[size] );
329                            table.init( size );
330                            setTableDBColumn( names );
331    
332                            valueClmIdx = new int[posList.size()];
333                            for( int i = 0; i<posList.size(); i++ ) {
334                                    valueClmIdx[i] = posList.get( i ).intValue();
335                            }
336                    }
337            }
338    
339            /**
340             * 行ã?åˆ?セル)単位ã?æƒ??を読み取り、DBTableModelに値をセãƒ?ƒˆしまã�?
341             *
342             * @og.rev 5.2.1.0 (2010/10/01) setTableColumnValues メソãƒ?ƒ‰を経由して、テーブルにãƒ??タをセãƒ?ƒˆするã€?
343             *
344             * @param rowInfo 行オブジェクãƒ?
345             */
346            private void makeBody( final RowInfo rowInfo ) {
347                    int rowRepeat = rowInfo.rowRepeat;
348                    CellInfo[] cellInfos = rowInfo.cellInfos;
349                    int cellLen = cellInfos.length;
350                    boolean isExistData = false;
351    
352                    List<String> colData = new ArrayList<String>();
353                    for ( int cellIdx = 0; cellIdx < cellLen; cellIdx++ ) {
354                            CellInfo cellInfo = cellInfos[cellIdx];
355                            for ( int cellRep = 0; cellRep < cellInfo.colRepeat; cellRep++ ) {
356                                    colData.add( cellInfo.text );
357                                    if( cellInfo.text.length() > 0 ) {
358                                            isExistData = true;
359                                    }
360                            }
361                    }
362    
363                    if( isExistData ) {
364                            // 初めのåˆ?#NAMEが記述されてã�?�Ÿåˆ?の値ã�?で始まってã�?‚‹場合ã?、コメント行とみなすã?
365                            String firstVal = colData.get( firstClmIdx );
366                            if( firstVal.length() > 0 && firstVal.startsWith( "#" ) ) {
367                                    return;
368                            }
369                            else {
370                                    String[] vals = new String[valueClmIdx.length];
371                                    for( int col = 0; col < valueClmIdx.length; col++ ) {
372                                            vals[col] = colData.get( valueClmIdx[col] );
373                                    }
374    
375                                    // 重è¤?¡Œã?繰り返し処ç�?
376                                    for ( int rowIdx = 0; rowIdx < rowRepeat; rowIdx++ ) {
377                                            // ãƒ??ブルモãƒ?ƒ«にãƒ??タをセãƒ?ƒˆ
378                                            if ( numberOfRows < getMaxRowCount() ) {
379                                                    setTableColumnValues( vals );           // 5.2.1.0 (2010/10/01)
380    //                                              table.addColumnValues( vals );
381                                                    numberOfRows++;
382                                            }
383                                            else {
384                                                    table.setOverflow( true );
385                                            }
386                                    }
387                            }
388                    }
389                    // 全くデータが存在しなã�?¡Œã?読み飛ã?ã�?
390                    else {
391                            return;
392                    }
393            }
394    
395            /**
396             * ODSファイルに含まれるcontent.xmlをDOMパã?サーでパã?スしã?行ã?列単位に
397             * オブジェクトに変換しますã?
398             *
399             */
400            private static class DomOdsParser{
401    
402                    // OpenOffice.org Calc tag Names
403    //              private static final String OFFICE_DOCUMENT_CONTEBT_ELEM = "office:document-content";
404    //              private static final String OFFICE_SPREADSHEET_ELEM = "office:spreadsheet";
405                    private static final String TABLE_TABLE_ELEM = "table:table";
406    //              private static final String TABLE_TABLE_COLUMN_ELEM = "table:table-column";
407                    private static final String TABLE_TABLE_ROW_ELEM = "table:table-row";
408                    private static final String TABLE_TABLE_CELL_ELEM = "table:table-cell";
409                    private static final String TEXT_P_ELEM = "text:p";
410    
411                    // Sheet tag attributes
412                    private static final String TABLE_NAME_ATTR = "table:name";
413    //              private static final String OFFICE_VALUE_YPE_ATTR = "office:value-type";
414                    private static final String TABLE_NUMBER_ROWS_REPEATED_ATTR = "table:number-rows-repeated";
415                    private static final String TABLE_NUMBER_COLUMNS_REPEATED_ATTR = "table:number-columns-repeated";
416    //              private static final String TABLE_NUMBER_ROWS_SPANNED_ATTR = "table:number-rows-spanned";
417    //              private static final String TABLE_NUMBER_COLUMNS_SPANNED_ATTR = "table:number-columns-spanned";
418    
419    //              ArrayList<RowInfo> rowInfoList = new ArrayList<RowInfo>();
420                    List<RowInfo> rowInfoList = new ArrayList<RowInfo>();
421                    /**
422                     * Domパã?サでXMLをパースする
423                     *
424                     * @og.rev 5.5.7.2 (2012/10/09) sheetNos 追åŠ?�«よるè¤?•°シートã?マã?ジ読み取りサポã?ãƒ?
425                     *
426                     * @param inputStream InputStream
427                     * @param sheetName String
428                     * @param sheetNos  String
429                     */
430    //              public void doParse( final InputStream inputStream, final String sheetName ) {
431                    public void doParse( final InputStream inputStream, final String sheetName, final String sheetNos ) {
432                            try {
433                                    // ドキュメントビルãƒ??ファクトリを生æˆ?
434                                    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
435                                    dbFactory.setNamespaceAware( true );
436    
437                                    // ドキュメントビルãƒ??を生æˆ?
438                                    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
439                                    // パã?スを実行してDocumentオブジェクトを取å¾?
440                                    Document doc = dBuilder.parse( inputStream );
441    //                              processBook( doc, sheetName );
442                                    processBook( doc, sheetName, sheetNos );                        // 5.5.7.2 (2012/10/09) sheetNos 追åŠ?
443                            }
444                            catch ( ParserConfigurationException ex ) {
445                                    throw new HybsSystemException( ex );
446                            }
447                            catch ( SAXException ex ) {
448                                    String errMsg = "ODSファイル中に含まれるcontent.xmlがXML形式ではありませんã€?;
449                                    throw new HybsSystemException( errMsg, ex );
450                            }
451                            catch ( IOException ex ) {
452                                    throw new HybsSystemException( ex );
453                            }
454                    }
455    
456                    /**
457                     * 行オブジェクトã?リストを返しますã?
458                     *
459                     * @return List<RowInfo>
460                     */
461                    public List<RowInfo> getRowInfoList() {
462                            return rowInfoList;
463                    }
464    
465                    /**
466                     * ODSファイル全体ã?パã?スを行い、å?ç�?¯¾象となるシートを検索しますã?
467                     *
468                     * @og.rev 5.5.7.2 (2012/10/09) sheetNos 追åŠ?�«よるè¤?•°シートã?マã?ジ読み取りサポã?ãƒ?
469                     *
470                     * @param doc Document
471                     * @param sheetName String
472                     * @param sheetNos  String
473                     */
474    //              private void processBook( final Document doc, final String sheetName ) {
475                    private void processBook( final Document doc, final String sheetName, final String sheetNos ) {
476                            // table:tableを探ã�?
477                            NodeList nodetList = doc.getElementsByTagName( TABLE_TABLE_ELEM );
478                            int listLen = nodetList.getLength();
479    
480    //                      Element sheet = null;
481                            Element[] sheets = null ;                       // 5.5.7.2 (2012/10/09)
482    
483                            // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?sheetNos のæŒ?®šが優先されるã€?
484                            if( sheetNos != null && sheetNos.length() > 0 ) {
485                                    String[] sheetList = StringUtil.csv2ArrayExt( sheetNos , listLen-1 );   // æœ?¤§シート番号は、シート数-1
486                                    sheets = new Element[sheetList.length];
487                                    for( int i=0; i<sheetList.length; i++ ) {
488                                            sheets[i] = (Element)nodetList.item( Integer.parseInt( sheetList[i] ) );
489                                    }
490                            }
491                            else if( sheetName != null && sheetName.length() > 0 ) {
492                                    Element sheet = null;
493                                    for ( int idx = 0; idx < listLen; idx++ ) {
494                                            Element st = (Element)nodetList.item( idx );
495                                            if ( sheetName.equals( st.getAttribute( TABLE_NAME_ATTR ) ) ) {
496                                                    sheet = st;
497                                                    break;
498                                            }
499                                    }
500                                    if( sheet == null ) {
501                                            String errMsg = "対応するシートが存在しませんã€?sheetName=[" + sheetName + "]" ;
502                                            throw new HybsSystemException( errMsg );
503                                    }
504                                    sheets = new Element[] { sheet };
505                            }
506                            else {
507                                    Element sheet = (Element)nodetList.item(0);
508                                    sheets = new Element[] { sheet };
509                            }
510    
511    //                      // シート探し:シート名があれã?、そのまま使用、なければ、最初ã?シートを対象としますã?
512    //                      for ( int idx = 0; idx < listLen; idx++ ) {
513    //                              Element st = (Element)nodetList.item( idx );
514    //                              if ( ( sheetName == null || sheetName.length() == 0 ) || sheetName.equals( st.getAttribute( TABLE_NAME_ATTR ) ) ) {
515    //                                      sheet = st;
516    //                                      break;
517    //                              }
518    //                      }
519                            // æŒ?®šã?シートがなければ、エラー
520    //                      if ( sheet == null ) {
521                            if ( sheets == null ) {
522                                    String errMsg = "対応するシートが存在しませんã€?sheetNos=[" + sheetNos + "] or sheetName=[" + sheetName + "]";
523                                    throw new HybsSystemException( errMsg );
524                            }
525                            else {
526    //                              processSheet( sheet );
527                                    // 5.5.7.2 (2012/10/09) è¤?•°シートã?マã?ジ読み取りã€?
528                                    for( int i=0; i<sheets.length; i++ ) {
529                                            processSheet( sheets[i] );
530                                    }
531                            }
532                    }
533    
534                    /**
535                     * ODSファイルのシート単位ã?パã?スを行い、行単位ã?オブジェクトを生æ?しますã?
536                     *
537                     * @param sheet Element
538                     */
539                    private void processSheet( final Element sheet ) {
540                            NodeList rows = sheet.getElementsByTagName( TABLE_TABLE_ROW_ELEM );
541                            int listLen = rows.getLength();
542                            int rowRepeat;
543                            for ( int idx = 0; idx < listLen; idx++ ) {
544                                    Element row = (Element)rows.item( idx );
545                                    // 行ã?å†?®¹がå?く同じå?合ã?table:number-rows-repeatedタグにより省略されるã?
546                                    String repeatStr = row.getAttribute( TABLE_NUMBER_ROWS_REPEATED_ATTR );
547                                    if ( repeatStr == null || repeatStr.length() == 0 ) {
548                                            rowRepeat = 1;
549                                    }
550                                    else {
551                                            rowRepeat = Integer.parseInt( repeatStr, 10 );
552                                    }
553    
554                                    processRow( row, rowRepeat );
555                            }
556                    }
557    
558                    /**
559                     * ODSファイルの行単位ã?パã?スを行い、カラãƒ?�˜位ã?オブジェクトを生æ?しますã?
560                     *
561                     * @og.rev 4.3.5.0 (2009/02/01) toArray するときに、サイズの初期値æŒ?®šを追åŠ?
562                     * @og.rev 5.1.8.0 (2010/07/01) セルå†?�§書式設定されてã�?‚‹場合に、テキストデータが取得されなã�?ƒ�グを修正
563                     *
564                     * @param row Element
565                     * @param rowRepeat int
566                     */
567                    private void processRow( final Element row, final int rowRepeat ) {
568                            NodeList cells = row.getElementsByTagName( TABLE_TABLE_CELL_ELEM );
569                            int listLen = cells.getLength();
570                            int colRepeat;
571                            String cellText;
572                            ArrayList<CellInfo> cellInfoList = new ArrayList<CellInfo>();
573                            for ( int idx = 0; idx < listLen; idx++ ) {
574                                    Element cell = (Element)cells.item( idx );
575                                    // カラãƒ??å†?®¹がå?く同じå?合ã?table:number-columns-repeatedタグにより省略されるã?
576                                    String repeatStr = cell.getAttribute( TABLE_NUMBER_COLUMNS_REPEATED_ATTR );
577                                    if ( repeatStr == null || repeatStr.length() == 0 ) {
578                                            colRepeat = 1;
579                                    }
580                                    else {
581                                            colRepeat = Integer.parseInt( repeatStr, 10 );
582                                    }
583    
584                                    // text:p
585                                    NodeList texts = cell.getElementsByTagName( TEXT_P_ELEM );
586                                    if ( texts.getLength() == 0 ) {
587                                            cellText = "";
588                                    }
589                                    else {
590                                            // 5.1.8.0 (2010/07/01) セルå†?�§書式設定されてã�?‚‹場合に、テキストデータが取得されなã�?ƒ�グを修正
591    //                                      StringBuilder sb = new StringBuilder();
592    //                                      NodeList textElems = texts.item( 0 ).getChildNodes();
593    //                                      int textElemLen = textElems.getLength();
594    //                                      for ( int idxt = 0; idxt < textElemLen; idxt++ ) {
595    //                                              Node textElem = textElems.item( idxt );
596    //                                              if ( textElem.getNodeType() == Node.TEXT_NODE ) {
597    //                                                      sb.append( textElem.getNodeValue() );
598    //                                              }
599    //                                      }
600    //                                      cellText = sb.toString();
601                                            cellText = texts.item( 0 ).getTextContent();
602                                    }
603                                    cellInfoList.add( new CellInfo( colRepeat, cellText ) );
604                            }
605    
606    //                      if ( cellInfoList.size() > 0 ) {
607                            if ( ! cellInfoList.isEmpty() ) {
608    //                              rowInfoList.add( new RowInfo( rowRepeat, cellInfoList.toArray( new CellInfo[0] ) ) );
609                                    // 4.3.5.0 (2009/02/01) toArray するときに、サイズの初期値æŒ?®šを追åŠ?
610                                    rowInfoList.add( new RowInfo( rowRepeat, cellInfoList.toArray( new CellInfo[cellInfoList.size()] ) ) );
611                            }
612                    }
613            }
614    
615            /**
616             * ODSファイルの行情報を表す構é?ä½?
617             */
618            private static final class RowInfo {
619                    public final int rowRepeat;
620                    public final CellInfo[] cellInfos;
621    
622                    RowInfo( final int rep, final CellInfo[] cell ) {
623                            rowRepeat = rep;
624                            cellInfos = cell;
625                    }
626            }
627    
628            /**
629             * ODSファイルのカラãƒ?ƒ…報を表す構é?ä½?
630             */
631            private static final class CellInfo {
632                    public final int colRepeat;
633                    public final String text;
634    
635                    CellInfo( final int rep, final String tx ) {
636                            colRepeat = rep;
637                            text = tx;
638                    }
639            }
640    }