    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.report2;
    017
    018import java.io.File;
    019import java.util.Map;
    020import java.util.HashMap;
    021import java.util.Locale;
    022// import java.util.List;                                                                               // 8.0.3.0 (2021/12/17) 【保留】
    023import java.nio.file.Files;                                                                             // 8.1.0.3 (2022/01/21)
    024import java.nio.file.Paths;                                                                             // 8.1.0.3 (2022/01/21)
    025import java.nio.file.Path;                                                                              // 8.1.0.3 (2022/01/21)
    026import java.nio.file.StandardCopyOption;                                                // 8.1.0.3 (2022/01/21)
    027
    028import org.opengion.fukurou.system.HybsConst;                                   // 8.0.1.0 (2021/10/29)
    029// import org.opengion.fukurou.model.ExcelModel;                                // 8.0.3.0 (2021/12/17)【保留】
    030import org.opengion.fukurou.util.FileUtil;
    031import org.opengion.fukurou.util.StringUtil;
    032import org.opengion.hayabusa.common.HybsSystem;
    033import org.opengion.hayabusa.common.HybsSystemException;
    034import static org.opengion.fukurou.system.HybsConst.CR ;                // 6.1.0.0 (2014/12/26)
    035// import static org.opengion.fukurou.system.HybsConst.FS ;             // 8.0.3.0 (2021/12/17)
    036
    037import com.sun.star.beans.PropertyValue;
    038import com.sun.star.frame.XComponentLoader;
    039import com.sun.star.frame.XController;
    040import com.sun.star.frame.XDispatchHelper;
    041import com.sun.star.frame.XDispatchProvider;
    042import com.sun.star.frame.XModel;
    043import com.sun.star.frame.XStorable;
    044import com.sun.star.io.IOException;
    045import com.sun.star.lang.EventObject;
    046import com.sun.star.lang.IllegalArgumentException;
    047import com.sun.star.lang.XComponent;
    048import com.sun.star.uno.UnoRuntime;
    049import com.sun.star.util.CloseVetoException;
    050import com.sun.star.util.XCloseable;
    051import com.sun.star.view.PrintJobEvent;
    052import com.sun.star.view.PrintableState;
    053import com.sun.star.view.XPrintJobBroadcaster;
    054import com.sun.star.view.XPrintJobListener;
    055import com.sun.star.view.XPrintable;
    056
    057/**
    058 * OpenOfficeを利用して様々な形式のﾌｧｲﾙを読み込み､出力･印刷を行うための変換ｸﾗｽです｡
    059 *
    060 * 変換を行うことのできる入出力のﾌｫｰﾏｯﾄ以下の通りです｡
    061 *
    062 * [対応ﾌｫｰﾏｯﾄ]
    063 *  入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)      ,PDF]
    064 *  入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)       ,PDF]
    065 *  入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx) ,PDF]
    066 *  入力[ * 上記の全て               ] ⇒ 印刷
    067 *
    068 * ※ xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡
    069 *
    070 * 変換を行うには､以下の2通りの方法があります｡
    071 * <del>
    072 * (1)簡易的な変換ﾒｿｯﾄﾞを利用する場合
    073 *   #convert(String, String)を利用して､変換を行います｡
    074 *   この場合､出力形式は､出力ﾌｧｲﾙの拡張子に従って自動的に決定されます｡
    075 *   このため､印刷処理などを行う場合は､(2)の方法で出力して下さい｡
    076 * </del>
    077 * (2)段階的に各ﾒｿｯﾄﾞを呼び出して変換する場合
    078 *   ｵﾌﾞｼﾞｪｸﾄを生成した後､{@link #open()}､#(各種変換ﾒｿｯﾄﾞ)､{@link #clone()}を
    079 *   順番に呼び出して変換を行います｡
    080 *   この場合､出力形式は､それに対応するﾒｿｯﾄﾞを呼び出すことで決定されます｡
    081 *
    082 *   また､変換を行うための､各種ﾒｿｯﾄﾞは､例外としてThrowableを投げるように定義されています｡
    083 *   このｸﾗｽを利用する場合は､このThrowableをcatchし､catch句で､必ず{@link #close( boolean )}に､
    084 *   "true"(ｴﾗｰ発生時のｸﾛｰｽﾞ処理)を指定して､終了処理を行って下さい｡
    085 *   (これを行わない場合､OpenOfficeの不要なﾌﾟﾛｾｽが残ってしまう可能性があります)
    086 *
    087 * また､出力ﾌｧｲﾙが既に存在する場合､出力ﾌｧｲﾙは一旦削除された後､処理されます｡
    088 * なお､入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合､何も処理されません｡(例外も発行されません)
    089 *
    090 * 入力ﾌｧｲﾙを､CSV形式で複数指定した場合､複数の入力ﾌｧｲﾙをﾏｰｼﾞして出力します｡
    091 * ※1 現状は､ﾌｧｲﾙのﾏｰｼﾞは､入力ﾌｧｲﾙがExcelまたはCalcの場合のみ対応しています｡
    092 *
    093 * ※ DocConverter は､ｸﾗｳﾄﾞ対応されていません｡変換時はﾛｰｶﾙﾌｧｲﾙ間で行ってください｡
    094 *
    095 * @og.group 帳票ｼｽﾃﾑ
    096 *
    097 * @version  4.0
    098 * @author   Hiroki.Nakamura
    099 * @since    JDK1.6
    100 */
    101public class DocConverter_OOO {
    102        private static final String OFFICE_VER = HybsConst.getenv( "OPENOFFICE_VER","NULL" );   // 8.0.1.0 (2021/10/29) 環境変数から取得
    103
    104        private final boolean                   isOnline;                       // ｵﾝﾗｲﾝ処理かどうか(ｵﾝﾗｲﾝ処理の場合､ﾌﾟﾛｾｽはﾌｧｸﾄﾘｸﾗｽ経由で生成されます)
    105        private final String[]                  mergeFile;
    106
    107        private String                                  inputName;
    108        private String                                  origName;
    109
    110        private XComponent                              xComp;                          // 5.1.8.0 (2010/07/01) ﾒｿｯﾄﾞと重なる変数名の変更
    111        private SOfficeProcess                  soffice;
    112
    113        // 入力､出力の拡張子とこれに対応するﾌｨﾙﾀｰ名
    114        // share¥registry¥calc.xcd 形式のﾌｧｲﾙ <node oor:name="****" 部分？
    115
    116        /** staticｲﾆｼｬﾗｲｻﾞ後､読み取り専用にするので､ConcurrentHashMap を使用しません｡ */
    117        private static final Map<String,String> FILTER_MAP      = new HashMap<>();              // 6.4.1.1 (2016/01/16) filterMap → FILTER_MAP refactoring
    118        static {
    119                // 8.1.0.3 (2022/01/21) ﾌｧｲﾙの拡張子が同じ場合は、copyで対応する。
    120        //      FILTER_MAP.put( "ods_ods", "calc8" );
    121                FILTER_MAP.put( "xls_ods", "calc8" );
    122                FILTER_MAP.put( "ods_xls", "MS Excel 97" );
    123        //      FILTER_MAP.put( "xls_xls", "MS Excel 97" );
    124                FILTER_MAP.put( "ods_pdf", "calc_pdf_Export" );
    125                FILTER_MAP.put( "xls_pdf", "calc_pdf_Export" );
    126        //      FILTER_MAP.put( "odt_odt", "writer8" );
    127                FILTER_MAP.put( "doc_odt", "writer8" );
    128                FILTER_MAP.put( "odt_doc", "MS Word 97" );
    129        //      FILTER_MAP.put( "doc_doc", "MS Word 97" );
    130                FILTER_MAP.put( "odt_pdf", "writer_pdf_Export" );
    131                FILTER_MAP.put( "doc_pdf", "writer_pdf_Export" );
    132        //      FILTER_MAP.put( "odp_odp", "impress8" );
    133                FILTER_MAP.put( "ppt_odp", "impress8" );
    134                FILTER_MAP.put( "odp_ppt", "MS PowerPoint 97" );
    135        //      FILTER_MAP.put( "ppt_ppt", "MS PowerPoint 97" );
    136                FILTER_MAP.put( "odp_pdf", "impress_pdf_Export" );
    137                FILTER_MAP.put( "ppt_pdf", "impress_pdf_Export" );
    138
    139                if( OFFICE_VER.contains( "LibreOffice" ) ) {                                            // 8.0.1.0 (2021/10/29) LibreOffice の時のみ使用可能
    140        //              FILTER_MAP.put( "ods_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
    141        //              FILTER_MAP.put( "xls_xlsx", "Calc MS Excel 2007 XML" );                 // 8.0.1.0 (2021/10/29)
    142
    143                        FILTER_MAP.put( "ods_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
    144                        FILTER_MAP.put( "xls_xlsx", "Calc Office Open XML" );                   // 8.0.1.0 (2021/10/29)
    145
    146                        // share¥registry¥writer.xcd
    147                        FILTER_MAP.put( "odt_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
    148                        FILTER_MAP.put( "doc_docx", "MS Word 2007 XML" );                               // 8.0.1.0 (2021/10/29)
    149                        // ※ writer_MS_Word_2007 は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    150
    151                        // share¥registry¥impress.xcd
    152                        FILTER_MAP.put( "odp_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
    153                        FILTER_MAP.put( "ppt_pptx", "Impress MS PowerPoint 2007 XML" ); // 8.0.1.0 (2021/10/29)
    154                        // ※ MS PowerPoint 2007 XML は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    155                        // ※ Office Open XML Presentation は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
    156                }
    157        };
    158
    159        /**
    160         * ｺﾝｽﾄﾗｸﾀです｡
    161         *
    162         * #DocConverter(input, true)と同じです｡
    163         *
    164         * @param input ﾌｧｲﾙ一覧(CSV形式)
    165         * @see #DocConverter_OOO(String[])
    166         */
    167        public DocConverter_OOO( final String input ) {
    168                this( StringUtil.csv2Array( input ), true );
    169        }
    170
    171        /**
    172         * ｺﾝｽﾄﾗｸﾀです｡
    173         *
    174         * #DocConverter(input, true)と同じです｡
    175         *
    176         * @param input ﾌｧｲﾙ一覧(配列)
    177         * @see #DocConverter_OOO(String[], boolean)
    178         */
    179        public DocConverter_OOO( final String input[] ) {
    180                this( input, true );
    181        }
    182
    183        /**
    184         * ｺﾝｽﾄﾗｸﾀです｡
    185         *
    186         * isOnline(isOl)がtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
    187         * ｷｬｯｼｭします｡
    188         * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
    189         * 利用できないため､isOnlineをfalseに指定する必要があります｡
    190         *
    191         * @param input ﾌｧｲﾙ一覧(配列)
    192         * @param isOl ｵﾝﾗｲﾝ(Web環境での使用)かどうか
    193         */
    194        public DocConverter_OOO( final String input[], final boolean isOl ) {
    195                if( input == null || input.length == 0 || input[0].isEmpty() ) {
    196                        throw new HybsSystemException( "入力ﾌｧｲﾙが指定されていません｡" );
    197                }
    198                origName = input[0];
    199                final File inFile = new File( origName );
    200                if( !inFile.exists() ) {
    201                        throw new HybsSystemException( "入力ﾌｧｲﾙが存在しません｡[file=" + input[0] + "]" );
    202                }
    203                isOnline  = isOl;
    204                inputName = origName;
    205//              origName  = input[0];
    206
    207                if( input.length == 1 ) {
    208                        mergeFile = null;
    209                }
    210                else {
    211                        if( !"xls".equals( getSuffix( origName ) ) && !"ods".equals( getSuffix( origName ) ) ) {
    212                                throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､入力ﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
    213                        }
    214
    215                        mergeFile = new String[input.length-1];
    216                        for( int i=0; i<mergeFile.length; i++ ) {
    217                                final String mrgFile = input[i+1];
    218                                if( mrgFile.isEmpty() || !( new File( mrgFile ) ).exists() ) {
    219                                        throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙが指定されていないか､または存在しません｡[file=" + mrgFile + "]" );
    220                                }
    221                                if( inputName.equals( mrgFile ) ) {
    222                                        throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙに入力ﾌｧｲﾙと同じﾌｧｲﾙが指定されてます｡[file=" + mrgFile + "]" );
    223                                }
    224                                if( !"xls".equals( getSuffix( mrgFile ) ) && !"ods".equals( getSuffix( mrgFile ) ) ) {
    225                                        throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､ﾏｰｼﾞﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
    226                                }
    227                                mergeFile[i] = mrgFile;
    228                        }
    229                }
    230        }
    231
    232        /**
    233         * SOficeのｺﾝﾎﾟｰﾈﾝﾄを起動します｡
    234         *
    235         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    236         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    237         *
    238         * @og.rev 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
    239         *
    240         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    241         * @see #close()
    242         * @see #close(boolean)
    243         */
    244        public void open() throws Throwable {
    245                // ﾌﾟﾛｾｽの取得
    246                if( soffice == null ) {
    247                        if( isOnline ) {
    248                                soffice = ProcessFactory.newInstance();
    249                        }
    250                        else {
    251                                soffice = new SOfficeProcess( "docconverter.class" );
    252                                soffice.bootstrap();
    253                        }
    254
    255                        // ﾏｰｼﾞする場合は､ﾏｰｼﾞ対象のﾌｧｲﾙをﾃﾝﾎﾟﾗﾘにｺﾋﾟｰする(readOnly回避のため)
    256                        // ﾃﾝﾌﾟﾚｰﾄ(無題)として上げると､ｼｰﾄｺﾋﾟｰ先として特定できなくなるため
    257                        if( mergeFile != null ) {
    258                                final File origFile = new File( origName );
    259                                inputName = soffice.getTempPath() + System.currentTimeMillis() + "_" + origFile.getName();
    260                                FileUtil.copy( origFile, new File( inputName ) );
    261                        }
    262                }
    263
    264                // 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
    265                xComp = getComponent( inputName, ( mergeFile == null ? true : false ), false );
    266
    267                if( mergeFile != null ) {
    268                        for( int i=0; i<mergeFile.length; i++ ) {
    269                                merge( mergeFile[i] );
    270                        }
    271                }
    272        }
    273
    274        /**
    275         * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄを取得します｡
    276         *
    277         * @param       input                   ﾌｧｲﾙ名
    278         * @param       isHidden                隠し属性[true/false]
    279         * @param       isAsTemplate    OpenOffice上のTemplate属性[true/false]
    280         *
    281         * @og.rev 8.1.0.2 (2022/01/14) odsﾌｫｰﾏｯﾄｴﾗｰ時には、rtnDoc が null になる
    282         *
    283         * @return      ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
    284         */
    285//      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    286        private XComponent getComponent( final String input, final boolean isHidden, final boolean isAsTemplate ) {
    287                final PropertyValue[] calcProps = new PropertyValue[2];
    288                calcProps[0] = new PropertyValue();
    289                calcProps[0].Name = "Hidden";
    290                calcProps[0].Value = isHidden;
    291                calcProps[1] = new PropertyValue();
    292                calcProps[1].Name = "AsTemplate";
    293                calcProps[1].Value = isAsTemplate;
    294
    295                final String url = "file:///" + input.replace( '\\', '/' );
    296
    297                XComponent rtnDoc;
    298//              final XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
    299                final XComponentLoader cloader = UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
    300                try {
    301                        rtnDoc = cloader.loadComponentFromURL( url, "_blank", 0, calcProps );
    302                }
    303                catch( final IOException ex ) {
    304                        throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(入出力ｴﾗｰ)｡", ex );
    305                }
    306                catch( final IllegalArgumentException ex ) {
    307                        throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(ﾊﾟﾗﾒｰﾀｰ不正)｡", ex );
    308                }
    309
    310                // 8.1.0.2 (2022/01/14)
    311                if( rtnDoc == null ) {
    312                        throw new HybsSystemException( "OpenOffice.ods ﾌｧｲﾙが不正です(例えば、印刷範囲の繰り返しに {@FORMALINE}が含まれるなど)" );
    313                }
    314
    315                return rtnDoc;
    316        }
    317
    318        /**
    319         * ﾄﾞｷｭﾒﾝﾄ(xls,ods)のﾏｰｼﾞを行います｡
    320         *
    321         * @param mergeInputName ﾏｰｼﾞ対象のﾌｧｲﾙ名
    322         */
    323//      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    324        private void merge( final String mergeInputName ) {
    325                // ﾏｰｼﾞする副ﾌｧｲﾙは､ﾃﾝﾌﾟﾚｰﾄ(無題)として上げる(readOnly回避のため)
    326                final XComponent subDoc = getComponent( mergeInputName, false, true );
    327
    328                final XDispatchProvider dispatchProvider
    329//                      = (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class
    330                        = UnoRuntime.queryInterface( XDispatchProvider.class
    331//                              ,((XController)UnoRuntime.queryInterface( XController.class
    332                                ,(UnoRuntime.queryInterface( XController.class
    333//                                      ,((XModel)UnoRuntime.queryInterface( XModel.class
    334                                        ,(UnoRuntime.queryInterface( XModel.class
    335                                                ,subDoc
    336                                        )).getCurrentController()
    337                                )).getFrame()
    338                        );
    339
    340                final XDispatchHelper xDispatchHelper = soffice.getDispatcher();
    341                xDispatchHelper.executeDispatch(dispatchProvider, ".uno:TableSelectAll", "", 0, new PropertyValue[0]);
    342
    343                String title = new File( inputName ).getName() ;
    344                title = title.substring( 0, title.indexOf( '.' ) );
    345
    346                final PropertyValue[] moveProps = new PropertyValue[3];
    347                moveProps[0] = new PropertyValue();
    348                moveProps[0].Name = "DocName";
    349                moveProps[0].Value = title;
    350                moveProps[1] = new PropertyValue();
    351                moveProps[1].Name = "Index";
    352                moveProps[1].Value = 32767;
    353                moveProps[2] = new PropertyValue();
    354                moveProps[2].Name = "Copy";
    355                moveProps[2].Value = true;
    356                xDispatchHelper.executeDispatch(dispatchProvider, ".uno:Move", "", 0, moveProps);
    357
    358                closeComponent( subDoc );
    359        }
    360
    361        /**
    362         * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    363         *
    364         * このｸﾛｰｽﾞ処理は､処理が正常終了した場合に呼び出しする必要があります｡
    365         * 例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    366         *
    367         * このﾒｿｯﾄﾞは#close(false)と同じです｡
    368         *
    369         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    370         * @see #close(boolean)
    371         */
    372        public void close() throws Throwable {
    373                close( false );
    374        }
    375
    376        /**
    377         * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    378         *
    379         * 引数のisErrがtrueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
    380         * falseの場合は､ﾌﾟﾛｾｽは､ﾌｧｸﾄﾘｸﾗｽを経由して､ｷｬｯｼｭに戻されます｡
    381         * (ﾊﾞｯﾁ処理の場合は､いずれの場合も､ﾌﾟﾛｾｽは強制的に破棄されます)
    382         *
    383         * 起動から変換､ｸﾛｰｽﾞまでの書く処理で例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    384         *
    385         * #close(false)は#close()と同じであるため､通常利用することはありません｡
    386         *
    387         * @og.rev 4.2.4.1 (2008/07/07 ) 終了処理を60回で終わるように修正
    388         * @og.rev 4.3.0.0 (2008/07/15 ) ↑は6秒しか待っていなかったので､60秒待つように修正
    389         *
    390         * @param       isErr   trueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
    391         */
    392//      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    393        public void close( final boolean isErr ) {
    394                if( xComp != null ) {
    395                        closeComponent( xComp );
    396                }
    397
    398                if( soffice != null ) {
    399                        if( isOnline ) {
    400                                if( isErr ) {
    401                                        ProcessFactory.remove( soffice );
    402                                }
    403                                else {
    404                                        ProcessFactory.release( soffice );
    405                                }
    406                        }
    407                        else {
    408                                soffice.close();
    409                        }
    410                }
    411
    412                // ﾏｰｼﾞした場合は､ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除
    413                // 6.0.0.1 (2014/04/25) These nested if statements could be combined
    414                if( mergeFile != null && ! ( new File( inputName ) ).delete() ) {
    415                        System.err.println( "ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除できませんでした｡[" + inputName + "]" );
    416                }
    417        }
    418
    419        /**
    420         * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
    421         *
    422         * @param comp ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
    423         */
    424//      @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    425        private void closeComponent( final XComponent comp ) {
    426                XCloseable closeable = null;
    427                for( int i=0;; ++i ) {
    428                        try {
    429//                              closeable = (XCloseable) UnoRuntime.queryInterface( XCloseable.class, comp );
    430                                closeable = UnoRuntime.queryInterface( XCloseable.class, comp );
    431                                closeable.close( true );
    432                                break;
    433                        }
    434                        catch( final CloseVetoException ex ) {
    435                                // 4.2.4.1 (2008/07/07 )
    436                                // 4.3.4.4 (2009/01/01)
    437                                if( i == 600 ) { throw new HybsSystemException( "sofficeﾌﾟﾛｾｽに接続できません｡", ex ); }
    438                                try {
    439                                        Thread.sleep( 100 );
    440                                }
    441                                catch( final InterruptedException ex2 ) {
    442                        //              throw new HybsSystemException( ex2 );
    443                                }
    444                        }
    445                }
    446        }
    447
    448        /**
    449         * 印刷を行います｡
    450         *
    451         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    452         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    453         *
    454         * @og.rev 4.3.0.0 (2008/07/16) ｽﾌﾟｰﾙが終わるまでwaitし､さらにﾌﾟﾘﾝﾀ発行の状況を監視し､正常終了かどうかを判断
    455         * @og.rev 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀｰを指定した場合のｴﾗｰﾊﾝﾄﾞﾘﾝｸﾞを追加
    456         * @og.rev 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
    457         *
    458         * @param       printer ﾌﾟﾘﾝﾀｰ名
    459         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    460         */
    461        public void print( final String printer ) throws Throwable {
    462                if( printer == null || printer.isEmpty() ) {
    463                        throw new HybsSystemException( "ﾌﾟﾘﾝﾀｰが指定されていません｡" );
    464                }
    465
    466        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(1)" ); }
    467//              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    468//              final XPrintable xprintable = (XPrintable) UnoRuntime.queryInterface( XPrintable.class, xComp );
    469                final XPrintable xprintable = UnoRuntime.queryInterface( XPrintable.class, xComp );
    470//              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    471//              final XPrintJobBroadcaster selection = (XPrintJobBroadcaster) UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
    472                final XPrintJobBroadcaster selection = UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
    473                final MyPrintJobListener listener = new MyPrintJobListener();
    474                selection.addPrintJobListener( listener );
    475
    476                final PropertyValue[] tmpProps = new PropertyValue[1];
    477                tmpProps[0] = new PropertyValue();
    478                tmpProps[0].Name = "Name";
    479                // 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
    480                // OSがLinuxの場合は､ﾌﾟﾘﾝﾀ名称の前後に"<",">"を付加
    481                tmpProps[0].Value = "LINUX".indexOf( HybsSystem.sys( "OS_INFO" ).toUpperCase( Locale.JAPAN ) ) >= 0 ? "<" + printer + ">" : printer;
    482
    483                // 4.3.4.4 (2009/01/01)
    484                try {
    485                        xprintable.setPrinter( tmpProps );
    486                }
    487                catch( final IllegalArgumentException ex ) {
    488                        throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
    489                }
    490
    491                // 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀを指定した場合は､PropertyValueに
    492                // ﾃﾞﾌｫﾙﾄﾌﾟﾘﾝﾀｰが入るため､引数の値と合致しているかで正しく設定されたかを確認
    493                String curPrinter = null;
    494                for( final PropertyValue chkProp : xprintable.getPrinter() ) {
    495                        if( "Name".equals( chkProp.Name) ) {
    496                                curPrinter = (String)chkProp.Value;
    497                                break;
    498                        }
    499                }
    500
    501//              final PropertyValue[] chkProps = xprintable.getPrinter();
    502//              for( int i=0; i<chkProps.length; i++ ) {
    503//                      if( "Name".equals( chkProps[i].Name) ) {
    504//                              curPrinter = (String)chkProps[i].Value;
    505//                              break;
    506//                      }
    507//              }
    508                if( !(printer.equalsIgnoreCase( curPrinter ) ) ) {
    509                        final String errMsg = "ﾌﾟﾘﾝﾀｰ[" + printer + "]を発行先に指定できませんでした｡" + CR
    510                                                        + "存在しないﾌﾟﾘﾝﾀ名が指定されている可能性があります｡";
    511                        throw new HybsSystemException( errMsg );
    512                }
    513
    514                // 4.3.0.0 (2008/07/16)
    515                final PropertyValue[] printProps = new PropertyValue[1];
    516                printProps[0] = new PropertyValue();
    517                printProps[0].Name = "Wait";
    518                printProps[0].Value = true;
    519
    520                // 4.3.4.4 (2009/01/01)
    521                try {
    522                        xprintable.print( printProps );
    523                }
    524                catch( final IllegalArgumentException ex ) {
    525                        throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
    526                }
    527
    528                // 4.3.0.0 (2008/07/16)
    529                // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
    530//              if( listener.getStatus() == null
    531//                              || listener.getStatus() != PrintableState.JOB_COMPLETED && listener.getStatus() != PrintableState.JOB_SPOOLED ) {
    532                if( listener.isError() ) {
    533                        throw new HybsSystemException ( "Error Occured while spooling print job. Check Spooler-Service!!!");
    534                }
    535        }
    536
    537        /**
    538         * ﾌﾟﾘﾝﾀｼﾞｮﾌﾞの状況を監視するﾘｽﾅｰです｡
    539         *
    540         * @author Hiroki.Nakamura
    541         */
    542        private static final class MyPrintJobListener implements XPrintJobListener {
    543                private PrintableState status   ;
    544
    545                /**
    546                 * PrintJobEventのｽﾃｰﾀｽを内部変数にｾｯﾄします｡
    547                 *
    548                 * @param       event   PrintJobEventｵﾌﾞｼﾞｪｸﾄ
    549                 */
    550                @Override
    551                public void printJobEvent( final PrintJobEvent event ) {
    552                        status = event.State;
    553                }
    554
    555                /**
    556                 * EventObjectの処理を実施します｡(ここでは何も行いません｡)
    557                 *
    558                 * @param       event   EventObjectｵﾌﾞｼﾞｪｸﾄ
    559                 */
    560                @Override
    561                public void disposing( final EventObject event ) {
    562                        // 何もありません｡(PMD ｴﾗｰ回避)
    563                }
    564
    565//              /**
    566//               * PrintableStateｵﾌﾞｼﾞｪｸﾄを返します｡
    567//               *
    568//               * @og.rev 8.0.3.0 (2021/12/17) Delete
    569//               *
    570//               * @return      PrintableStateｵﾌﾞｼﾞｪｸﾄ
    571//               */
    572//              public PrintableState getStatus() {
    573//                      return status;
    574//              }
    575
    576                /**
    577                 * PrintableStateｵﾌﾞｼﾞｪｸﾄの状態を返します｡
    578                 *
    579                 * statusが nullか､COMPLETEDでなく､SPOOLEDでない場合にｴﾗｰと判断します｡
    580                 *
    581                 * @return      ｴﾗｰの場合､true
    582                 */
    583                public boolean isError() {
    584                        return status == null || status != PrintableState.JOB_COMPLETED && status != PrintableState.JOB_SPOOLED ;
    585                }
    586        }
    587
    588        /**
    589         * Calc(ods)出力を行います｡
    590         *
    591         * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    592         *
    593         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    594         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    595         *
    596         * @param       outputName      出力ﾌｧｲﾙ名
    597         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    598         */
    599//      public void ods( final String outputName ) throws Throwable {
    600//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ods" ) );
    601//              saveDoc( outputName, getFilterName( inputName, "ods" ) );
    602//      }
    603
    604//      /**
    605//       * Excel(xls)出力を行います｡
    606//       *
    607//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    608//       *
    609//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    610//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    611//       *
    612//       * @param       outputName      出力ﾌｧｲﾙ名
    613//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    614//       */
    615//      public void xls( final String outputName ) throws Throwable {
    616//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "xls" ) );
    617//              saveDoc( outputName, getFilterName( inputName, "xls" ) );
    618//      }
    619
    620//      /**
    621//       * Writer(ods)出力を行います｡
    622//       *
    623//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    624//       *
    625//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    626//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    627//       *
    628//       * @param       outputName      出力ﾌｧｲﾙ名
    629//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    630//       */
    631//      public void odt( final String outputName ) throws Throwable {
    632//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odt" ) );
    633//              saveDoc( outputName, getFilterName( inputName, "odt" ) );
    634//      }
    635
    636//      /**
    637//       * Word(doc)出力を行います｡
    638//       *
    639//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    640//       *
    641//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    642//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    643//       *
    644//       * @param       outputName      出力ﾌｧｲﾙ名
    645//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    646//       */
    647//      public void doc( final String outputName ) throws Throwable {
    648//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "doc" ) );
    649//              saveDoc( outputName, getFilterName( inputName, "doc" ) );
    650//      }
    651
    652//      /**
    653//       * Impress(odp)出力を行います｡
    654//       *
    655//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    656//       *
    657//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    658//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    659//       *
    660//       * @param       outputName      出力ﾌｧｲﾙ名
    661//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    662//       */
    663//      public void odp( final String outputName ) throws Throwable {
    664//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "odp" ) );
    665//              saveDoc( outputName, getFilterName( inputName, "odp" ) );
    666//      }
    667
    668//      /**
    669//       * PowerPoint(ppt)出力を行います｡
    670//       *
    671//       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    672//       *
    673//       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    674//       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    675//       *
    676//       * @param       outputName      出力ﾌｧｲﾙ名
    677//       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    678//       */
    679//      public void ppt( final String outputName ) throws Throwable {
    680//      //      saveDoc( outputName, getFilterName( getSuffix( inputName ), "ppt" ) );
    681//              saveDoc( outputName, getFilterName( inputName, "ppt" ) );
    682//      }
    683
    684        /**
    685         * PDF出力を行います｡
    686         *
    687         * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    688         *
    689         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    690         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    691         *
    692         * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
    693         *
    694         * @param       outputName      出力ﾌｧｲﾙ名
    695         * @param       pdfPasswd       PDFﾊﾟｽﾜｰﾄﾞ
    696         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    697         */
    698        public void pdf( final String outputName, final String pdfPasswd ) throws Throwable {
    699                if( !checkOutput( outputName ) ){ return; }                     // 8.1.0.3 (2022/01/21)
    700
    701        //      savePdf( outputName, getFilterName( getSuffix( inputName ), "pdf" ), pdfPasswd );
    702                savePdf( outputName, getFilterName( inputName, "pdf" ), pdfPasswd );
    703        }
    704
    705        //      /**
    706        //       * 【保留】Excel2007(xlsx)出力を行います｡
    707        //       *
    708        //       * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    709        //       *
    710        //       * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    711        //       * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    712        //       *
    713        //       * @og.rev 8.0.3.0 (2021/12/17) ods→xlsx変換時のｼｰﾄ毎の行数
    714        //       *
    715        //       * @param       outputName      出力ﾌｧｲﾙ名
    716        //       * @param       sheetRows       ｼｰﾄ毎の行数List
    717        //       * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    718        //       */
    719        //      public void xlsx( final String outputName,final List<Integer> sheetRows ) throws Throwable {
    720        //              saveDoc( outputName, getFilterName( inputName, "xlsx" ) );
    721        //
    722        //              // 余分な行やｶﾗﾑを除去(ただし、ものすごく遅い)
    723        //              final File outputFile = new File( outputName );
    724        //              final ExcelModel excel = new ExcelModel( outputFile , true );
    725        //              excel.activeWorkbook( sheetRows );
    726        //              excel.saveFile( outputFile );
    727        //      }
    728
    729        /**
    730         * 出力ﾌｧｲﾙから出力形式を自動判別し､変換を行います｡
    731         *
    732         * 入出力形式で未対応の場合(形式は入出力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
    733         *
    734         * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
    735         * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
    736         *
    737         * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
    738         *
    739         * @param       outputName      出力ﾌｧｲﾙ名
    740         * @throws Throwable 何らかのｴﾗｰが発生した場合｡
    741         */
    742        public void auto( final String outputName ) throws Throwable {
    743                if( !checkOutput( outputName ) ){ return; }                     // 8.1.0.3 (2022/01/21)
    744
    745                final String outSuffix = getSuffix( outputName );
    746                if( "pdf".equalsIgnoreCase( outSuffix ) ) {
    747//                      savePdf( outputName, getFilterName( getSuffix( inputName ), outSuffix ), null );
    748                        savePdf( outputName, getFilterName( inputName, outSuffix ), null );
    749                }
    750                else {
    751//                      saveDoc( outputName, getFilterName( getSuffix( inputName ), outSuffix ) );
    752                        saveDoc( outputName, getFilterName( inputName, outSuffix ) );
    753                }
    754        }
    755
    756        /**
    757         * ﾌｨﾙﾀｰ名を指定して､各種ﾌｧｲﾙ形式に出力を行います｡
    758         *
    759         * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
    760         *
    761         * @param       outputName      出力ﾌｧｲﾙ名
    762         * @param       filter          ﾌｨﾙﾀｰ名
    763         */
    764        private void saveDoc( final String outputName, final String filter ) {
    765//              if( !checkOutput( outputName ) ){ return; }
    766
    767                final PropertyValue[] storeProps = new PropertyValue[1];
    768                storeProps[0] = new PropertyValue();
    769                storeProps[0].Name = "FilterName";
    770                storeProps[0].Value = filter;
    771
    772                final String url = "file:///" + outputName.replace( '\\', '/' );
    773        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(2)" ); }
    774//              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    775//              final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
    776                final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
    777                try {
    778                        xstorable.storeAsURL( url, storeProps );
    779                }
    780                catch( final Throwable th ) {
    781                        throw new HybsSystemException( "ﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
    782                }
    783        }
    784
    785        /**
    786         * ﾌｨﾙﾀｰを指定してPDF出力を行います｡
    787         *
    788         * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
    789         *
    790         * @param       outputName      出力ﾌｧｲﾙ名
    791         * @param       filter          ﾌｨﾙﾀｰ名
    792         * @param       pdfPasswd       PDFﾊﾟｽﾜｰﾄﾞ
    793         */
    794        private void savePdf( final String outputName, final String filter, final String pdfPasswd ) {
    795//              if( !checkOutput( outputName ) ){ return; }
    796
    797                final PropertyValue[] storeProps;
    798                if( pdfPasswd == null || pdfPasswd.isEmpty() ) {
    799                        storeProps = new PropertyValue[1];
    800                        storeProps[0] = new PropertyValue();
    801                        storeProps[0].Name = "FilterName";
    802                        storeProps[0].Value = filter;
    803                }
    804                // 帳票要求ﾃｰﾌﾞﾙでPDFﾊﾟｽﾜｰﾄﾞが設定されている場合
    805                else {
    806                        final PropertyValue[] filterProps = new PropertyValue[2];
    807                        filterProps[0] = new PropertyValue();
    808                        filterProps[0].Name = "EncryptFile";
    809                        filterProps[0].Value = true;
    810                        filterProps[1] = new PropertyValue();
    811                        filterProps[1].Name = "DocumentOpenPassword";
    812                        filterProps[1].Value = pdfPasswd;
    813
    814                        storeProps = new PropertyValue[2];
    815                        storeProps[0] = new PropertyValue();
    816                        storeProps[0].Name = "FilterName";
    817                        storeProps[0].Value = "calc_pdf_Export";
    818                        storeProps[1] = new PropertyValue();
    819                        storeProps[1].Name = "FilterData";
    820                        storeProps[1].Value = filterProps;
    821                }
    822
    823                final String url = "file:///" + outputName.replace( '\\', '/' );
    824        //      if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(3)" ); }
    825//              @SuppressWarnings("cast")       // OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
    826//              final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
    827                final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
    828                try {
    829                        xstorable.storeToURL( url, storeProps );
    830                }
    831                catch( final Throwable th ) {
    832                        final String err = "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]"
    833                                                        + " URL=" + url + " , storeProps=" + storeProps + " , xComp=" + xComp ;
    834
    835//                      throw new HybsSystemException( "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
    836                        throw new HybsSystemException( err, th );
    837                }
    838        }
    839
    840        /**
    841         * 出力ﾌｧｲﾙのﾁｪｯｸを行います｡
    842         *
    843         * @og.rev 8.1.0.3 (2022/01/21) ﾌｧｲﾙの拡張子が同じ場合は、copyで対応する。
    844         *
    845         * @param       outputName      出力ﾌｧｲﾙ名
    846         *
    847         * @return      処理対象かどうか(入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合は､falseが返ります)
    848         */
    849        private boolean checkOutput( final String outputName ) {
    850                if( outputName == null || outputName.isEmpty() ) {
    851                        throw new HybsSystemException( "出力ﾌｧｲﾙが指定されていません｡" );
    852                }
    853
    854                try {
    855                        // 8.1.0.3 (2022/01/21) 出力ﾌｧｲﾙがあれば、無条件削除
    856                        final Path outPath = Paths.get( outputName );
    857                        if( Files.exists( outPath ) ) { Files.delete( outPath ); }
    858//                      if( Files.exists( outPath ) && !Files.deleteIfExists( outPath ) ) {
    859//                              throw new HybsSystemException( "出力先の既存ﾌｧｲﾙが削除できません｡[file=" + outputName + "]" );
    860//                      }
    861
    862                        // 8.1.0.3 (2022/01/21) 拡張子が同じなら、copyする。
    863                        if( getSuffix( inputName ).equals( getSuffix( outputName ) ) ) {
    864                                final Path inPath = Paths.get( inputName );
    865                                Files.copy( inPath , outPath , StandardCopyOption.REPLACE_EXISTING );
    866                                return false;
    867                        }
    868                }
    869//              catch( final IOException ex ) {         // 意味不明なｴﾗｰが出る。
    870                catch( final Throwable ex ) {
    871                        throw new HybsSystemException( "ﾌｧｲﾙｺﾋﾟｰが失敗しました｡[in=" + inputName + "],out=" + outputName + "]" ,ex );
    872                }
    873
    874                return true;
    875
    876//              if( outFile.exists() ) {
    877//                      if( inFile.getAbsoluteFile().equals( outFile.getAbsoluteFile() ) ) {
    878//                              // 入力と出力が同じﾌｧｲﾙの場合な何もしない
    879//                              return false;
    880//                      }
    881//                      else if( !outFile.delete() ) {
    882//                              throw new HybsSystemException( "出力先の既存ﾌｧｲﾙが削除できません｡[file=" + outputName + "]" );
    883//                      }
    884//              }
    885//              return true;
    886        }
    887
    888        /**
    889         * 入出力の形式(拡張子)からﾌｨﾙﾀｰ名を取得します｡
    890         *
    891         * 入力ﾌｧｲﾙ名からｻﾌｨｯｸｽを取り出して､FILTER_MAP からﾌｨﾙﾀｰ名を取り出します｡
    892         *
    893         * @og.rev 8.0.1.0 (2021/10/29) ﾒｯｾｰｼﾞ修正
    894         *
    895//       * @param       inSuffix        入力拡張子
    896         * @param       inputName       入力ﾌｧｲﾙ名
    897         * @param       outSuffix       出力拡張子
    898         *
    899         * @return      ﾌｨﾙﾀｰ名
    900         */
    901//      private static String getFilterName( final String inSuffix, final String outSuffix ) {
    902        private static String getFilterName( final String inputName, final String outSuffix ) {
    903                final String inSuffix = getSuffix( inputName );
    904
    905                final String filterName = FILTER_MAP.get( inSuffix + "_" + outSuffix );
    906                if( filterName == null ) {
    907                        final String errMsg = "入力ﾌｧｲﾙ=[" + inputName + "] , 出力形式=[" + outSuffix + "]" + CR
    908                                                        + "入力形式､出力形式は､以下の対応表に基づき､設定して下さい｡" + CR
    909                                                        + "入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)     ,PDF]" + CR
    910                                                        + "入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)      ,PDF]" + CR
    911                                                        + "入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx),PDF]" + CR
    912                                                        + "xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡" + CR ;
    913                        throw new HybsSystemException( errMsg );
    914                }
    915                return filterName;
    916        }
    917
    918        /**
    919         * ﾌｧｲﾙ名から拡張子(小文字)を求めます｡
    920         *
    921         * @param       fileName        ﾌｧｲﾙ名
    922         *
    923         * @return      拡張子(小文字)…存在しない場合は、空文字列
    924         */
    925        private static String getSuffix( final String fileName ) {
    926//              String suffix = null;
    927                String suffix = "";
    928                if( fileName != null ) {
    929                        final int sufIdx = fileName.lastIndexOf( '.' );
    930                        if( sufIdx >= 0 ) {
    931                                suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
    932                        }
    933                }
    934                return suffix;
    935        }
    936
    937//      /**
    938//       * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    939//       *
    940//       * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    941//       *
    942//       * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
    943//       *
    944//       * @param       inputFile       入力ﾌｧｲﾙ名
    945//       * @param       outputFile      出力ﾌｧｲﾙ名
    946//       * @see #convert(String[], String, boolean)
    947//       */
    948//      public static final void convert( final String inputFile, final String outputFile ) {
    949////            convert( StringUtil.csv2Array( inputFile ), outputFile );
    950//              convert( StringUtil.csv2Array( inputFile ), outputFile, true ); // 8.0.3.0 (2021/12/17)
    951//      }
    952
    953//      /**
    954//       * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    955//       *
    956//       * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    957//       *
    958//       * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
    959//       *
    960//       * @param       inputFile       入力ﾌｧｲﾙ名配列
    961//       * @param       outputFile      出力ﾌｧｲﾙ名
    962//       * @see #convert(String[], String, boolean)
    963//       */
    964//      public static final void convert( final String[] inputFile, final String outputFile ) {
    965//              convert( inputFile, outputFile, true );
    966//      }
    967
    968        /**
    969         * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
    970         *
    971         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    972         *
    973         * isOnlineがtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
    974         * ｷｬｯｼｭします｡
    975         * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
    976         * 利用できないため､isOnlineをfalseに指定する必要があります｡
    977         *
    978         * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
    979         *
    980         * @param       inputFile       入力ﾌｧｲﾙ名配列
    981         * @param       outputFile      出力ﾌｧｲﾙ名
    982         * @param       isOnline        ｵﾝﾗｲﾝ(Web環境での使用)かどうか
    983         */
    984        public static final void convert( final String inputFile[], final String outputFile, final boolean isOnline ) {
    985                final DocConverter_OOO dc = new DocConverter_OOO( inputFile, isOnline );
    986                try {
    987                        dc.open();
    988                        dc.auto( outputFile );
    989                        dc.close();
    990                }
    991                catch( final Throwable th ) {
    992                        dc.close( true );
    993                        throw new HybsSystemException( th );
    994                }
    995        }
    996
    997        /**
    998         * ﾄﾞｷｭﾒﾝﾄの変換を行います｡
    999         *
    1000         * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
    1001         *
    1002         * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
    1003         * @og.rev 6.3.9.1 (2015/11/27) A method/constructor shouldnt explicitly throw java.lang.Exception(PMD)｡
    1004         * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
    1005         *
    1006         * @param       args    ｺﾏﾝﾄﾞ引数配列
    1007         */
    1008        public static void main( final String[] args ) {
    1009                if( args.length < 2 ) {
    1010                        System.out.println( "usage : OdsConverter [inputFile] [outputFile]" );
    1011                        return;
    1012                }
    1013
    1014                DocConverter_OOO.convert( new String[] {args[0]}, args[1], false );
    1015
    1016//              final File input  = new File( args[0] );
    1017//              final File output = new File( args[1] );
    1018//
    1019//              // 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
    1020//              if( outPath.mkdirs() ) {
    1021//                      System.err.println( args[1] + " の ﾃﾞｨﾚｸﾄﾘ作成に失敗しました｡" );
    1022//              }
    1023//
    1024//              final String absPath = output.getAbsolutePath() + FS ;          // 8.0.3.0 (2021/12/17)
    1025//              if( input.isDirectory() ) {
    1026//                      final File[] inputFiles = input.listFiles();
    1027//                      // 6.3.9.0 (2015/11/06) null になっている可能性があるﾒｿｯﾄﾞの戻り値を利用している(findbugs)
    1028//                      if( inputFiles != null ) {
    1029//                              for( final File file : inputFiles ) {
    1030//                                      final String inputFile = file.getAbsolutePath();
    1031////                                    final String outputFile = output.getAbsolutePath() + File.separator + file.getName().replace( ".xls", ".ods" );
    1032//                                      final String outputFile = absPath + file.getName().replace( ".xls", ".ods" );
    1033//                                      convert( StringUtil.csv2Array( inputFile ), outputFile, false );
    1034//                              }
    1035//                      }
    1036//              }
    1037//              else {
    1038//                      final String inputFile = input.getAbsolutePath();
    1039////                    final String outputFile = output.getAbsolutePath() + File.separator + input.getName().replace( ".xls", ".ods" );
    1040//                      final String outputFile = absPath + input.getName().replace( ".xls", ".ods" );
    1041//                      convert( StringUtil.csv2Array( inputFile ), outputFile, false );
    1042//              }
    1043        }
    1044}