/*
 *  Copyright 2004 Clinton Begin
 *
 *  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 com.ibatis.sqlmap.client;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * This interface declares methods for demarcating SQL Map transactions.
 *
 * @see SqlMapSession 
 * @see SqlMapClient
 */
public interface SqlMapTransactionManager {

  /**
   * Demarcates the beginning of a transaction scope.  Transactions must be properly
   * committed or rolled back to be effective.  Use the following pattern when working
   * with transactions:
   * <pre>
   * try {
   *   sqlMap.startTransaction();
   *   // do work
   *   sqlMap.commitTransaction();
   * } finally {
   *   sqlMap.endTransaction();
   * }
   * </pre>
   * <p/>
   * Always call endTransaction() once startTransaction() has been called.
   *
   * @throws java.sql.SQLException If an error occurs while starting the transaction, or
   *                               the transaction could not be started.
   */
  public void startTransaction() throws SQLException;


  /**
   * Demarcates the beginning of a transaction scope using the specified transaction
   * isolation.  Transactions must be properly committed or rolled back to be effective.
   * Use the following pattern when working with transactions:
   * <pre>
   * try {
   *   sqlMap.startTransaction(Connection.TRANSACTION_REPEATABLE_READ);
   *   // do work
   *   sqlMap.commitTransaction();
   * } finally {
   *   sqlMap.endTransaction();
   * }
   * </pre>
   * <p/>
   * Always call endTransaction() once startTransaction() has been called.
   *
   * @throws java.sql.SQLException If an error occurs while starting the transaction, or
   *                               the transaction could not be started.
   */
  public void startTransaction(int transactionIsolation) throws SQLException;

  /**
   * Commits the currently started transaction.
   *
   * @throws SQLException If an error occurs while committing the transaction, or
   *                      the transaction could not be committed.
   */
  public void commitTransaction() throws SQLException;

  /**
   * Ends a transaction and rolls back if necessary.  If the transaction has
   * been started, but not committed, it will be rolled back upon calling
   * endTransaction().
   *
   * @throws SQLException If an error occurs during rollback or the transaction could
   *                      not be ended.
   */
  public void endTransaction() throws SQLException;

  /**
   * Allows the developer to easily use an externally supplied connection
   * when executing statements.
   * <p/>
   * <b>Important:</b> Using a user supplied connection basically sidesteps the transaction manager,
   * so you are responsible for appropriately.  Here's a (very) simple example (throws SQLException):
   * <pre>
   * try {
   *   Connection connection = dataSource.getConnection();
   *   sqlMap.setUserConnection(connection);
   *   // do work
   *   connection.commit();
   * } catch (SQLException e) {
   *     try {
   *       if (connection != null) commit.rollback();
   *     } catch (SQLException ignored) {
   *       // generally ignored
   *     }
   *     throw e;  // rethrow the exception
   * } finally {
   *   try {
   *     if (connection != null) connection.close();
   *   } catch (SQLException ignored) {
   *     // generally ignored
   *   }
   * }
   * </pre>
   *
   * @param connnection
   * @throws SQLException
   */
  public void setUserConnection(Connection connnection) throws SQLException;

  /**
   * Returns the current user supplied connection as set by setUserConnection().
   * <p/>
   * TODO : DEPRECATED
   *
   * @return The current user supplied connection.
   * @throws SQLException
   * @deprecated Use getCurrentConnection() instead.
   */
  public Connection getUserConnection() throws SQLException;

  /**
   * Returns the current connection in use.  If no connection exists null will
   * be returned. There may be no connection if no transaction has been started,
   * and if no user provided connection has been set.
   *
   * @return The current connection or null.
   * @throws SQLException
   */
  public Connection getCurrentConnection() throws SQLException;

  /**
   * Returns the DataSource instance currently being used by the SqlMapSession.
   *
   * @return The DataSource instance currently being used by the SqlMapSession.
   */
  public DataSource getDataSource();


}
