/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is Protege-2000.
 *
 * The Initial Developer of the Original Code is Stanford University. Portions
 * created by Stanford University are Copyright (C) 2007.  All Rights Reserved.
 *
 * Protege was developed by Stanford Medical Informatics
 * (http://www.smi.stanford.edu) at the Stanford University School of Medicine
 * with support from the National Library of Medicine, the National Science
 * Foundation, and the Defense Advanced Research Projects Agency.  Current
 * information about Protege can be obtained at http://protege.stanford.edu.
 *
 */

package edu.stanford.smi.protege.model;

//ESCA*JAVA0037

import edu.stanford.smi.protege.util.Log;

/**
 * Encapsulation of method for executing a tranaction.
 * <br> <br>
 *
 * Example:
 * <pre> <code>
 * void foo(KnowledgeBase kb) {
 * 		Transaction t = new Transaction(kb) {
 *			public boolean doOperations() {
 *				// kb calls go here
 *				// return true for commit, false for rollback
 *			}
 * 		};
 *		boolean committed = t.execute();
 *		if (committed) {
 *			System.out("transaction committed");
 *		} else {
 * 			System.out("transaction rolled back");
 *		}
 * }
 * </code> </pre>
 *
 * @author Ray Fergerson <fergerson@smi.stanford.edu>
 */
public abstract class Transaction<X> {
    public static final String APPLY_TO_TRAILER_STRING = " -- Apply to: ";

    private KnowledgeBase _knowledgeBase;
    
    private String applyTo;
    
    private String transactionName = "transaction";

    protected Transaction(KnowledgeBase kb) {
        _knowledgeBase = kb;
    }
    
    protected Transaction(KnowledgeBase kb, String transactionName) {
        _knowledgeBase = kb;
        this.transactionName = transactionName;
    }
    
    protected Transaction(KnowledgeBase kb, String transactionName, String applyTo) {
        _knowledgeBase = kb;
        this.transactionName = transactionName;
        this.applyTo = applyTo;
    }
    
    public KnowledgeBase getKnowledgeBase() {
        return _knowledgeBase;
    }

    /** returns true if the the results of this method should be committed */
    public abstract boolean doOperations();

    /** returns true if the transaction was committed
     *
     * This method handles the logic of executing a transaction, including the
     * necessary synchronization.  In addition, it handles correctly both
     * runtime exceptions and errors.
     */
    public boolean execute() {
        boolean commited = false;
        synchronized (_knowledgeBase) {
            boolean transactionComplete = false;
            try {
                _knowledgeBase.beginTransaction(transactionName, applyTo);
                boolean doCommit = doOperations();
                if (doCommit) {
                    commited = _knowledgeBase.commitTransaction();
                } else {
                    /* how to handle an error here? */
                    _knowledgeBase.rollbackTransaction();
                    commited = false;
                }
                transactionComplete = true;
            } finally {
                if (!transactionComplete) {
                    _knowledgeBase.rollbackTransaction();
                }
            }
        }
        return commited;
    }
    
    public X getResult() {
        return null;
    }
    
    public static String getApplyTo(String beginString) {
        int index = beginString.indexOf(Transaction.APPLY_TO_TRAILER_STRING);
        if (index < 0) return null;
        index += Transaction.APPLY_TO_TRAILER_STRING.length();
        return beginString.substring(index);
    }
}
