package org.jboss.cache.eviction;

import org.jboss.cache.config.ConfigurationComponent;
import org.jboss.cache.config.ConfigurationException;
import org.jboss.cache.config.Dynamic;
import org.jboss.cache.config.EvictionPolicyConfig;
import org.jboss.cache.util.Util;

/**
 * Base implementation of {@link EvictionPolicyConfig}. Adds properties
 * for the most commonly used config elements.
 *
 * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
 */
public abstract class EvictionPolicyConfigBase
      extends ConfigurationComponent
      implements EvictionPolicyConfig
{
   /**
    * The serialVersionUID
    */
   private static final long serialVersionUID = 4591691674370188932L;

   private String evictionPolicyClass;
   @Dynamic
   private int maxNodes = 0;

   @Dynamic
   private int minTimeToLiveSeconds = 0;

   /**
    * Can only be instantiated by a subclass.
    * <p/>
    * Calls {@link #setEvictionPolicyClassName()}.
    */
   protected EvictionPolicyConfigBase()
   {
      setEvictionPolicyClassName();
   }

   public String getEvictionPolicyClass()
   {
      return evictionPolicyClass;
   }

   public void setEvictionPolicyClass(String evictionPolicyClass)
   {
      testImmutability("evictionPolicyClass");
      this.evictionPolicyClass = evictionPolicyClass;
   }

   public int getMaxNodes()
   {
      return maxNodes;
   }

   public void setMaxNodes(int maxNodes)
   {
      testImmutability("maxNodes");
      this.maxNodes = maxNodes;
   }

   public int getMinTimeToLiveSeconds()
   {
      return this.minTimeToLiveSeconds;
   }

   public void setMinTimeToLiveSeconds(int minTimeToLiveSeconds)
   {
      this.minTimeToLiveSeconds = minTimeToLiveSeconds;
   }

   public void validate() throws ConfigurationException
   {
      // no-op
   }

   @Override
   public boolean equals(Object obj)
   {
      if (obj == null) return false;
      if (this == obj)
         return true;
      if (getClass().equals(obj.getClass()))
      {
         EvictionPolicyConfigBase other = (EvictionPolicyConfigBase) obj;

         return this.maxNodes == other.maxNodes && this.minTimeToLiveSeconds == other.minTimeToLiveSeconds
               && Util.safeEquals(this.evictionPolicyClass, other.evictionPolicyClass);
      }

      return false;
   }

   @Override
   public int hashCode()
   {
      int result = 17;
      result = 31 * result + maxNodes;
      result = 31 * result + minTimeToLiveSeconds;
      result = 31 * result + (evictionPolicyClass == null ? 0 : evictionPolicyClass.hashCode());
      return result;
   }

   public void reset()
   {
      setEvictionPolicyClass(null);
      setMaxNodes(0);
      setMinTimeToLiveSeconds(0);
      setEvictionPolicyClassName();
   }

   /**
    * This method should be overridden by subclass implementers to set the default
    * {@link #setEvictionPolicyClass(String) policy class name} for the subclass.
    * This will be called when the implementation is constructed, but is also
    * called in {@link #reset()}.
    */
   abstract protected void setEvictionPolicyClassName();
}
