/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache;


import org.jboss.cache.lock.IdentityLock;
import org.jboss.logging.Logger;
import org.jgroups.blocks.MethodCall;

import javax.naming.Context;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * Maintains the mapping between local (Transaction) and global transactions
 * (GlobalTransaction).
 *
 * @author <a href="mailto:bela@jboss.org">Bela Ban</a> Apr 14, 2003
 * @version $Revision: 1.9.2.5 $
 */
public class TransactionTable {
   /**
    * Keys: Transaction, values: GlobalTransaction
    */
   protected HashMap tx_map=new HashMap();

   /**
    * Keys: GlobalTransaction, values: TransactionEntries
    */
   protected HashMap txs=new HashMap();

   /**
    * Our logger
    */
   private Logger log=Logger.getLogger(getClass());

   /**
    * Used to lookup the TransactionManager from JNDI (only on first time)
    */
   protected Context ctx=null;

   /**
    * The TransactionManager. To get the transaction associated with the current thread
    */
   protected TransactionManager tm=null;


   public TransactionTable() {
      ;
   }


   public GlobalTransaction get(Transaction tx) {
      return tx != null ? (GlobalTransaction)tx_map.get(tx) : null;
   }

   public void put(Transaction tx, GlobalTransaction gtx) {
      if(tx == null) {
         log.error("put(): key (Transaction) is null");
         return;
      }
      tx_map.put(tx, gtx);
   }

   public TransactionEntry get(GlobalTransaction gtx) {
      return gtx != null ? (TransactionEntry)txs.get(gtx) : null;
   }

   public void put(GlobalTransaction tx, TransactionEntry entry) {
      if(tx == null) {
         log.error("put(): key (GlobalTransaction) is null");
         return;
      }
      txs.put(tx, entry);
   }

   public TransactionEntry remove(GlobalTransaction tx) {
      return (TransactionEntry)txs.remove(tx);
   }

   public GlobalTransaction remove(Transaction tx) {
      if(tx == null)
         return null;
      return (GlobalTransaction)tx_map.remove(tx);
   }

   public void addModification(GlobalTransaction gtx, MethodCall m) {
      TransactionEntry entry=get(gtx);
      if(entry == null) {
         log.error("addModification(): transaction not found (gtx=" + gtx + ")");
         return;
      }
      entry.addModification(m);
   }

   public void addUndoOperation(GlobalTransaction gtx, MethodCall m) {
      TransactionEntry entry=get(gtx);
      if(entry == null) {
         log.error("addUndoOperation(): transaction not found (gtx=" + gtx + ")");
         return;
      }
      entry.addUndoOperation(m);
   }

   public void addNode(GlobalTransaction gtx, Fqn node) {
      TransactionEntry entry=get(gtx);
      if(entry == null) {
         log.error("addNode(): transaction not found (gtx=" + gtx + ")");
         return;
      }
      entry.addNode(node);
   }

   public void addLock(GlobalTransaction gtx, IdentityLock l) {
      TransactionEntry entry=get(gtx);
      if(entry == null) {
         log.error("addLock(): transaction entry not found for (gtx=" + gtx + ")");
         return;
      }
      entry.addLock(l);
   }

   public String toString() {
      StringBuffer sb=new StringBuffer();
      sb.append(tx_map.size()).append(" mappings, ");
      sb.append(txs.size()).append(" transactions");
      return sb.toString();
   }

   public String toString(boolean print_details) {
      if(!print_details)
         return toString();
      StringBuffer sb=new StringBuffer();
      Map.Entry entry;
      sb.append("tx_map:\n");
      for(Iterator it=tx_map.entrySet().iterator(); it.hasNext();) {
         entry=(Map.Entry)it.next();
         sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
      }
      for(Iterator it=txs.entrySet().iterator(); it.hasNext();) {
         entry=(Map.Entry)it.next();
         sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
      }
      return sb.toString();
   }
}
