/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.hayabusa.report2;

import java.io.File;
import java.util.Map;
import java.util.HashMap;
import java.util.Locale;
// import java.util.List;										// 8.0.3.0 (2021/12/17) 【保留】
import java.nio.file.Files;										// 8.1.0.3 (2022/01/21)
import java.nio.file.Paths;										// 8.1.0.3 (2022/01/21)
import java.nio.file.Path;										// 8.1.0.3 (2022/01/21)
import java.nio.file.StandardCopyOption;						// 8.1.0.3 (2022/01/21)

// import org.opengion.fukurou.system.HybsConst;				// 8.0.1.0 (2021/10/29)
// import org.opengion.fukurou.model.ExcelModel;				// 8.0.3.0 (2021/12/17)【保留】
import org.opengion.fukurou.util.FileUtil;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import static org.opengion.fukurou.system.HybsConst.CR ;		// 6.1.0.0 (2014/12/26)
// import static org.opengion.fukurou.system.HybsConst.FS ;		// 8.0.3.0 (2021/12/17)

import com.sun.star.beans.PropertyValue;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XController;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.frame.XDispatchProvider;
import com.sun.star.frame.XModel;
import com.sun.star.frame.XStorable;
import com.sun.star.io.IOException;
import com.sun.star.lang.EventObject;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.XComponent;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.util.CloseVetoException;
import com.sun.star.util.XCloseable;
import com.sun.star.view.PrintJobEvent;
import com.sun.star.view.PrintableState;
import com.sun.star.view.XPrintJobBroadcaster;
import com.sun.star.view.XPrintJobListener;
import com.sun.star.view.XPrintable;

import com.sun.star.sheet.XCalculatable;						// 8.1.1.2 (2022/02/25)

/**
 * OpenOfficeを利用して様々な形式のﾌｧｲﾙを読み込み､出力・印刷を行うための変換ｸﾗｽです｡
 *
 * 変換を行うことのできる入出力のﾌｫｰﾏｯﾄ以下の通りです｡
 *
 * [対応ﾌｫｰﾏｯﾄ]
 *  入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)      ,PDF]
 *  入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)       ,PDF]
 *  入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx) ,PDF]
 *  入力[ * 上記の全て               ] ⇒ 印刷
 *
 * ※ xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡
 *
 * 変換を行うには､以下の2通りの方法があります｡
 * <del>
 * (1)簡易的な変換ﾒｿｯﾄﾞを利用する場合
 *   #convert(String, String)を利用して､変換を行います｡
 *   この場合､出力形式は､出力ﾌｧｲﾙの拡張子に従って自動的に決定されます｡
 *   このため､印刷処理などを行う場合は､(2)の方法で出力して下さい｡
 * </del>
 * (2)段階的に各ﾒｿｯﾄﾞを呼び出して変換する場合
 *   ｵﾌﾞｼﾞｪｸﾄを生成した後､{@link #open()}､#(各種変換ﾒｿｯﾄﾞ)､{@link #clone()}を
 *   順番に呼び出して変換を行います｡
 *   この場合､出力形式は､それに対応するﾒｿｯﾄﾞを呼び出すことで決定されます｡
 *
 *   また､変換を行うための､各種ﾒｿｯﾄﾞは､例外としてThrowableを投げるように定義されています｡
 *   このｸﾗｽを利用する場合は､このThrowableをcatchし､catch句で､必ず{@link #close( boolean )}に､
 *   "true"(ｴﾗｰ発生時のｸﾛｰｽﾞ処理)を指定して､終了処理を行って下さい｡
 *   (これを行わない場合､OpenOfficeの不要なﾌﾟﾛｾｽが残ってしまう可能性があります)
 *
 * また､出力ﾌｧｲﾙが既に存在する場合､出力ﾌｧｲﾙは一旦削除された後､処理されます｡
 * なお､入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合､何も処理されません｡(例外も発行されません)
 *
 * 入力ﾌｧｲﾙを､CSV形式で複数指定した場合､複数の入力ﾌｧｲﾙをﾏｰｼﾞして出力します｡
 * ※1 現状は､ﾌｧｲﾙのﾏｰｼﾞは､入力ﾌｧｲﾙがExcelまたはCalcの場合のみ対応しています｡
 *
 * ※ DocConverter は､ｸﾗｳﾄﾞ対応されていません｡変換時はﾛｰｶﾙﾌｧｲﾙ間で行ってください｡
 *
 * @og.group 帳票ｼｽﾃﾑ
 *
 * @version  4.0
 * @author   Hiroki.Nakamura
 * @since    JDK1.6
 */
public class DocConverter_OOO {
//	// XLSX は、LibreOffice のみ実行可能なので、その判定用に使用する。
//	private static final String OFFICE_HOME = HybsConst.getenv( "OFFICE_HOME","NULL" );	// 8.0.1.0 (2021/10/29) 環境変数から取得

	private final boolean			isOnline;			// ｵﾝﾗｲﾝ処理かどうか(ｵﾝﾗｲﾝ処理の場合､ﾌﾟﾛｾｽはﾌｧｸﾄﾘｸﾗｽ経由で生成されます)
	private final String[]			mergeFile;

	private String					inputName;
	private String					origName;

	private XComponent				xComp;				// 5.1.8.0 (2010/07/01) ﾒｿｯﾄﾞと重なる変数名の変更
	private SOfficeProcess			soffice;

	// 入力､出力の拡張子とこれに対応するﾌｨﾙﾀｰ名
	// share¥registry¥calc.xcd 形式のﾌｧｲﾙ <node oor:name="****" 部分？

	/** staticｲﾆｼｬﾗｲｻﾞ後､読み取り専用にするので､ConcurrentHashMap を使用しません｡ */
	private static final Map<String,String> FILTER_MAP	= new HashMap<>();		// 6.4.1.1 (2016/01/16) filterMap → FILTER_MAP refactoring
	static {
		// 8.1.0.3 (2022/01/21) ﾌｧｲﾙの拡張子が同じ場合は、copyで対応する。
	//	FILTER_MAP.put( "ods_ods", "calc8" );
		FILTER_MAP.put( "xls_ods", "calc8" );
		FILTER_MAP.put( "ods_xls", "MS Excel 97" );
	//	FILTER_MAP.put( "xls_xls", "MS Excel 97" );
		FILTER_MAP.put( "ods_pdf", "calc_pdf_Export" );
		FILTER_MAP.put( "xls_pdf", "calc_pdf_Export" );
	//	FILTER_MAP.put( "odt_odt", "writer8" );
		FILTER_MAP.put( "doc_odt", "writer8" );
		FILTER_MAP.put( "odt_doc", "MS Word 97" );
	//	FILTER_MAP.put( "doc_doc", "MS Word 97" );
		FILTER_MAP.put( "odt_pdf", "writer_pdf_Export" );
		FILTER_MAP.put( "doc_pdf", "writer_pdf_Export" );
	//	FILTER_MAP.put( "odp_odp", "impress8" );
		FILTER_MAP.put( "ppt_odp", "impress8" );
		FILTER_MAP.put( "odp_ppt", "MS PowerPoint 97" );
	//	FILTER_MAP.put( "ppt_ppt", "MS PowerPoint 97" );
		FILTER_MAP.put( "odp_pdf", "impress_pdf_Export" );
		FILTER_MAP.put( "ppt_pdf", "impress_pdf_Export" );

//		if( OFFICE_HOME.contains( "LibreOffice" ) ) {						// 8.0.1.0 (2021/10/29) LibreOffice の時のみ使用可能
	//		FILTER_MAP.put( "ods_xlsx", "Calc MS Excel 2007 XML" );			// 8.0.1.0 (2021/10/29)
	//		FILTER_MAP.put( "xls_xlsx", "Calc MS Excel 2007 XML" );			// 8.0.1.0 (2021/10/29)

			FILTER_MAP.put( "ods_xlsx", "Calc Office Open XML" );			// 8.0.1.0 (2021/10/29)
			FILTER_MAP.put( "xls_xlsx", "Calc Office Open XML" );			// 8.0.1.0 (2021/10/29)

			// share¥registry¥writer.xcd
			FILTER_MAP.put( "odt_docx", "MS Word 2007 XML" );				// 8.0.1.0 (2021/10/29)
			FILTER_MAP.put( "doc_docx", "MS Word 2007 XML" );				// 8.0.1.0 (2021/10/29)
			// ※ writer_MS_Word_2007 は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)

			// share¥registry¥impress.xcd
			FILTER_MAP.put( "odp_pptx", "Impress MS PowerPoint 2007 XML" );	// 8.0.1.0 (2021/10/29)
			FILTER_MAP.put( "ppt_pptx", "Impress MS PowerPoint 2007 XML" );	// 8.0.1.0 (2021/10/29)
			// ※ MS PowerPoint 2007 XML は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
			// ※ Office Open XML Presentation は､failed: 0x81a(Error Area:Io Class:Parameter Code:26)
//		}
	};

	/**
	 * ｺﾝｽﾄﾗｸﾀです｡
	 *
	 * #DocConverter(input, true)と同じです｡
	 *
	 * @param input ﾌｧｲﾙ一覧(CSV形式)
	 * @see #DocConverter_OOO(String[])
	 */
	public DocConverter_OOO( final String input ) {
		this( StringUtil.csv2Array( input ), true );
	}

	/**
	 * ｺﾝｽﾄﾗｸﾀです｡
	 *
	 * #DocConverter(input, true)と同じです｡
	 *
	 * @param input ﾌｧｲﾙ一覧(配列)
	 * @see #DocConverter_OOO(String[], boolean)
	 */
	public DocConverter_OOO( final String input[] ) {
		this( input, true );
	}

	/**
	 * ｺﾝｽﾄﾗｸﾀです｡
	 *
	 * isOnline(isOl)がtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
	 * ｷｬｯｼｭします｡
	 * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
	 * 利用できないため､isOnlineをfalseに指定する必要があります｡
	 *
	 * @param input ﾌｧｲﾙ一覧(配列)
	 * @param isOl ｵﾝﾗｲﾝ(Web環境での使用)かどうか
	 */
	public DocConverter_OOO( final String input[], final boolean isOl ) {
		if( input == null || input.length == 0 || input[0].isEmpty() ) {
			throw new HybsSystemException( "入力ﾌｧｲﾙが指定されていません｡" );
		}
		origName = input[0];
		final File inFile = new File( origName );
		if( !inFile.exists() ) {
			throw new HybsSystemException( "入力ﾌｧｲﾙが存在しません｡[file=" + input[0] + "]" );
		}
		isOnline  = isOl;
		inputName = origName;
//		origName  = input[0];

		if( input.length == 1 ) {
			mergeFile = null;
		}
		else {
			if( !"xls".equals( getSuffix( origName ) ) && !"ods".equals( getSuffix( origName ) ) ) {
				throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､入力ﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
			}

			mergeFile = new String[input.length-1];
			for( int i=0; i<mergeFile.length; i++ ) {
				final String mrgFile = input[i+1];
				if( mrgFile.isEmpty() || !( new File( mrgFile ) ).exists() ) {
					throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙが指定されていないか､または存在しません｡[file=" + mrgFile + "]" );
				}
				if( inputName.equals( mrgFile ) ) {
					throw new HybsSystemException( "ﾏｰｼﾞﾌｧｲﾙに入力ﾌｧｲﾙと同じﾌｧｲﾙが指定されてます｡[file=" + mrgFile + "]" );
				}
				if( !"xls".equals( getSuffix( mrgFile ) ) && !"ods".equals( getSuffix( mrgFile ) ) ) {
					throw new HybsSystemException( "ﾌｧｲﾙのﾏｰｼﾞを行う場合､ﾏｰｼﾞﾌｧｲﾙは､ExcelまたはCacl形式である必要があります｡" );
				}
				mergeFile[i] = mrgFile;
			}
		}
	}

	/**
	 * SOficeのｺﾝﾎﾟｰﾈﾝﾄを起動します｡
	 *
	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * @og.rev 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
	 *
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 * @see #close()
	 * @see #close(boolean)
	 */
	public void open() throws Throwable {
		// ﾌﾟﾛｾｽの取得
		if( soffice == null ) {
			if( isOnline ) {
				soffice = ProcessFactory.newInstance();
			}
			else {
				soffice = new SOfficeProcess( "docconverter.class" );
				soffice.bootstrap();
			}

			// ﾏｰｼﾞする場合は､ﾏｰｼﾞ対象のﾌｧｲﾙをﾃﾝﾎﾟﾗﾘにｺﾋﾟｰする(readOnly回避のため)
			// ﾃﾝﾌﾟﾚｰﾄ(無題)として上げると､ｼｰﾄｺﾋﾟｰ先として特定できなくなるため
			if( mergeFile != null ) {
				final File origFile = new File( origName );
				inputName = soffice.getTempPath() + System.currentTimeMillis() + "_" + origFile.getName();
				FileUtil.copy( origFile, new File( inputName ) );
			}
		}

		// 5.1.7.0 (2010/06/01) ﾏｰｼﾞ処理対応
		xComp = getComponent( inputName, ( mergeFile == null ? true : false ), false );

		if( mergeFile != null ) {
			for( int i=0; i<mergeFile.length; i++ ) {
				merge( mergeFile[i] );
			}
		}
	}

	/**
	 * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄを取得します｡
	 *
	 * @param	input			ﾌｧｲﾙ名
	 * @param	isHidden		隠し属性[true/false]
	 * @param	isAsTemplate	OpenOffice上のTemplate属性[true/false]
	 *
	 * @og.rev 8.1.0.2 (2022/01/14) odsﾌｫｰﾏｯﾄｴﾗｰ時には、rtnDoc が null になる
	 * @og.rev 8.1.1.2 (2022/02/25) calcの計算式がLibreOfficeで実行されない対応
	 *
	 * @return	ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
	 */
//	@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
	private XComponent getComponent( final String input, final boolean isHidden, final boolean isAsTemplate ) {
		final PropertyValue[] calcProps = new PropertyValue[2];
		calcProps[0] = new PropertyValue();
		calcProps[0].Name = "Hidden";
		calcProps[0].Value = isHidden;
		calcProps[1] = new PropertyValue();
		calcProps[1].Name = "AsTemplate";
		calcProps[1].Value = isAsTemplate;

		final String url = "file:///" + input.replace( '\\', '/' );

		XComponent rtnDoc;
//		final XComponentLoader cloader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
		final XComponentLoader cloader = UnoRuntime.queryInterface( XComponentLoader.class, soffice.getDesktop() );
		try {
			rtnDoc = cloader.loadComponentFromURL( url, "_blank", 0, calcProps );

			// 8.1.1.2 (2022/02/25) calcの計算式がLibreOfficeで実行されない対応
			final XCalculatable calc = UnoRuntime.queryInterface(XCalculatable.class,rtnDoc);
		//	calc.enableAutomaticCalculation(true);
			calc.calculateAll();
		}
		catch( final IOException ex ) {
			throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(入出力ｴﾗｰ)｡", ex );
		}
		catch( final IllegalArgumentException ex ) {
			throw new HybsSystemException( "OpenOfficeの立ち上げ時にｴﾗｰが発生しました(ﾊﾟﾗﾒｰﾀｰ不正)｡", ex );
		}

		// 8.1.0.2 (2022/01/14)
		if( rtnDoc == null ) {
			final String errMsg = "OpenOffice[" + input + "]ﾌｧｲﾙが不正です｡" + CR
								+ "印刷範囲設定や、ﾃﾞｰﾀにCTRL文字等が含まれていないかご確認ください｡";
			throw new HybsSystemException( errMsg );
		}

		return rtnDoc;
	}

	/**
	 * ﾄﾞｷｭﾒﾝﾄ(xls,ods)のﾏｰｼﾞを行います｡
	 *
	 * @param mergeInputName ﾏｰｼﾞ対象のﾌｧｲﾙ名
	 */
//	@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
	private void merge( final String mergeInputName ) {
		// ﾏｰｼﾞする副ﾌｧｲﾙは､ﾃﾝﾌﾟﾚｰﾄ(無題)として上げる(readOnly回避のため)
		final XComponent subDoc = getComponent( mergeInputName, false, true );

		final XDispatchProvider dispatchProvider
//			= (XDispatchProvider)UnoRuntime.queryInterface( XDispatchProvider.class
			= UnoRuntime.queryInterface( XDispatchProvider.class
//				,((XController)UnoRuntime.queryInterface( XController.class
				,(UnoRuntime.queryInterface( XController.class
//					,((XModel)UnoRuntime.queryInterface( XModel.class
					,(UnoRuntime.queryInterface( XModel.class
						,subDoc
					)).getCurrentController()
				)).getFrame()
			);

		final XDispatchHelper xDispatchHelper = soffice.getDispatcher();
		xDispatchHelper.executeDispatch(dispatchProvider, ".uno:TableSelectAll", "", 0, new PropertyValue[0]);

		String title = new File( inputName ).getName() ;
		title = title.substring( 0, title.indexOf( '.' ) );

		final PropertyValue[] moveProps = new PropertyValue[3];
		moveProps[0] = new PropertyValue();
		moveProps[0].Name = "DocName";
		moveProps[0].Value = title;
		moveProps[1] = new PropertyValue();
		moveProps[1].Name = "Index";
		moveProps[1].Value = 32767;
		moveProps[2] = new PropertyValue();
		moveProps[2].Name = "Copy";
		moveProps[2].Value = true;
		xDispatchHelper.executeDispatch(dispatchProvider, ".uno:Move", "", 0, moveProps);

		closeComponent( subDoc );
	}

	/**
	 * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
	 *
	 * このｸﾛｰｽﾞ処理は､処理が正常終了した場合に呼び出しする必要があります｡
	 * 例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * このﾒｿｯﾄﾞは#close(false)と同じです｡
	 *
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 * @see #close(boolean)
	 */
	public void close() throws Throwable {
		close( false );
	}

	/**
	 * Calcｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
	 *
	 * 引数のisErrがtrueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
	 * falseの場合は､ﾌﾟﾛｾｽは､ﾌｧｸﾄﾘｸﾗｽを経由して､ｷｬｯｼｭに戻されます｡
	 * (ﾊﾞｯﾁ処理の場合は､いずれの場合も､ﾌﾟﾛｾｽは強制的に破棄されます)
	 *
	 * 起動から変換､ｸﾛｰｽﾞまでの書く処理で例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * #close(false)は#close()と同じであるため､通常利用することはありません｡
	 *
	 * @og.rev 4.2.4.1 (2008/07/07 ) 終了処理を60回で終わるように修正
	 * @og.rev 4.3.0.0 (2008/07/15 ) ↑は6秒しか待っていなかったので､60秒待つように修正
	 *
	 * @param	isErr	trueの場合､この変換ｵﾌﾞｼﾞｪｸﾄで生成されたﾌﾟﾛｾｽは強制的に破棄されます｡
	 */
//	@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
	public void close( final boolean isErr ) {
		if( xComp != null ) {
			closeComponent( xComp );
		}

		if( soffice != null ) {
			if( isOnline ) {
				if( isErr ) {
					ProcessFactory.remove( soffice );
				}
				else {
					ProcessFactory.release( soffice );
				}
			}
			else {
				soffice.close();
			}
		}

		// ﾏｰｼﾞした場合は､ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除
		// 6.0.0.1 (2014/04/25) These nested if statements could be combined
		if( mergeFile != null && ! ( new File( inputName ) ).delete() ) {
			System.err.println( "ﾃﾝﾎﾟﾗﾘにｺﾋﾟｰしたﾌｧｲﾙを削除できませんでした｡[" + inputName + "]" );
		}
	}

	/**
	 * ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄをｸﾛｰｽﾞします｡
	 *
	 * @param comp ﾄﾞｷｭﾒﾝﾄｺﾝﾎﾟｰﾈﾝﾄ
	 */
//	@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
	private void closeComponent( final XComponent comp ) {
		XCloseable closeable = null;
		for( int i=0;; ++i ) {
			try {
//				closeable = (XCloseable) UnoRuntime.queryInterface( XCloseable.class, comp );
				closeable = UnoRuntime.queryInterface( XCloseable.class, comp );
				closeable.close( true );
				break;
			}
			catch( final CloseVetoException ex ) {
				// 4.2.4.1 (2008/07/07 )
				// 4.3.4.4 (2009/01/01)
				if( i == 600 ) { throw new HybsSystemException( "sofficeﾌﾟﾛｾｽに接続できません｡", ex ); }
				try {
					Thread.sleep( 100 );
				}
				catch( final InterruptedException ex2 ) {
			//		throw new HybsSystemException( ex2 );
				}
			}
		}
	}

	/**
	 * 印刷を行います｡
	 *
	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * @og.rev 4.3.0.0 (2008/07/16) ｽﾌﾟｰﾙが終わるまでwaitし､さらにﾌﾟﾘﾝﾀ発行の状況を監視し､正常終了かどうかを判断
	 * @og.rev 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀｰを指定した場合のｴﾗｰﾊﾝﾄﾞﾘﾝｸﾞを追加
	 * @og.rev 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
	 *
	 * @param	printer	ﾌﾟﾘﾝﾀｰ名
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 */
	public void print( final String printer ) throws Throwable {
		if( printer == null || printer.isEmpty() ) {
			throw new HybsSystemException( "ﾌﾟﾘﾝﾀｰが指定されていません｡" );
		}

	//	if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(1)" ); }
//		@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
//		final XPrintable xprintable = (XPrintable) UnoRuntime.queryInterface( XPrintable.class, xComp );
		final XPrintable xprintable = UnoRuntime.queryInterface( XPrintable.class, xComp );
//		@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
//		final XPrintJobBroadcaster selection = (XPrintJobBroadcaster) UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
		final XPrintJobBroadcaster selection = UnoRuntime.queryInterface(XPrintJobBroadcaster.class, xprintable);
		final MyPrintJobListener listener = new MyPrintJobListener();
		selection.addPrintJobListener( listener );

		final PropertyValue[] tmpProps = new PropertyValue[1];
		tmpProps[0] = new PropertyValue();
		tmpProps[0].Name = "Name";
		// 5.1.2.0 (2010/01/01) CentOS等は､OS_INFOがLinux UNKNOWNとなるため､判定条件を変更
		// OSがLinuxの場合は､ﾌﾟﾘﾝﾀ名称の前後に"<",">"を付加
		tmpProps[0].Value = "LINUX".indexOf( HybsSystem.sys( "OS_INFO" ).toUpperCase( Locale.JAPAN ) ) >= 0 ? "<" + printer + ">" : printer;

		// 4.3.4.4 (2009/01/01)
		try {
			xprintable.setPrinter( tmpProps );
		}
		catch( final IllegalArgumentException ex ) {
			throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
		}

		// 4.3.7.3 (2009/06/22) 存在しないﾌﾟﾘﾝﾀを指定した場合は､PropertyValueに
		// ﾃﾞﾌｫﾙﾄﾌﾟﾘﾝﾀｰが入るため､引数の値と合致しているかで正しく設定されたかを確認
		String curPrinter = null;
		for( final PropertyValue chkProp : xprintable.getPrinter() ) {
			if( "Name".equals( chkProp.Name) ) {
				curPrinter = (String)chkProp.Value;
				break;
			}
		}

//		final PropertyValue[] chkProps = xprintable.getPrinter();
//		for( int i=0; i<chkProps.length; i++ ) {
//			if( "Name".equals( chkProps[i].Name) ) {
//				curPrinter = (String)chkProps[i].Value;
//				break;
//			}
//		}
		if( !(printer.equalsIgnoreCase( curPrinter ) ) ) {
			final String errMsg = "ﾌﾟﾘﾝﾀｰ[" + printer + "]を発行先に指定できませんでした｡" + CR
							+ "存在しないﾌﾟﾘﾝﾀ名が指定されている可能性があります｡";
			throw new HybsSystemException( errMsg );
		}

		// 4.3.0.0 (2008/07/16)
		final PropertyValue[] printProps = new PropertyValue[1];
		printProps[0] = new PropertyValue();
		printProps[0].Name = "Wait";
		printProps[0].Value = true;

		// 4.3.4.4 (2009/01/01)
		try {
			xprintable.print( printProps );
		}
		catch( final IllegalArgumentException ex ) {
			throw new HybsSystemException( "印刷時にｴﾗｰが発生しました｡", ex );
		}

		// 4.3.0.0 (2008/07/16)
		// 6.9.7.0 (2018/05/14) PMD Useless parentheses.
//		if( listener.getStatus() == null
//				|| listener.getStatus() != PrintableState.JOB_COMPLETED && listener.getStatus() != PrintableState.JOB_SPOOLED ) {
		if( listener.isError() ) {
			throw new HybsSystemException ( "Error Occured while spooling print job. Check Spooler-Service!!!");
		}
	}

	/**
	 * ﾌﾟﾘﾝﾀｼﾞｮﾌﾞの状況を監視するﾘｽﾅｰです｡
	 *
	 * @author Hiroki.Nakamura
	 */
	private static final class MyPrintJobListener implements XPrintJobListener {
		private PrintableState status	;

		/**
		 * PrintJobEventのｽﾃｰﾀｽを内部変数にｾｯﾄします｡
		 *
		 * @param	event	PrintJobEventｵﾌﾞｼﾞｪｸﾄ
		 */
		@Override	// XPrintJobListener
		public void printJobEvent( final PrintJobEvent event ) {
			status = event.State;
		}

		/**
		 * EventObjectの処理を実施します｡(ここでは何も行いません｡)
		 *
		 * @param	event	EventObjectｵﾌﾞｼﾞｪｸﾄ
		 */
		@Override	// XPrintJobListener
		public void disposing( final EventObject event ) {
			// 何もありません｡(PMD ｴﾗｰ回避)
		}

//		/**
//		 * PrintableStateｵﾌﾞｼﾞｪｸﾄを返します｡
//		 *
//		 * @og.rev 8.0.3.0 (2021/12/17) Delete
//		 *
//		 * @return	PrintableStateｵﾌﾞｼﾞｪｸﾄ
//		 */
//		public PrintableState getStatus() {
//			return status;
//		}

		/**
		 * PrintableStateｵﾌﾞｼﾞｪｸﾄの状態を返します｡
		 *
		 * statusが nullか､COMPLETEDでなく､SPOOLEDでない場合にｴﾗｰと判断します｡
		 *
		 * @return	ｴﾗｰの場合､true
		 */
		public boolean isError() {
			return status == null || status != PrintableState.JOB_COMPLETED && status != PrintableState.JOB_SPOOLED ;
		}
	}

	/**
	 * Calc(ods)出力を行います｡
	 *
	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
	 *
	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 */
//	public void ods( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "ods" ) );
//		saveDoc( outputName, getFilterName( inputName, "ods" ) );
//	}

//	/**
//	 * Excel(xls)出力を行います｡
//	 *
//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
//	 *
//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
//	 *
//	 * @param	outputName	出力ﾌｧｲﾙ名
//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
//	 */
//	public void xls( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "xls" ) );
//		saveDoc( outputName, getFilterName( inputName, "xls" ) );
//	}

//	/**
//	 * Writer(ods)出力を行います｡
//	 *
//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
//	 *
//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
//	 *
//	 * @param	outputName	出力ﾌｧｲﾙ名
//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
//	 */
//	public void odt( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "odt" ) );
//		saveDoc( outputName, getFilterName( inputName, "odt" ) );
//	}

//	/**
//	 * Word(doc)出力を行います｡
//	 *
//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
//	 *
//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
//	 *
//	 * @param	outputName	出力ﾌｧｲﾙ名
//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
//	 */
//	public void doc( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "doc" ) );
//		saveDoc( outputName, getFilterName( inputName, "doc" ) );
//	}

//	/**
//	 * Impress(odp)出力を行います｡
//	 *
//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
//	 *
//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
//	 *
//	 * @param	outputName	出力ﾌｧｲﾙ名
//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
//	 */
//	public void odp( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "odp" ) );
//		saveDoc( outputName, getFilterName( inputName, "odp" ) );
//	}

//	/**
//	 * PowerPoint(ppt)出力を行います｡
//	 *
//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
//	 *
//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
//	 *
//	 * @param	outputName	出力ﾌｧｲﾙ名
//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
//	 */
//	public void ppt( final String outputName ) throws Throwable {
//	//	saveDoc( outputName, getFilterName( getSuffix( inputName ), "ppt" ) );
//		saveDoc( outputName, getFilterName( inputName, "ppt" ) );
//	}

	/**
	 * PDF出力を行います｡
	 *
	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
	 *
	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 * @param	pdfPasswd	PDFﾊﾟｽﾜｰﾄﾞ
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 */
	public void pdf( final String outputName, final String pdfPasswd ) throws Throwable {
		if( !checkOutput( outputName ) ){ return; }			// 8.1.0.3 (2022/01/21)

	//	savePdf( outputName, getFilterName( getSuffix( inputName ), "pdf" ), pdfPasswd );
		savePdf( outputName, getFilterName( inputName, "pdf" ), pdfPasswd );
	}

	//	/**
	//	 * 【保留】Excel2007(xlsx)出力を行います｡
	//	 *
	//	 * 入力形式で未対応の場合(形式は入力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
	//	 *
	//	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	//	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	//	 *
	//	 * @og.rev 8.0.3.0 (2021/12/17) ods→xlsx変換時のｼｰﾄ毎の行数
	//	 *
	//	 * @param	outputName	出力ﾌｧｲﾙ名
	//	 * @param	sheetRows	ｼｰﾄ毎の行数List
	//	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	//	 */
	//	public void xlsx( final String outputName,final List<Integer> sheetRows ) throws Throwable {
	//		saveDoc( outputName, getFilterName( inputName, "xlsx" ) );
	//
	//		// 余分な行やｶﾗﾑを除去(ただし、ものすごく遅い)
	//		final File outputFile = new File( outputName );
	//		final ExcelModel excel = new ExcelModel( outputFile , true );
	//		excel.activeWorkbook( sheetRows );
	//		excel.saveFile( outputFile );
	//	}

	/**
	 * 出力ﾌｧｲﾙから出力形式を自動判別し､変換を行います｡
	 *
	 * 入出力形式で未対応の場合(形式は入出力ﾌｧｲﾙの拡張子で判別)､例外が発行されます｡
	 *
	 * 正常に処理が終了した場合は､#close()を発行し､終了処理を行って下さい｡
	 * また､例外が発生した場合は､#close(true)を発行し､終了処理を行って下さい｡
	 *
	 * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 * @throws Throwable 何らかのｴﾗｰが発生した場合｡
	 */
	public void auto( final String outputName ) throws Throwable {
		if( !checkOutput( outputName ) ){ return; }			// 8.1.0.3 (2022/01/21)

		final String outSuffix = getSuffix( outputName );
		if( "pdf".equalsIgnoreCase( outSuffix ) ) {
//			savePdf( outputName, getFilterName( getSuffix( inputName ), outSuffix ), null );
			savePdf( outputName, getFilterName( inputName, outSuffix ), null );
		}
		else {
//			saveDoc( outputName, getFilterName( getSuffix( inputName ), outSuffix ) );
			saveDoc( outputName, getFilterName( inputName, outSuffix ) );
		}
	}

	/**
	 * ﾌｨﾙﾀｰ名を指定して､各種ﾌｧｲﾙ形式に出力を行います｡
	 *
	 * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 * @param	filter		ﾌｨﾙﾀｰ名
	 */
	private void saveDoc( final String outputName, final String filter ) {
//		if( !checkOutput( outputName ) ){ return; }

		final PropertyValue[] storeProps = new PropertyValue[1];
		storeProps[0] = new PropertyValue();
		storeProps[0].Name = "FilterName";
		storeProps[0].Value = filter;

		final String url = "file:///" + outputName.replace( '\\', '/' );
	//	if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(2)" ); }
//		@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
//		final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
		final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
		try {
			xstorable.storeAsURL( url, storeProps );
		}
		catch( final Throwable th ) {
			throw new HybsSystemException( "ﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
		}
	}

	/**
	 * ﾌｨﾙﾀｰを指定してPDF出力を行います｡
	 *
	 * @og.rev 8.1.0.3 (2022/01/21) checkOutputﾒｿｯﾄﾞは呼出元で判定する。
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 * @param	filter		ﾌｨﾙﾀｰ名
	 * @param	pdfPasswd	PDFﾊﾟｽﾜｰﾄﾞ
	 */
	private void savePdf( final String outputName, final String filter, final String pdfPasswd ) {
//		if( !checkOutput( outputName ) ){ return; }

		final PropertyValue[] storeProps;
		if( pdfPasswd == null || pdfPasswd.isEmpty() ) {
			storeProps = new PropertyValue[1];
			storeProps[0] = new PropertyValue();
			storeProps[0].Name = "FilterName";
			storeProps[0].Value = filter;
		}
		// 帳票要求ﾃｰﾌﾞﾙでPDFﾊﾟｽﾜｰﾄﾞが設定されている場合
		else {
			final PropertyValue[] filterProps = new PropertyValue[2];
			filterProps[0] = new PropertyValue();
			filterProps[0].Name = "EncryptFile";
			filterProps[0].Value = true;
			filterProps[1] = new PropertyValue();
			filterProps[1].Name = "DocumentOpenPassword";
			filterProps[1].Value = pdfPasswd;

			storeProps = new PropertyValue[2];
			storeProps[0] = new PropertyValue();
			storeProps[0].Name = "FilterName";
			storeProps[0].Value = "calc_pdf_Export";
			storeProps[1] = new PropertyValue();
			storeProps[1].Name = "FilterData";
			storeProps[1].Value = filterProps;
		}

		final String url = "file:///" + outputName.replace( '\\', '/' );
	//	if( xComp == null ) { throw new HybsSystemException( "初めに､#open()を実行して下さい(3)" ); }
//		@SuppressWarnings("cast")	// OpenOffice 3.2 での冗長なｷｬｽﾄ警告の抑止｡ｷｬｽﾄをはずすと､旧3.1 では､ｴﾗｰになる｡
//		final XStorable xstorable = (XStorable) UnoRuntime.queryInterface( XStorable.class, xComp );
		final XStorable xstorable = UnoRuntime.queryInterface( XStorable.class, xComp );
		try {
			xstorable.storeToURL( url, storeProps );
		}
		catch( final Throwable th ) {
			final String err = "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]"
							+ " URL=" + url + " , storeProps=" + storeProps + " , xComp=" + xComp ;

//			throw new HybsSystemException( "PDFﾌｧｲﾙへの変換時にｴﾗｰが発生しました｡[filter=" + filter + "]", th );
			throw new HybsSystemException( err, th );
		}
	}

	/**
	 * 出力ﾌｧｲﾙのﾁｪｯｸを行います｡
	 *
	 * @og.rev 8.1.0.3 (2022/01/21) ﾌｧｲﾙの拡張子が同じ場合は、copyで対応する。
	 *
	 * @param	outputName	出力ﾌｧｲﾙ名
	 *
	 * @return	処理対象かどうか(入力ﾌｧｲﾙと出力ﾌｧｲﾙが同じ場合は､falseが返ります)
	 */
	private boolean checkOutput( final String outputName ) {
		if( outputName == null || outputName.isEmpty() ) {
			throw new HybsSystemException( "出力ﾌｧｲﾙが指定されていません｡" );
		}

		try {
			// 8.1.0.3 (2022/01/21) 出力ﾌｧｲﾙがあれば、無条件削除
			final Path outPath = Paths.get( outputName );
			if( Files.exists( outPath ) ) { Files.delete( outPath ); }
//			if( Files.exists( outPath ) && !Files.deleteIfExists( outPath ) ) {
//				throw new HybsSystemException( "出力先の既存ﾌｧｲﾙが削除できません｡[file=" + outputName + "]" );
//			}

			// 8.1.0.3 (2022/01/21) 拡張子が同じなら、copyする。
			if( getSuffix( inputName ).equals( getSuffix( outputName ) ) ) {
				final Path inPath = Paths.get( inputName );
				Files.copy( inPath , outPath , StandardCopyOption.REPLACE_EXISTING );
				return false;
			}
		}
//		catch( final IOException ex ) {		// 意味不明なｴﾗｰが出る。
		catch( final Throwable ex ) {
			throw new HybsSystemException( "ﾌｧｲﾙｺﾋﾟｰが失敗しました｡[in=" + inputName + "],out=" + outputName + "]" ,ex );
		}

		return true;

//		if( outFile.exists() ) {
//			if( inFile.getAbsoluteFile().equals( outFile.getAbsoluteFile() ) ) {
//				// 入力と出力が同じﾌｧｲﾙの場合な何もしない
//				return false;
//			}
//			else if( !outFile.delete() ) {
//				throw new HybsSystemException( "出力先の既存ﾌｧｲﾙが削除できません｡[file=" + outputName + "]" );
//			}
//		}
//		return true;
	}

	/**
	 * 入出力の形式(拡張子)からﾌｨﾙﾀｰ名を取得します｡
	 *
	 * 入力ﾌｧｲﾙ名からｻﾌｨｯｸｽを取り出して､FILTER_MAP からﾌｨﾙﾀｰ名を取り出します｡
	 *
	 * @og.rev 8.0.1.0 (2021/10/29) ﾒｯｾｰｼﾞ修正
	 *
//	 * @param	inSuffix	入力拡張子
	 * @param	inputName	入力ﾌｧｲﾙ名
	 * @param	outSuffix	出力拡張子
	 *
	 * @return	ﾌｨﾙﾀｰ名
	 */
//	private static String getFilterName( final String inSuffix, final String outSuffix ) {
	private static String getFilterName( final String inputName, final String outSuffix ) {
		final String inSuffix = getSuffix( inputName );

		final String filterName = FILTER_MAP.get( inSuffix + "_" + outSuffix );
		if( filterName == null ) {
			final String errMsg = "入力ﾌｧｲﾙ=[" + inputName + "] , 出力形式=[" + outSuffix + "]" + CR
							+ "入力形式､出力形式は､以下の対応表に基づき､設定して下さい｡" + CR
							+ "入力[Calc(ods)   ,Excel(xls)     ] ⇒ 出力[Calc(ods)   ,Excel(xls,xlsx)     ,PDF]" + CR
							+ "入力[Writer(odt) ,Word(doc)      ] ⇒ 出力[Writer(odt) ,Word(doc,docx)      ,PDF]" + CR
							+ "入力[Impress(odp),PowerPoint(ppt)] ⇒ 出力[Impress(odp),PowerPoint(ppt,pptx),PDF]" + CR
							+ "xlsx,docx,pptx は､MS 2007形式の為､LibreOffice のみ利用できます｡" + CR ;
			throw new HybsSystemException( errMsg );
		}
		return filterName;
	}

	/**
	 * ﾌｧｲﾙ名から拡張子(小文字)を求めます｡
	 *
	 * @param	fileName	ﾌｧｲﾙ名
	 *
	 * @return	拡張子(小文字)…存在しない場合は、空文字列
	 */
	private static String getSuffix( final String fileName ) {
//		String suffix = null;
		String suffix = "";
		if( fileName != null ) {
			final int sufIdx = fileName.lastIndexOf( '.' );
			if( sufIdx >= 0 ) {
				suffix = fileName.substring( sufIdx + 1 ).toLowerCase( Locale.JAPAN );
			}
		}
		return suffix;
	}

//	/**
//	 * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
//	 *
//	 * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
//	 *
//	 * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
//	 *
//	 * @param	inputFile	入力ﾌｧｲﾙ名
//	 * @param	outputFile	出力ﾌｧｲﾙ名
//	 * @see #convert(String[], String, boolean)
//	 */
//	public static final void convert( final String inputFile, final String outputFile ) {
////		convert( StringUtil.csv2Array( inputFile ), outputFile );
//		convert( StringUtil.csv2Array( inputFile ), outputFile, true );	// 8.0.3.0 (2021/12/17)
//	}

//	/**
//	 * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
//	 *
//	 * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
//	 *
//	 * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
//	 *
//	 * @param	inputFile	入力ﾌｧｲﾙ名配列
//	 * @param	outputFile	出力ﾌｧｲﾙ名
//	 * @see #convert(String[], String, boolean)
//	 */
//	public static final void convert( final String[] inputFile, final String outputFile ) {
//		convert( inputFile, outputFile, true );
//	}

	/**
	 * ﾄﾞｷｭﾒﾝﾄの変換を行うための簡易ﾒｿｯﾄﾞです｡
	 *
	 * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
	 *
	 * isOnlineがtrueに指定された場合､soffice.binのﾌﾟﾛｾｽをﾌｧｸﾄﾘｰｸﾗｽ経由で生成し､
	 * ｷｬｯｼｭします｡
	 * 但し､ｼｽﾃﾑﾘｿｰｽが読み込まれないような､ﾊﾞｯﾁﾌｧｲﾙから起動した場合は､この方法は
	 * 利用できないため､isOnlineをfalseに指定する必要があります｡
	 *
	 * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
	 *
	 * @param	inputFile	入力ﾌｧｲﾙ名配列
	 * @param	outputFile	出力ﾌｧｲﾙ名
	 * @param	isOnline	ｵﾝﾗｲﾝ(Web環境での使用)かどうか
	 */
	public static final void convert( final String inputFile[], final String outputFile, final boolean isOnline ) {
		final DocConverter_OOO dc = new DocConverter_OOO( inputFile, isOnline );
		try {
			dc.open();
			dc.auto( outputFile );
			dc.close();
		}
		catch( final Throwable th ) {
			dc.close( true );
			throw new HybsSystemException( th );
		}
	}

	/**
	 * ﾄﾞｷｭﾒﾝﾄの変換を行います｡
	 *
	 * 変換方法は､出力ﾌｧｲﾙの拡張子により自動的に決定されます｡
	 *
	 * @og.rev 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
	 * @og.rev 6.3.9.1 (2015/11/27) A method/constructor shouldnt explicitly throw java.lang.Exception(PMD)｡
	 * @og.rev 8.0.3.0 (2021/12/17) ﾌｧｲﾙ連結の簡易ﾒｿｯﾄﾞは、使用しません。
	 *
	 * @param	args	ｺﾏﾝﾄﾞ引数配列
	 */
	public static void main( final String[] args ) {
		if( args.length < 2 ) {
			System.out.println( "usage : OdsConverter [inputFile] [outputFile]" );
			return;
		}

		DocConverter_OOO.convert( new String[] {args[0]}, args[1], false );

//		final File input  = new File( args[0] );
//		final File output = new File( args[1] );
//
//		// 4.3.1.1 (2008/08/23) mkdirs の戻り値判定
//		if( outPath.mkdirs() ) {
//			System.err.println( args[1] + " の ﾃﾞｨﾚｸﾄﾘ作成に失敗しました｡" );
//		}
//
//		final String absPath = output.getAbsolutePath() + FS ;		// 8.0.3.0 (2021/12/17)
//		if( input.isDirectory() ) {
//			final File[] inputFiles = input.listFiles();
//			// 6.3.9.0 (2015/11/06) null になっている可能性があるﾒｿｯﾄﾞの戻り値を利用している(findbugs)
//			if( inputFiles != null ) {
//				for( final File file : inputFiles ) {
//					final String inputFile = file.getAbsolutePath();
////					final String outputFile = output.getAbsolutePath() + File.separator + file.getName().replace( ".xls", ".ods" );
//					final String outputFile = absPath + file.getName().replace( ".xls", ".ods" );
//					convert( StringUtil.csv2Array( inputFile ), outputFile, false );
//				}
//			}
//		}
//		else {
//			final String inputFile = input.getAbsolutePath();
////			final String outputFile = output.getAbsolutePath() + File.separator + input.getName().replace( ".xls", ".ods" );
//			final String outputFile = absPath + input.getName().replace( ".xls", ".ods" );
//			convert( StringUtil.csv2Array( inputFile ), outputFile, false );
//		}
	}
}
