/*
 *
 * 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.dbunitng.listeners.internal;

import static org.dbunitng.annotations.DatabaseOperationType.*;

import java.sql.SQLException;

import org.apache.commons.lang.StringUtils;
import org.dbunit.IDatabaseTester;
import org.dbunit.database.DatabaseConfig;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.datatype.IDataTypeFactory;
import org.dbunit.operation.DatabaseOperation;
import org.dbunitng.annotations.DatabaseOperationType;
import org.dbunitng.exception.DbUnitNGRuntimeException;
import org.testng.log4testng.Logger;

/**
 * データベースへの操作を表す。
 * 
 * @author jyukutyo
 * 
 */
public class DbUnitNGDatabaseOperation {

	/** This class' log4testng Logger. */
	private static final Logger LOGGER =
		Logger.getLogger(DbUnitNGDatabaseOperation.class);

	/** DbUnitのTester */
	private IDatabaseTester tester;

	/** DbUnitのDataTypeFactory */
	private IDataTypeFactory factory;

	protected void setSchema(DbUnitNGConfig config) {
		String schema = config.getSchema();
		if (StringUtils.isNotBlank(schema)) {
			tester.setSchema(schema.toUpperCase());
		}
	}

	/**
	 * コンストラクタ.
	 * 
	 * @param tester
	 *            テスター
	 * @param config
	 *            接続情報
	 */
	public DbUnitNGDatabaseOperation(IDatabaseTester tester,
			DbUnitNGConfig config) {
		this.tester = tester;
		setSchema(config);
		factory = config.getFactory();
	}

	/**
	 * データベースへの操作を実行する.
	 * 
	 * @param type
	 *            データベース操作タイプ
	 * @param dataSet
	 *            DbUnitのデータセット
	 */
	public void execute(DatabaseOperationType type, IDataSet dataSet) {
		if (NONE == type) {
			return;
		}

		IDatabaseConnection connection = null;
		try {
			connection = tester.getConnection();
			DatabaseConfig config = connection.getConfig();

			if (factory != null) {
				config.setProperty(
					DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
					factory);
			}
			LOGGER.debug("Database Operation is " + type + ".");

			DatabaseOperation operation;
			if (CLEAN_INSERT == type) {
				operation = DatabaseOperation.CLEAN_INSERT;
			} else if (INSERT == type) {
				operation = DatabaseOperation.INSERT;
			} else if (UPDATE == type) {
				operation = DatabaseOperation.UPDATE;
			} else if (REFRESH == type) {
				operation = DatabaseOperation.REFRESH;
			} else if (DELETE == type) {
				operation = DatabaseOperation.DELETE;
			} else if (DELETE_ALL == type) {
				operation = DatabaseOperation.DELETE_ALL;
			} else if (TRUNCATE_TABLE == type) {
				operation = DatabaseOperation.TRUNCATE_TABLE;
			} else {
				throw new DbUnitNGRuntimeException(
					"DatabaseOperationType is not undifined. " + type);
			}
			operation.execute(connection, dataSet);

		} catch (Exception e) {
			throw new DbUnitNGRuntimeException(
				"DatabaseOperation can not be executed.",
				e);
		} finally {
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException e) {
					// empty
				}
			}
		}
	}
}
