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.hayabusa.taglib;
017
018import static org.opengion.fukurou.util.StringUtil.nval;
019
020import java.io.File;
021
022import org.opengion.fukurou.util.StringUtil;
023import org.opengion.fukurou.util.ToString;                                              // 6.1.1.0 (2015/01/17)
024import org.opengion.hayabusa.common.HybsSystem;
025import org.opengion.hayabusa.report2.DocConverter_OOO;
026// import org.opengion.hayabusa.io.HybsFileOperationFactory;    // 8.0.0.1 (2021/10/08) , 8.0.1.0 (2021/10/29) 廃止
027// import org.opengion.fukurou.model.FileOperation;                             // 8.0.0.1 (2021/10/08)
028// import org.opengion.fukurou.util.FileUtil;                                   // 8.0.0.1 (2021/10/08)
029
030/**
031 * ドキュメントの変換・マージを行うタグです。
032 *
033 * 変換を行うことのできる入出力のフォーマット以下の通りです。
034 *
035 * [対応フォーマット]
036 *  入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)      ,PDF]
037 *  入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)       ,PDF]
038 *  入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx) ,PDF]
039 *
040 * ※ xlsx,docx,pptx は、MS 2007形式の為、LibreOffice のみ利用できます。
041 *
042 * 入出力のフォーマットは、入出力ファイルの拡張子により自動判別されます。
043 * また、入出力ファイル名が同じ場合は何も処理されません。
044 *
045 * 入力ファイルを、CSV形式で複数指定することで、複数の入力ファイルをマージして
046 * 出力することもできます。
047 *
048 * ※2 現状は、ファイルのマージは、入力ファイルがExcelまたはCalcの場合のみ対応しています。
049 * ※1 この機能を利用するには、OpenOfficeが正しく設定されている必要があります。
050 *
051 * @og.formSample
052 * ●形式:<og:docConvert fileURL="…" inputFile="…" outputFile="…" />
053 * ●body:なし
054 *
055 * ●Tag定義:
056 *   <og:docConvert
057 *       fileURL            【TAG】操作するファイルのディレクトリを指定します (初期値:FILE_URL[=filetemp/])
058 *       inputFile        ○【TAG】入力ファイル名を指定します(必須)。
059 *       outputFile       ○【TAG】出力ファイル名を指定します(必須)。
060 *       delInput           【TAG】ドキュメント変換後、元のファイルを削除するかどうかを指定します(初期値:false[=削除しない])
061 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
062 *   />
063 *
064 * ●使用例
065 *    ・Calc(ods)ファイルをPDFに変換
066 *        <og:docConvert inputFile="temp.ods" outputFile="out.pdf" />
067 *
068 *    ・Excel(xls)ファイルを連結
069 *        <og:docConvert inputFile="temp1.xls,temp2.xls" outputFile="out.xls" />
070 *
071 * @og.group その他部品
072 *
073 * @version  4.0
074 * @author       Hiroki Nakamura
075 * @since    JDK5.0,
076 */
077public class DocConvertTag extends CommonTagSupport {
078        /** このプログラムのVERSION文字列を設定します。 {@value} */
079        private static final String VERSION = "8.0.1.0 (2021/10/29)" ;
080        private static final long serialVersionUID = 801020211029L ;
081
082        private String  fileURL         = HybsSystem.sys( "FILE_URL" );
083        private String[]inputFile       ;
084        private String  outputFile      ;
085        private boolean delInput        ;
086
087        /**
088         * デフォルトコンストラクター
089         *
090         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
091         */
092        public DocConvertTag() { super(); }             // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
093
094        /**
095         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
096         *
097         * @return      後続処理の指示( SKIP_BODY )
098         */
099        @Override
100        public int doStartTag() {
101                return SKIP_BODY ;
102        }
103
104        /**
105         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
106         *
107         * @og.rev 8.0.0.2 (2021/10/15) ローカルファイルとクラウドファイル間の移動
108         *
109         * @return      後続処理の指示
110         */
111        @Override
112        public int doEndTag() {
113                debugPrint();
114
115                // 出力ファイルで拡張子だけが指定された場合は、入力ファイル名を付加する
116                if( outputFile.indexOf( '.' ) < 0 ) {
117                        final int inSufIdx = inputFile[0].lastIndexOf( '.' );
118                        if( inSufIdx >= 0 ) {
119                                outputFile = inputFile[0].substring( 0, inSufIdx ) + "." + outputFile;
120                        }
121                }
122
123                final String directory = HybsSystem.url2dir( fileURL );
124                String[] input = new String[inputFile.length];
125                for( int i=0; i<input.length; i++ ) {
126                        input[i] = StringUtil.urlAppend( directory,inputFile[i] );
127                }
128                final String output = StringUtil.urlAppend( directory,outputFile );
129
130//              // 8.0.1.0 (2021/10/29) 廃止
131//              // 8.0.0.2 (2021/10/15) ローカルファイルとクラウドファイル間の移動
132//              if( !useLocal && HybsFileOperationFactory.useCloud() ) {
133//                      // 5.10.9.0 (2019/03/01) ADD クラウドストレージ指定の場合、ファイルをローカルにダウンロードします。
134//                      for( final String in: input ) {
135//                              HybsFileOperationFactory.cloud2local( false,() -> new File( in ) );             // false:システム定義のクラウド設定に従う。
136//                      }
137//              }
138//              final FileOperation inFile = HybsFileOperationFactory.create( input[0] );
139//              // 5.10.9.0 (2019/03/01) ADD クラウドストレージ指定の場合、ファイルをローカルにダウンロードします。
140//              if( inFile.isCloud() ) {
141//                      for( final String in: input ) {
142//                              final File fromFile = HybsFileOperationFactory.create( in );
143//                              final File toFile = new File( in );
144//                              toFile.mkdirs();                        // toFileのディレクトリを作成する必要あり?
145//                              FileUtil.copy( fromFile, toFile );
146//                      }
147//              }
148
149                // ドキュメント変換
150//              DocConverter_OOO.convert( input, output );
151                DocConverter_OOO.convert( input, output, true );                //  8.0.3.0 (2021/12/17) メソッド削除に伴う処置
152
153//              // 8.0.1.0 (2021/10/29) 廃止
154//              // 8.0.0.1 (2021/10/08) cloud対応
155//              // 5.10.9.0 (2019/03/01) ADD クラウドストレージ指定の場合、ファイルをクラウドストレージにアップロードします。
156//              // 8.0.0.2 (2021/10/15) ローカルファイルとクラウドファイル間の移動
157//              HybsFileOperationFactory.local2cloud( useLocal,() -> new File( output ) );
158//      //      final FileOperation outFile = HybsFileOperationFactory.create( output );
159//      //      if( outFile.isCloud() ) {
160//      //              final File localFile = new File( output );
161//      //              FileUtil.copy( localFile, outFile );
162//      //              localFile.delete();
163//      //      }
164
165                if( delInput ) {
166                        for( int i=0; i<input.length; i++ ) {
167                                if( !( new File( input[i] ) ).delete() ) {
168                                        System.err.println( "入力ファイルの削除に失敗しました。file=[" + input[i] + "]" );
169                                }
170                        }
171                }
172
173                return EVAL_PAGE ;
174        }
175
176        /**
177         * タグリブオブジェクトをリリースします。
178         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
179         *
180         */
181        @Override
182        protected void release2() {
183                super.release2();
184                fileURL         = HybsSystem.sys( "FILE_URL" );
185                inputFile       = null;
186                outputFile      = null;
187                delInput        = false;
188        }
189
190        /**
191         * 【TAG】操作するファイルのディレクトリを指定します
192         *              (初期値:FILE_URL[={@og.value SystemData#FILE_URL}])。
193         *
194         * @og.tag
195         * この属性で指定されるディレクトリのファイルを操作します。
196         * 指定方法は、通常の fileURL 属性と同様に、先頭が、'/' (UNIX) または、2文字目が、
197         * ":" (Windows)の場合は、指定のURLそのままのディレクトリに、そうでない場合は、
198         * (初期値:システム定数のFILE_URL[={@og.value SystemData#FILE_URL}])。
199         *
200         * @og.rev 6.4.2.1 (2016/02/05) URLの最後に、"/" を追加する処理を廃止。
201         *
202         * @param       url ファイルURL
203         * @see         org.opengion.hayabusa.common.SystemData#FILE_URL
204         */
205        public void setFileURL( final String url ) {
206                final String furl = nval( getRequestParameter( url ),null );
207                if( furl != null ) {
208                        fileURL = StringUtil.urlAppend( fileURL,furl );
209                }
210        }
211
212        /**
213         * 【TAG】入力ファイル名を指定します。
214         *
215         * @og.tag
216         * 入力ファイル名を指定します。
217         *
218         * 入力ファイルは、CSV形式で複数指定することができます。
219         * この場合、複数の入力ファイルをマージして出力を行います。
220         *
221         * ※現状は、ファイルのマージは、入力ファイルがExcelまたはCalcの場合のみ対応しています。
222         *   また、マージを行う場合、印刷範囲など、ドキュメントに関連する情報は、1つ目のファイルの
223         *   情報が使用されます。
224         *
225         * @param       fname 入力ファイル名
226         */
227        public void setInputFile( final String fname ) {
228                inputFile = getCSVParameter( fname );
229        }
230
231        /**
232         * 【TAG】出力ファイル名を指定します。
233         *
234         * @og.tag
235         * 出力ファイル名を指定します。
236         * 出力ファイルには、拡張子のみ(xls,ods等)を指定することもできます。
237         * この場合、出力ファイル名は、入力ファイル名と同じになります。(拡張子のみが変換される)
238         *
239         * @param       fname 出力ファイル名
240         */
241        public void setOutputFile( final String fname ) {
242                outputFile = nval( getRequestParameter( fname ),outputFile );
243        }
244
245        /**
246         * 【TAG】ドキュメント変換後、元のファイルを削除するかどうかを指定します(初期値:false[=削除しない])。
247         *
248         * @og.tag
249         * ドキュメント変換後、元のファイルを削除するかどうかを指定します。
250         * 初期値は、false(削除しない)です。
251         *
252         * @param       flag 元ファイルの削除 [true:する/false:しない]
253         */
254        public void setDelInput( final String flag ) {
255                delInput = nval( getRequestParameter( flag ),delInput );
256        }
257
258//      /**
259//       * 【TAG】システム定数でクラウド設定されていても、クラウド環境を使用しない場合、trueを指定します(初期値:false)。
260//       *
261//       * @og.tag
262//       * クラウド設定は、システム定数の『CLOUD_TARGET』と『CLOUD_BUCKET』の設定で自動的に使用しますが、
263//       * どうしてもローカルでのみ使いたい場合は、この属性を true に設定します。
264//       * 標準はfalse:設定どおりとなります。
265//       *
266//       * true/false以外を指定した場合はfalse扱いとします。
267//       *
268//       * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加。
269//       *
270//       * @param flag ローカル環境のみ [true:ローカルのみ/false:設定どおり]
271//       */
272//      public void setUseLocal( final String flag ) {
273//              useLocal = nval( getRequestParameter( flag ),useLocal );
274//      }
275
276        /**
277         * このオブジェクトの文字列表現を返します。
278         * 基本的にデバッグ目的に使用します。
279         *
280         * @return このクラスの文字列表現
281         * @og.rtnNotNull
282         */
283        @Override
284        public String toString() {
285                return ToString.title( this.getClass().getName() )
286                                .println( "VERSION"             ,VERSION        )
287                                .println( "fileURL"             ,fileURL        )
288                                .println( "inputFile"   ,inputFile              )
289                                .println( "outputFile"  ,outputFile             )
290                                .println( "Other..."    ,getAttributes().getAttribute() )
291                                .fixForm().toString() ;
292        }
293}