/*
 * 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.fukurou.model;

import java.io.File;
import java.util.Locale;
import org.opengion.fukurou.util.StringUtil;

import static org.opengion.fukurou.system.HybsConst.CR;

/**
 * ﾌｧｲﾙ操作のﾌｧｸﾄﾘｰｸﾗｽ
 *
 * ﾃﾞﾌｫﾙﾄはﾛｰｶﾙのﾌｧｲﾙ操作を行うFileOperationｸﾗｽを生成します。
 * 利用ﾌﾟﾗｸﾞｲﾝ、ﾊﾞｹｯﾄ、ﾊﾟｽ等を指定する事でｸﾗｳﾄﾞのｵﾌﾞｼﾞｪｸﾄｽﾄﾚｰｼﾞに対応した
 * ｸﾗｽを生成します。
 * ﾛｰｶﾙのﾌｧｲﾙを扱いたい場合は、pluginかbucketに空文字列かLOCALを指定してください。
 *
 * @og.rev 5.10.8.0 (2019/02/01) 新規作成
 * @og.rev 5.10.9.0 (2019/03/01) 変更対応
 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
 * @author oota
 * @since JDK7.0
 */
public final class FileOperationFactory {	// 7.2.9.4 (2020/11/20) PMD:A class which only has private constructors should be final
//	private static final int BUFFER_MIDDLE = 200;

	private static final String CLOUD_PLUGIN = "org.opengion.cloud.FileOperation_" ;

	/**
	 * ｵﾌﾞｼﾞｪｸﾄを作らせない為の、private ｺﾝｽﾄﾗｸﾀ。
	 *
	 * @og.rev 7.2.9.4 (2020/11/20) ｵﾌﾞｼﾞｪｸﾄを作らせない為の、private ｺﾝｽﾄﾗｸﾀ
	 */
	private FileOperationFactory() {}

	/**
	 * ｲﾝｽﾀﾝｽ生成(ﾛｰｶﾙFile)。
	 *
	 * 引数を元に、ﾌｧｲﾙ操作ｲﾝｽﾀﾝｽを生成します。
	 * ﾛｰｶﾙのﾌｧｲﾙ操作を行うFileOperationｸﾗｽを返します。
	 *
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @param path ﾌｧｲﾙﾊﾟｽ
	 * @return ﾌｧｲﾙ操作ｲﾝｽﾀﾝｽ
	 */
	public static FileOperation newStorageOperation(final String path) {
		return new FileOperation( path );
	}

	/**
	 * ｲﾝｽﾀﾝｽ生成(ｸﾗｳﾄﾞFile)。
	 *
	 * 引数を元に、ﾌｧｲﾙ操作ｸﾗｽを生成します。
	 * new File( dir,fileName ).getPath() で求めたﾊﾟｽで、生成します。
	 * ﾌﾟﾗｸﾞｲﾝとﾊﾞｹｯﾄを指定する事で、plugin.cloud内のｸﾗｳﾄﾞ用のｸﾗｽを返します。
	 *
	 * ﾃﾞｨﾚｸﾄﾘとﾌｧｲﾙ名からﾊﾟｽを生成します。
	 *
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @param plugin 利用ﾌﾟﾗｸﾞｲﾝ
	 * @param bucket ﾊﾞｹｯﾄ名
	 * @param dir ﾃﾞｨﾚｸﾄﾘ
	 * @param fileName ﾌｧｲﾙ名
	 * @return ﾌｧｲﾙ操作ｲﾝｽﾀﾝｽ
	 */
	public static FileOperation newStorageOperation(final String plugin, final String bucket, final String dir, final String fileName) {
		return newStorageOperation(plugin, bucket, new File(dir,fileName).getPath());
	}

	/**
	 * ｲﾝｽﾀﾝｽ生成(ｸﾗｳﾄﾞFile/ﾛｰｶﾙFile)。
	 *
	 * 引数を元に、ﾌｧｲﾙ操作ｸﾗｽを生成します。
	 * ﾌﾟﾗｸﾞｲﾝとﾊﾞｹｯﾄを指定する事で、plugin.cloud内のｸﾗｳﾄﾞ用のｸﾗｽを返します。
	 * pluginかbucketに空文字列かLOCALを指定した場合は標準のFileOperation(ﾛｰｶﾙﾌｧｲﾙ用)を返します。
	 *
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @param plugin 利用ﾌﾟﾗｸﾞｲﾝ
	 * @param bucket ﾊﾞｹｯﾄ名
	 * @param path ﾌｧｲﾙﾊﾟｽ
	 * @return ﾌｧｲﾙ操作ｲﾝｽﾀﾝｽ
	 */
	public static FileOperation newStorageOperation(final String plugin, final String bucket, final String path) {
		// bucket の null 判定も条件に加えます。
//		if( StringUtil.isNull(plugin) || "LOCAL".equalsIgnoreCase(plugin)
//			|| StringUtil.isNull(bucket) || "LOCAL".equalsIgnoreCase(bucket) ) {		// 8.0.1.0 (2021/10/29)
//			return new FileOperation( path );		// ﾛｰｶﾙFile
//		}

		if( StringUtil.isNull( plugin,bucket )
				|| FileOperation.LOCAL.equalsIgnoreCase(plugin)
				|| FileOperation.LOCAL.equalsIgnoreCase(bucket) ) {
			return new FileOperation( path );		// ﾛｰｶﾙFile
		}

		try {
			final Object[] args = new Object[] { bucket, path };

			final String cloudTarget = plugin.toUpperCase( Locale.JAPAN );	// 先に null 判定済み
			return (FileOperation)Class.forName( CLOUD_PLUGIN + cloudTarget )
						.getConstructor(String.class, String.class)
						.newInstance( args );
		}
		catch ( final Throwable th ) {
			final String errMsg = "FileOperation 生成で、失敗しました。" + CR
								+ " plugin=" + plugin + " , bucket=" + bucket + CR
								+ " path=" + path + CR ;

			throw new RuntimeException( errMsg,th );
		}
	}

	/**
	 * 引数を元に、ﾌｧｲﾙ操作ｸﾗｽのｱﾄﾞﾚｽを解決した新しいｵﾌﾞｼﾞｪｸﾄを返します。
	 *
	 * 与えたfileｵﾌﾞｼﾞｪｸﾄがFileOperationだった場合は、ﾌﾟﾗｸﾞｲﾝとﾊﾞｹｯﾄを取得して
	 * それに基づいたFileOperationを返します。
	 * 標準のFileの場合は、defaultのFileOperationを返します。
	 * 元がnullの場合はnullを返します。
	 * new File( dir,fileName ).getPath() で求めたﾊﾟｽで、生成します。
	 * ※ ﾌｧｲﾙのｺﾋﾟｰは行いません。
	 *
	 * @og.rev 7.2.9.4 (2020/11/20) PMD:Avoid declaring a variable if it is unreferenced before a possible exit point.
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @param file ｺﾋﾟｰ元
	 * @param dir 親ﾊﾟｽ(ﾃﾞｨﾚｸﾄﾘ)
	 * @param fileName 子ﾊﾟｽ
	 * @return 設定をｺﾋﾟｰしたのFileOperation
	 */
	public static FileOperation resolveFile(final File file, final String dir, final String fileName) {
		return resolveFile( file, new File(dir,fileName).getPath() );
	}

	/**
	 * 引数を元に、ﾌｧｲﾙ操作ｸﾗｽのｱﾄﾞﾚｽを解決した新しいｵﾌﾞｼﾞｪｸﾄを返します。
	 *
	 * 与えたfileｵﾌﾞｼﾞｪｸﾄがFileOperationだった場合は、ﾌﾟﾗｸﾞｲﾝとﾊﾞｹｯﾄを取得して
	 * それに基づいた新しいFileOperationを返します。
	 * 標準のFileの場合は、defaultのFileOperationを返します。
	 * 元がnullの場合はnullを返します。
	 * ※ ﾌｧｲﾙのｺﾋﾟｰは行いません。
	 *
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @param file ｺﾋﾟｰ元
	 * @param path ﾊﾟｽ
	 * @return 設定をｺﾋﾟｰしたFileOperation
	 */
	public static FileOperation resolveFile(final File file, final String path) {
		if( file == null) { return null; }		// 元がnullの場合はnullを返します。

		// FileOperation型の場合にﾌﾟﾗｸﾞｲﾝを判定する
		if( file instanceof FileOperation ) {
			final String plugin = ((FileOperation)file).getPlugin();
			final String bucket = ((FileOperation)file).getBucket();

			return newStorageOperation( plugin, bucket, path );		// ｸﾗｳﾄﾞFile/(ﾛｰｶﾙFile もありうる)
		}
		else {
			return newStorageOperation( path );						// ﾛｰｶﾙFile
		}
	}
}
