/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.config;

import org.jboss.cache.NodeFactory;
import org.jboss.cache.RPCManager;
import org.jboss.cache.buddyreplication.BuddyGroup;
import org.jboss.cache.util.Util;
import org.jgroups.Channel;
import org.jgroups.ChannelFactory;

import javax.transaction.TransactionManager;

public class RuntimeConfig extends ConfigurationComponent
{
   /**
    * The serialVersionUID
    */
   private static final long serialVersionUID = 5626847485703341794L;

   private transient TransactionManager transactionManager;
   private transient Channel channel;
   private transient ChannelFactory muxChannelFactory;
   private transient NodeFactory nodeFactory;
   private transient BuddyGroup buddyGroup;
   private RPCManager rpcManager;

   /**
    * Resets the runtime to default values.
    */
   public void reset()
   {
      // only reset the node factory and channel for now.
      nodeFactory = null;
      channel = null;
      rpcManager = null;
   }


   /**
    * Gets the factory the cache will use to create a multiplexed channel.
    *
    * @return the channel, or <code>null</code> if not set
    */
   public ChannelFactory getMuxChannelFactory()
   {
      return muxChannelFactory;
   }

   /**
    * Sets the factory the cache should use to create a multiplexed channel.
    * Ignored if a Channel is directly configured via
    * {@link {@link #setChannel(Channel)}. If the channel factory is set,
    * {@link Configuration#setMultiplexerStack(String)} must also be set, or
    * a <code>CacheException</code> will be thrown during cache startup.
    *
    * @param multiplexerChannelFactory
    */
   public void setMuxChannelFactory(ChannelFactory multiplexerChannelFactory)
   {
      testImmutability("muxChannelFactory");
      this.muxChannelFactory = multiplexerChannelFactory;
   }

   /**
    * Gets the channel the cache is using.
    * <p/>
    * External callers should use extreme care if they access the channel.
    * The cache expects it has exclusive access to the channel; external code
    * trying to send or receive messages via the channel will almost certainly
    * disrupt the operation of the cache.
    * </p>
    *
    * @return the channel. May return <code>null</code> if the channel was
    *         not externally set via {@link #setChannel(Channel)} and the
    *         cache has not yet been started.
    * @see #setChannel(Channel)
    */
   public Channel getChannel()
   {
      return channel;
   }

   /**
    * Sets the channel the cache will use.  The channel should not be
    * connected or closed.
    * <p/>
    * External callers should use extreme care if they access the channel.
    * The cache expects it has exclusive access to the channel; external code
    * trying to send or receive messages via the channel will almost certainly
    * disrupt the operation of the cache.
    * </p>
    * <p/>
    * If an application wishes to send and receive messages using the same
    * underlying channel as the <ocde>Cache</code>, a multiplexed channel should
    * be used. Two separate mux channels should be created from the same
    * <code>ChannelFactory</code> using the same <i>stack name</i> but different
    * <code>id</code>s.
    * See {@link ChannelFactory#createMultiplexerChannel(String,String,boolean,String)}.
    * These two mux channels will share the same underlying channel. One of the
    * two mux channels can be injected into the cache; the other can be used by
    * the application.  The cache will not see the application messages and vice versa.
    * </p>
    * <p/>
    * Configuring the cache to use a mux channel can also be done by configuring
    * {@link #setMuxChannelFactory(ChannelFactory) the channel factory} and the
    * {@link Configuration#setMultiplexerStack(String) stack name}, in which case
    * the cache will create and use a mux channel.
    * </p>
    *
    * @param channel
    */
   public void setChannel(Channel channel)
   {
      this.channel = channel;
   }

   public TransactionManager getTransactionManager()
   {
      return transactionManager;
   }

   public void setTransactionManager(TransactionManager transactionManager)
   {
      testImmutability("transactionManager");
      this.transactionManager = transactionManager;
   }

   public NodeFactory getNodeFactory()
   {
      return nodeFactory;
   }

   public void setNodeFactory(NodeFactory nodeFactory)
   {
      this.nodeFactory = nodeFactory;
   }

   @Override
   public boolean equals(Object obj)
   {
      if (this == obj)
      {
         return true;
      }

      if (obj instanceof RuntimeConfig)
      {
         RuntimeConfig other = (RuntimeConfig) obj;
         return Util.safeEquals(transactionManager, other.transactionManager)
               && Util.safeEquals(muxChannelFactory, other.muxChannelFactory)
               && Util.safeEquals(rpcManager, other.rpcManager)
               && Util.safeEquals(channel, other.channel);
      }

      return false;
   }

   @Override
   public int hashCode()
   {
      int result = 17;
      result = result * 29 + (transactionManager == null ? 0 : transactionManager.hashCode());
      result = result * 29 + (muxChannelFactory == null ? 0 : muxChannelFactory.hashCode());
      result = result * 29 + (rpcManager == null ? 0 : rpcManager.hashCode());
      result = result * 29 + (channel == null ? 0 : channel.hashCode());
      return result;
   }

   public void setBuddyGroup(BuddyGroup buddyGroup)
   {
      this.buddyGroup = buddyGroup;
   }

   public BuddyGroup getBuddyGroup()
   {
      return buddyGroup;
   }

   public void setRPCManager(RPCManager rpcManager)
   {
      this.rpcManager = rpcManager;
   }

   public RPCManager getRPCManager()
   {
      return rpcManager;
   }

   @Override
   public RuntimeConfig clone() throws CloneNotSupportedException
   {
      return (RuntimeConfig) super.clone();
   }


}
