/*
 * Copyright 2006 Takahiro Nakamura.
 *
 * 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 woolpack.sql.tx;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import woolpack.fn.Fn;

/**
 * RDBトランザクション制御のユーティリティです。
 * 型推論で表記を簡略するためのスタティックメソッドを含みます。
 * 
 * @author nakamura
 *
 */
public class SqlTxUtils {
	private SqlTxUtils() {
	}

	/**
	 * RDBとのトランザクションのブロックを処理する関数を生成します。
	 * {@link TxBuilder#getTxDataSource()}と組み合わせて使用します。
	 * {@link Fn#exec(Object)}は{@link DataSource#getConnection()}を
	 * 実行して処理を委譲先に委譲します。
	 * 委譲先から例外を受け取った場合は{@link Connection#rollback()}を呼び出します。
	 * 最後に{@link Connection#close()}を呼び出します。
	 * このクラスのメソッドは最初に発生した例外を再スローするため、メソッド内で続けて発生した例外の情報は失われます。
	 * <br/>適用しているデザインパターン：Before After。
	 * @param <C>
	 * @param <R>
	 * @param dataSource データソース。
	 * @param fn 委譲先。
	 * @return 関数。
	 */
	public static <C, R> Fn<C, R, Exception> tx(
			final DataSource dataSource,
			final Fn<? super C, ? extends R, Exception> fn) {
		return new TxFn<C, R>(dataSource, fn);
	}

	/**
	 * {@link DataSource}から{@link Connection}を取得して
	 * {@link Connection#rollback()}を呼び出す関数を生成します。
	 * {@link woolpack.sql.tx.TxBuilder#getTmpDataSource()}と組み合わせて使用します。
	 * @param <C>
	 * @param <R>
	 * @param dataSource データソース。
	 * @return 関数。
	 */
	public static <C, R> Fn<C, R, SQLException> rollback(final DataSource dataSource) {
		return new RollbackFn<C, R>(dataSource);
	}

	/**
	 * {@link DataSource}から{@link Connection}を取得して
	 * {@link Connection#commit()}を呼び出す関数を生成します。
	 * {@link woolpack.sql.tx.TxBuilder#getTmpDataSource()}と組み合わせて使用します。
	 * @param <C>
	 * @param <R>
	 * @param dataSource データソース。
	 * @return 関数。
	 */
	public static <C, R> Fn<C, R, SQLException> commit(final DataSource dataSource) {
		return new CommitFn<C, R>(dataSource);
	}
}
