package data_objects;

import static data_objects.DataObjects.DATA_OBJECTS_MODULE_NAME;

import java.sql.SQLException;

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.builtin.IRubyObject;

import data_objects.drivers.DriverDefinition;

/**
 * Transaction Class
 *
 * @author alexbcoles
 * @author mkristian
 */
@SuppressWarnings("serial")
@JRubyClass(name = "Transaction")
public class Transaction extends DORubyObject {

    public final static String RUBY_CLASS_NAME = "Transaction";

    private final static ObjectAllocator TRANSACTION_ALLOCATOR = new ObjectAllocator() {

        public IRubyObject allocate(Ruby runtime, RubyClass klass) {
            return new Transaction(runtime, klass);
        }
    };

    public static RubyClass createTransactionClass(final Ruby runtime,
            DriverDefinition driver) {
        RubyModule doModule = runtime.getModule(DATA_OBJECTS_MODULE_NAME);
        RubyClass superClass = doModule.getClass(RUBY_CLASS_NAME);
        RubyModule driverModule = (RubyModule) doModule.getConstant(driver
                .getModuleName());
        RubyClass transactionClass = runtime.defineClassUnder("Transaction",
                superClass, TRANSACTION_ALLOCATOR, driverModule);
        transactionClass.defineAnnotatedMethods(Transaction.class);
        setDriverDefinition(transactionClass, runtime, driver);
        return transactionClass;
    }

    private Transaction(Ruby runtime, RubyClass klass) {
        super(runtime, klass);
    }

    // -------------------------------------------------- DATAOBJECTS PUBLIC API

    // inherit initialize

    /**
     * Begins the transaction
     *
     * @return
     */
    @JRubyMethod
    public IRubyObject begin() {
        java.sql.Connection conn = getConnection();
        try {
            conn.setAutoCommit(false);
        } catch (SQLException sqle) {
            throw driver.newDriverError(getRuntime(), sqle);
        }
        return getRuntime().getTrue();
    }

    /**
     * Commits the transaction
     *
     * @return
     */
    @JRubyMethod
    public IRubyObject commit() {
        java.sql.Connection conn = getConnection();
        try {
            conn.commit();
        } catch (SQLException sqle) {
            throw driver.newDriverError(getRuntime(), sqle);
        } finally {
            try {
                conn.setAutoCommit(true);
            } catch (SQLException sqle) {
                throw driver.newDriverError(getRuntime(), sqle);
            }
        }
        return getRuntime().getTrue();
    }

    /**
     * Rollsback the transaction
     *
     * @return
     */
    @JRubyMethod
    public IRubyObject rollback() {
        java.sql.Connection conn = getConnection();
        try {
            conn.rollback();
        } catch (SQLException sqle) {
            throw driver.newDriverError(getRuntime(), sqle);
        } finally {
            try {
                conn.setAutoCommit(true);
            } catch (SQLException sqle) {
                throw driver.newDriverError(getRuntime(), sqle);
            }
        }
        return getRuntime().getTrue();
    }

    // ---------------------------------------------------------- HELPER METHODS

    private java.sql.Connection getConnection() {
        Ruby runtime = getRuntime();
        IRubyObject connection_instance = api.getInstanceVariable(this,
                "@connection");
        IRubyObject wrapped_jdbc_connection = api.getInstanceVariable(
                connection_instance, "@connection");
        if (wrapped_jdbc_connection.isNil()) {
            throw driver.newDriverError(runtime,
                    "This connection has already been closed.");
        }
        return (java.sql.Connection) wrapped_jdbc_connection.dataGetStruct();
    }

}

@@ -3425,56 +3425,18 @@
     
-Ruby runtime = getRuntime();%0A        IRubyObject
+Connection
  con
@@ -3453,16 +3453,29 @@
 stance =
+ (Connection)
  api.get
@@ -3541,86 +3541,34 @@
     
-IRubyObject wrapped_jdbc_connection = api.getInstanceVariable(%0A               
+java.sql.Connection conn =
  con
@@ -3587,13 +3587,21 @@
 ance
-, %22@c
+.getInternalC
 onne
@@ -3597,33 +3597,33 @@
 ternalConnection
-%22
+(
 );%0A        if (w
@@ -3621,47 +3621,69 @@
     
-if (wrapped_jdbc_connection.isNil
+try %7B%0A            if (conn == null %7C%7C conn.isClosed
 ()) %7B%0A
+    
     
@@ -3722,36 +3722,21 @@
 ror(
-r
+getR
 untime
-,%0A                   
+(),
  %22Th
@@ -3777,32 +3777,36 @@
 sed.%22);%0A        
+    
 %7D%0A        return
@@ -3803,76 +3803,71 @@
     
-return (java.sql.Connection) wrapped_jdbc_connection.dataGetStruct()
+%7D catch (SQLException ignored) %7B%0A        %7D%0A%0A        return conn
 ;%0A  

Fix missed usage of ivar in Transaction