/**
 *  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.
 *
 *  See the NOTICE file distributed with this work for additional
 *  information regarding copyright ownership.
 */

package org.seaborne.dboe.transaction;

import java.util.function.Supplier ;

import org.apache.jena.query.ReadWrite ;

/** Application utilities for transactions. */
public class Txn {
    
    /** Execute the Runnable in a read transaction.
     *  Nested transactions are not supported.
     */
    public static <T extends Transactional> void executeRead(T txn, Runnable r) {
        txn.begin(ReadWrite.READ) ;
        r.run(); 
        txn.end() ;
    }

    /** Execute and return a value in a read transaction
     * Nested transactions are not supported.
     */

    public static <T extends Transactional, X> X executeReadReturn(T txn, Supplier<X> r) {
        txn.begin(ReadWrite.READ) ;
        X x = r.get() ;
        txn.end() ;
        return x ;
    }

    /** Execute the Runnable in a write transaction 
     *  Nested transaction are not supported.
     */
    public static <T extends Transactional> void executeWrite(T txn, Runnable r) {
        txn.begin(ReadWrite.WRITE) ;
        try { r.run(); }
        catch (Throwable th) {
            txn.abort();
            txn.end();
            throw th ; 
        }
        txn.commit() ;
        txn.end() ;
    }
    
    /** Execute the Runnable in a write transaction 
     *  Nested transaction are not supported.
     */
    public static <T extends Transactional, X> X executeWriteReturn(Transactional txn, Supplier<X> r) {
        txn.begin(ReadWrite.WRITE) ;
        X x = r.get() ;
        txn.commit() ;
        txn.end() ;
        return x ;
    }
    
    // ---- Thread
    
    /** Create a thread-backed delayed READ transaction action. */
    public static ThreadTxn threadTxnRead(Transactional trans, Runnable action) {
        return ThreadTxn.create(trans, ReadWrite.READ, action, false) ;
    }
    
    /** Create a thread-backed delayed WRITE  action.
     * If called from inside a write transaction on the {@code trans},
     * this will deadlock.
     */
    public static ThreadTxn threadTxnWrite(Transactional trans, Runnable action) {
        return ThreadTxn.create(trans, ReadWrite.WRITE, action, true) ;
    }
    
    /** Create a thread-backed delayed WRITE-abort action (testing). */
    public static ThreadTxn threadTxnWriteAbort(Transactional trans, Runnable action) {
        return ThreadTxn.create(trans, ReadWrite.WRITE, action, false) ;
    }
    

}


@@ -1090,32 +1090,52 @@
 adWrite.READ) ;%0A
+        try %7B  %0A    
         r.run();
@@ -1135,32 +1135,44 @@
 .run(); %0A       
+ %7D finally %7B
  txn.end() ;%0A   
@@ -1163,24 +1163,27 @@
  txn.end() ;
+ %7D 
 %0A    %7D%0A%0A    
@@ -1373,32 +1373,52 @@
 upplier%3CX%3E r) %7B%0A
+        try %7B  %0A    
         txn.begi
@@ -1437,37 +1437,42 @@
 READ) ;%0A        
-X x =
+    return
  r.get() ;%0A     
@@ -1478,38 +1478,34 @@
     
-txn.end() ;%0A        return x ;
+%7D finally %7B txn.end() ; %7D 
 %0A   
@@ -1752,27 +1752,63 @@
 ry %7B
- r.run(); %7D
+%0A            r.run();%0A            txn.commit();
 %0A       
  cat
@@ -1803,16 +1803,18 @@
 %0A       
+ %7D
  catch (
@@ -1858,31 +1858,8 @@
 ();%0A
-            txn.end();%0A
     
@@ -1891,39 +1891,18 @@
    %7D
-%0A        txn.commit() ;%0A       
+ finally %7B
  txn
@@ -1903,26 +1903,27 @@
  %7B txn.end()
- 
 ;
+ %7D
 %0A    %7D%0A    %0A
@@ -2162,32 +2162,51 @@
 dWrite.WRITE) ;%0A
+        try %7B %0A    
         X x = r.
@@ -2213,32 +2213,36 @@
 get() ;%0A        
+    
 txn.commit() ;%0A 
@@ -2248,26 +2248,87 @@
         
+    
-txn.end
+return x ;%0A        %7D catch (Throwable th) %7B%0A            txn.abort
 ()
- 
 ;%0A      
@@ -2325,34 +2325,72 @@
 ();%0A        
+    
-return x ;
+throw th ; %0A        %7D finally %7B txn.end(); %7D
 %0A    %7D%0A    %0A
@@ -3208,19 +3208,13 @@
 ) ;%0A
+
     %7D%0A
-    %0A%0A
 %7D%0A%0A

Use try-finally even on read transactions.