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.PrintWriter;
019    
020    import org.odftoolkit.odfdom.OdfFileDom;
021    import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
022    import org.odftoolkit.odfdom.doc.office.OdfOfficeAutomaticStyles;
023    import org.odftoolkit.odfdom.doc.office.OdfOfficeSpreadsheet;
024    import org.odftoolkit.odfdom.doc.table.OdfTable;
025    import org.odftoolkit.odfdom.doc.table.OdfTableCell;
026    import org.odftoolkit.odfdom.doc.table.OdfTableRow;
027    import org.odftoolkit.odfdom.doc.text.OdfTextParagraph;
028    import org.odftoolkit.odfdom.dom.attribute.office.OfficeValueTypeAttribute;
029    import org.opengion.fukurou.model.NativeType;
030    import org.opengion.fukurou.util.StringUtil;
031    import org.opengion.hayabusa.common.HybsSystemException;
032    import org.opengion.hayabusa.db.DBTableModel;
033    import org.w3c.dom.Node;
034    
035    /**
036     * Calcファイルの書き?しクラスです?
037     *
038     * DefaultTableWriter を継承して?す?で?ラベル?名前,データの出力部のみ
039     * オーバ?ライドして?OpenOfficeのCalcファイルの出力機?を実現して?す?
040     *
041     * @og.group ファイル出?
042     *
043     * @version  5.0
044     * @author       Hiroki Nakamura
045     * @since    JDK6.0,
046     */
047    public class TableWriter_Calc extends TableWriter_Default {
048            //* こ?プログラ??VERSION??を設定します?       {@value} */
049            private static final String VERSION = "5.5.2.6 (2012/05/25)" ;
050    
051            protected OdfSpreadsheetDocument        wb                                      = null;
052            protected OdfTable                                      sheet                           = null;
053            protected OdfFileDom                            contentDom                      = null;
054            protected OdfOfficeSpreadsheet          officeSpreadsheet       = null;
055            protected OdfOfficeAutomaticStyles      contentAutoStyles       = null;
056    
057            protected boolean                                       useNumber                       = true;
058    
059            private String                                  sheetName                       = "Sheet1";
060            private String                                  refSheetName            = null;
061            private String                                  filename                        = null;
062            private String                                  refFilename                     = null;
063    //      private String                                  fontName                        = null;                 // 現時点では未使用
064    //      private short                                   fontPoint                       = -1;                   // 現時点では未使用
065    
066            /**
067             * DBTableModel から ?式???タを作?して,PrintWriter に書き?します?
068             * こ?メソ?は、Calc 書き?し時に使用します?
069             *
070             * @see #isExcel()
071             */
072            @Override
073            public void writeDBTable() {
074                    if( !createDBColumn() ) { return; }
075    
076                    useNumber = isUseNumber();
077    
078                    if( filename == null ) {
079                            String errMsg = "ファイルが指定されて?せん?;
080                            throw new HybsSystemException( errMsg );
081                    }
082    
083                    /* 以下?未実?***********************************************/
084                    if( isAppend() ) {
085                            String errMsg = "Calcの場合?Append利用できません?;
086                            throw new HybsSystemException( errMsg );
087                    }
088    
089                    if( ( refFilename != null && refFilename.length() > 0 ) || ( refSheetName != null && refSheetName.length() >= 0 ) ) {
090                            String errMsg = "Calcの場合?,refFilenamerefSheetName利用できません?;
091                            throw new HybsSystemException( errMsg );
092                    }
093    
094            //      if( fontName != null && fontName.length() > 0 ) {
095            //              String errMsg = "Calcの場合?fontNameは、利用できません?;
096            //              throw new HybsSystemException( errMsg );
097            //              System.err.println( errMsg );
098            //      }
099    
100            //      if( fontPoint >= 0 ) {
101            //              String errMsg = "Calcの場合?fontPointは、利用できません?;
102            //              throw new HybsSystemException( errMsg );
103            //              System.err.println( errMsg );
104            //      }
105                    /* *************************************************************/
106    
107                    // 新規?場?
108                    try {
109                            wb = OdfSpreadsheetDocument.newSpreadsheetDocument();
110                            // コン???ルートとDOMを取?
111                            contentDom = wb.getContentDom();
112                            officeSpreadsheet = wb.getContentRoot();
113                            contentAutoStyles = contentDom.getOrCreateAutomaticStyles();
114    
115                            // ?ォルトで用意されて?ノ?ドを削除
116                            Node childNode = officeSpreadsheet.getFirstChild();
117                            while( childNode != null ) {
118                                    officeSpreadsheet.removeChild( childNode );
119                                    childNode = officeSpreadsheet.getFirstChild();
120                            }
121                    }
122                    catch( Exception ex ) {
123                            String errMsg = "Calcの?宣?できません?;
124                            throw new HybsSystemException( errMsg, ex );
125                    }
126    
127                    //?ォルトで用意されて?Styles調整
128                    resetAutoStylesAndMasterStyles();
129    
130                    sheet = new OdfTable( contentDom );
131                    sheet.setTableNameAttribute( sheetName );
132    
133                    super.writeDBTable( null );
134    
135                    officeSpreadsheet.appendChild( sheet );
136    
137                    try {
138                            wb.save( filename );
139                            wb.close();
140                    }
141                    catch( Exception ex ) {
142                            String errMsg = "Calcの?saveができません?;
143                            throw new HybsSystemException( errMsg, ex );
144                    }
145                    finally {
146                            if( null != sheet )     { sheet = null; }
147                            if( null != wb )        { wb = null; }
148                    }
149            }
150    
151            /**
152             * DBTableModel から ??タを作?して,PrintWriter に書き?します?
153             *
154             * @param       writer PrintWriterオブジェク?
155             */
156            @Override
157            public void writeDBTable( final PrintWriter writer )  {
158                    String errMsg = "こ?クラスでは実?れて?せん?;
159                    throw new UnsupportedOperationException( errMsg );
160            }
161    
162            /**
163             * PrintWriter に DBTableModelのラベル??を書き込みます?
164             * 第?ラ?は、ラベル??を示?"#Label" を書き込みます?
165             * こ?行?、?力形式に無関係に、TableWriter.TAB_SEPARATOR で区?れます?
166             *
167             * @param       table  DBTableModelオブジェク?
168             * @param       writer PrintWriterオブジェク?
169             */
170            @Override
171            protected void writeLabel( final DBTableModel table, final PrintWriter writer ) {
172                    OdfTableRow row = new OdfTableRow( contentDom );
173    
174                    if( useNumber ) {
175                            row.appendCell( createTextCell( contentDom, "#Label", false, false ) );
176                    }
177    
178                    for( int i = 0; i < numberOfColumns; i++ ) {
179                            int clm = clmNo[i];
180                            String val = dbColumn[clm].getLabel();
181                            if( i == 0 && !useNumber ) {
182                                    val = "#" + val;
183                            }
184                            row.appendCell( createTextCell( contentDom, val, false, false ) );
185                    }
186                    row.setStyleName( "ro1" );
187                    sheet.appendRow( row );
188            }
189    
190            /**
191             * PrintWriter に DBTableModelの?名情報を書き込みます?
192             * 第?ラ?は??目名情報を示?"#Name" を書き込みます?
193             * こ?行?、?力形式に無関係に、TableWriter.TAB_SEPARATOR で区?れます?
194             *
195             * @param       table  DBTableModelオブジェク?
196             * @param       writer PrintWriterオブジェク?
197             */
198            @Override
199            protected void writeName( final DBTableModel table, final PrintWriter writer ) {
200                    OdfTableRow row = new OdfTableRow( contentDom );
201    
202                    if( useNumber ) {
203                            row.appendCell( createTextCell( contentDom, "#Name", false, false ) );
204                    }
205    
206                    for( int i = 0; i < numberOfColumns; i++ ) {
207                            int clm = clmNo[i];
208                            String val = table.getColumnName( clm );
209                            if( i == 0 && !useNumber ) {
210                                    val = "#" + val;
211                            }
212                            row.appendCell( createTextCell( contentDom, val, false, false ) );
213                    }
214                    row.setStyleName( "ro1" );
215                    sheet.appendRow( row );
216            }
217    
218            /**
219             * PrintWriter に DBTableModelのサイズ??を書き込みます?
220             * 第?ラ?は、サイズ??を示?"#Size" を書き込みます?
221             * こ?行?、?力形式に無関係に、TableWriter.TAB_SEPARATOR で区?れます?
222             *
223             * @param       table  DBTableModelオブジェク?
224             * @param       writer PrintWriterオブジェク?
225             */
226            @Override
227            protected void writeSize( final DBTableModel table, final PrintWriter writer ) {
228                    OdfTableRow row = new OdfTableRow( contentDom );
229    
230                    if( useNumber ) {
231                            row.appendCell( createTextCell( contentDom, "#Size", false, false ) );
232                    }
233    
234                    for( int i = 0; i < numberOfColumns; i++ ) {
235                            int clm = clmNo[i];
236                            String val = String.valueOf( dbColumn[clm].getTotalSize() );
237                            if( i == 0 && !useNumber ) {
238                                    val = "#" + val;
239                            }
240                            row.appendCell( createTextCell( contentDom, val, true, false ) );
241                    }
242                    row.setStyleName( "ro1" );
243                    sheet.appendRow( row );
244            }
245    
246            /**
247             * PrintWriter に DBTableModelのクラス名情報を書き込みます?
248             * 第?ラ?は、サイズ??を示?"#Class" を書き込みます?
249             * こ?行?、?力形式に無関係に、TableWriter.TAB_SEPARATOR で区?れます?
250             *
251             * @param       table  DBTableModelオブジェク?
252             * @param       writer PrintWriterオブジェク?
253             */
254            @Override
255            protected void writeClass( final DBTableModel table, final PrintWriter writer ) {
256                    OdfTableRow row = new OdfTableRow( contentDom );
257    
258                    if( useNumber ) {
259                            row.appendCell( createTextCell( contentDom, "#Class", false, false ) );
260                    }
261    
262                    for( int i = 0; i < numberOfColumns; i++ ) {
263                            int clm = clmNo[i];
264                            String val = dbColumn[clm].getClassName();
265                            if( i == 0 && !useNumber ) {
266                                    val = "#" + val;
267                            }
268                            row.appendCell( createTextCell( contentDom, val, false, false ) );
269                    }
270                    row.setStyleName( "ro1" );
271                    sheet.appendRow( row );
272            }
273    
274            /**
275             * PrintWriter に セパレーターを書き込みます?
276             * 第?ラ?は、サイズ??を示?"#----" を書き込みます?
277             * こ?行?、?力形式に無関係に、TableWriter.TAB_SEPARATOR で区?れます?
278             *
279             * @param       table  DBTableModelオブジェク?
280             * @param       writer PrintWriterオブジェク?
281             */
282            @Override
283            protected void writeSeparator( final DBTableModel table, final PrintWriter writer ) {
284                    String sep = "----";
285    
286                    OdfTableRow row = new OdfTableRow( contentDom );
287                    row.appendCell( createTextCell( contentDom, "#----", false, false ) );
288                    for( int i = 0; i < numberOfColumns; i++ ) {
289                            if( i == 0 && !useNumber ) {
290                                    continue;
291                            }
292                            row.appendCell( createTextCell( contentDom, sep, false, false ) );
293                    }
294                    sheet.appendRow( row );
295            }
296    
297            /**
298             * PrintWriter に DBTableModelの??ブル??を書き込みます?
299             * こ?クラスでは?データ??ルコー??ション(")で囲みます?
300             * PrintWriter に DBTableModelの??ブル??を書き込みます?
301             *
302             * @og.rev 5.2.1.0 (2010/10/01) useRenderer 対?
303             *
304             * @param       table  DBTableModelオブジェク?
305             * @param       writer PrintWriterオブジェク?
306             */
307            @Override
308            protected void writeData( final DBTableModel table,final PrintWriter writer ) {
309                    int numberOfRows =      table.getRowCount();
310    
311                    boolean[] nvar = new boolean[numberOfColumns];
312                    boolean[] cellType = new boolean[numberOfColumns];
313                    for( int i=0; i<numberOfColumns; i++ ) {
314                            int clm = clmNo[i];
315                            NativeType nativeType = dbColumn[clm].getNativeType();
316                            switch( nativeType ) {
317                                    case INT    :
318                                    case LONG   :
319                                    case DOUBLE :
320                                            cellType[i] = true ;
321                                            break;
322                                    case STRING :
323                                    case CALENDAR :
324                                    default :
325                                            cellType[i] = false ;
326                                            break;
327                            }
328                            nvar[i] = "NVAR".equals( dbColumn[clm].getDbType() );
329                    }
330                    boolean useRenderer = isUseRenderer();  // 5.2.1.0 (2010/10/01)
331    
332                    for( int r = 0; r < numberOfRows; r++ ) {
333                            OdfTableRow row = new OdfTableRow( contentDom );
334    
335                            if( useNumber ) {
336                                    row.appendCell( createTextCell( contentDom, String.valueOf( r + 1 ), true, true ) );
337                            }
338    
339                            for( int i = 0; i < numberOfColumns; i++ ) {
340                                    int clm = clmNo[i];
341                                    String val = table.getValue( r, clm );
342                                    if( nvar[i] ) {
343                                            val = StringUtil.getReplaceEscape( val );
344                                    }
345                                    // 5.2.1.0 (2010/10/01) useRenderer 対?
346                                    else if( useRenderer ) {
347                                            val = StringUtil.spanCut( dbColumn[clm].getRendererValue( val ) );
348                                    }
349                                    row.appendCell( createTextCell( contentDom, val, cellType[i], false ) );
350                            }
351                            row.setStyleName( "ro1" );
352                            sheet.appendRow( row );
353                    }
354            }
355    
356            /**
357             * ?ストコン??のセルを生成す?
358             *
359             * @param       contentDom      OdfFileDomオブジェク?
360             * @param       content         コン??
361             * @param       isCellTypeNumber        [true:数字型/false:?型]
362             * @param       isNumberList            [true:数字リス?999/false:通常]
363             *
364             * @return      OpenOfficeのセル??ブルオブジェク?
365             */
366            protected OdfTableCell createTextCell(  final OdfFileDom contentDom,
367                                                                                            final String content,
368                                                                                            final Boolean isCellTypeNumber,
369                                                                                            final Boolean isNumberList ) {
370                    OdfTableCell cell = new OdfTableCell( contentDom );
371                    if( isCellTypeNumber ) {
372                            cell.setOfficeValueAttribute( Double.parseDouble( content ) );
373                            cell.setOfficeValueTypeAttribute( OfficeValueTypeAttribute.Value.FLOAT.toString() );
374                    }
375                    else {
376                            cell.setOfficeValueTypeAttribute( OfficeValueTypeAttribute.Value.STRING.toString() );
377                    }
378                    OdfTextParagraph paragraph = new OdfTextParagraph( contentDom, null, content );
379                    cell.appendChild( paragraph );
380                    return cell;
381            }
382    
383            /**
384             * ?ォルトで用意されて?Stylesを調整します?
385             * ※ここでは何もしません?
386             *
387             */
388            protected void resetAutoStylesAndMasterStyles(){
389                    // Document empty method 対?
390            }
391    
392            /**
393             * DBTableModelの??タとして読み込?き?シート名を設定します?
394             * 初期値は?Sheet1" です?
395             * これは、Calc追??として実?れて?す?
396             *
397             * @param   sheetName シート名
398             */
399            @Override
400            public void setSheetName( final String sheetName ) {
401                    if( sheetName != null ) {
402                            this.sheetName = sheetName;
403                    }
404            }
405    
406            /**
407             * Calc雛型参?ファイルのシート名を設定します?
408             * これは、Calc追??として実?れて?す?
409             *
410             * Calcファイルを書き?す時に?型として参?するシート名を指定します?
411             * これにより、?の形式?異なるデータを?次書き?した?appendモードを併用)する
412             * こと??シートを?して新規にCalcを作?する場合にフォー?設定する事が可能になります?
413             * 初期値は、null(第?ー? です?
414             *
415             * @param   sheetName シート名
416             */
417            @Override
418            public void setRefSheetName( final String sheetName ) {
419                    if( sheetName != null ) {
420                            refSheetName = sheetName;
421                    }
422            }
423    
424            /**
425             * こ?クラスが?Calc対応機?(=Excel対応機?)を持って?かど?を返します?
426             *
427             * Calc対応機?とは、シート名のセ??型参照ファイル名?セ??
428             * 書き込み?ァイルのFileオブジェクト取得などの、特殊機?です?
429             * 本来は、インターフェースを?けるべきと?ますが、taglib クラス等?
430             * 関係があり、問?わせによる条件?で対応します?
431             *
432             * @return      Calc対応機?(=Excel対応機?)を持って?かど?(true 固?
433             */
434            @Override
435            public boolean isExcel() {
436                    return true;
437            }
438    
439            /**
440             * 出力?ファイル名をセ?します?(DIR + Filename)
441             * これは、Calc追??として実?れて?す?
442             *
443             * @param   filename Calc雛型参?ファイル?
444             */
445            @Override
446            public void setFilename( final String filename ) {
447                    this.filename = filename;
448            }
449    
450            /**
451             * Calc雛型参?ファイル名をセ?します?(DIR + Filename)
452             * これは、Calc追??として実?れて?す?
453             *
454             * @param   filename Calc雛型参?ファイル?
455             */
456            @Override
457            public void setRefFilename( final String filename ) {
458                    refFilename = filename;
459            }
460    
461            /**
462             * Calc出力時の?ォルトフォント名を設定します?
463             * <del>これは、Calc追??として実?れて?す?</del>
464             * Calcの場合?fontNameは、利用できません?
465             *
466             * Calcファイルを書き?す時に、デフォルトフォント名を指定します?
467             * フォント名は、Calcのフォント名をそのまま使用してください?
468             * に設定されます?
469             * 初期値は、シス?リソース の TABLE_WRITER_DEFAULT_FONT_NAME です?
470             *
471             * @og.rev      5.5.2.6 (2012/05/25) findbugs対?
472             *
473             * @param   fontName ?ォルトフォント名
474             */
475            @Override
476            public void setFontName( final String fontName ) {
477    //              this.fontName = fontName ;
478                    String errMsg = "Calcの場合?fontNameは、利用できません。fontName=[" + fontName + "]";
479                    System.err.println( errMsg );
480            }
481    
482            /**
483             * Calc出力時の?ォルトフォント?イント数を設定します?
484             * <del>これは、Calc追??として実?れて?す?</del>
485             * Calcの場合?fontPointは、利用できません?
486             *
487             * Calcファイルを書き?す時に、デフォルト?イント数を指定します?
488             * に設定されます?
489             * 初期値は、シス?リソース の TABLE_WRITER_DEFAULT_FONT_POINTS です?
490             *
491             * @og.rev      5.5.2.6 (2012/05/25) findbugs対?
492             *
493             * @param   point ?ォルトフォント?イント数
494             */
495            @Override
496            public void setFontPoint( final short point ) {
497    //              fontPoint = point;
498                    String errMsg = "Calcの場合?fontPointは、利用できません。fontPoint=[" + point + "]";
499                    System.err.println( errMsg );
500            }
501    }