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


import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;

import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.config.BuddyReplicationConfig.BuddyLocatorConfig;
import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig;
import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.eviction.LRUPolicy;
import org.jboss.cache.factories.XmlConfigurationParser;
import org.testng.annotations.Test;

/**
 * Tests the ability to clone Configuration elements and end up with
 * independently modifiable configurations.
 * 
 * @author Brian Stansberry
 */
@Test(groups = {"functional"})
public class ConfigurationCloningTest
{
   /** A file that includes every configuration element I could think of */
   public static final String DEFAULT_CONFIGURATION_FILE = "META-INF/conf-test/clonable-config-service.xml";
   
   private static final Log log = LogFactory.getLog(ConfigurationCloningTest.class);
   
   public void testClone() throws Exception
   {
      XmlConfigurationParser parser = new XmlConfigurationParser();
      Configuration c = parser.parseFile(DEFAULT_CONFIGURATION_FILE);
      
      try {
         Configuration clone = c.clone();   
         
         // Test a few simple properties 
         assertEquals(NodeLockingScheme.OPTIMISTIC, clone.getNodeLockingScheme());   
         assertEquals(CacheMode.INVALIDATION_SYNC, clone.getCacheMode());   
         assertEquals("CloneCluster", clone.getClusterName());   
         assertEquals(c.getClusterConfig(), clone.getClusterConfig());   
         assertEquals(3, clone.getStateRetrievalTimeout());   
         
         // Buddy replication config
         BuddyReplicationConfig brc1 = c.getBuddyReplicationConfig();
         BuddyReplicationConfig brc2 = clone.getBuddyReplicationConfig();
         
         assertFalse(brc1 == brc2);
         
         assertEquals(7, brc2.getBuddyCommunicationTimeout());
         assertEquals("cloneGroup", brc2.getBuddyPoolName());
         
         BuddyLocatorConfig blc1 = brc1.getBuddyLocatorConfig();
         BuddyLocatorConfig blc2 = brc2.getBuddyLocatorConfig();
         assertFalse(blc1 == blc2);
         Properties p1 = blc1.getBuddyLocatorProperties();
         Properties p2 = blc2.getBuddyLocatorProperties();
         assertFalse(p1 == p2);
         assertEquals(p1, p2);
         
         // Eviction
         EvictionConfig ec1 = c.getEvictionConfig();
         EvictionConfig ec2 = clone.getEvictionConfig();
         
         assertFalse(ec1 == ec2);
         
         assertEquals(4, ec2.getDefaultEventQueueSize());
         assertEquals(45, ec2.getWakeupIntervalSeconds());
         assertEquals(LRUPolicy.class.getName(), ec2.getDefaultEvictionPolicyClass());
         
         List<EvictionRegionConfig> ercs1 = ec1.getEvictionRegionConfigs();
         List<EvictionRegionConfig> ercs2 = ec2.getEvictionRegionConfigs();
         assertEquals(ercs1.size(), ercs2.size());
         for (int i = 0; i < ercs1.size(); i++)
         {
            compareEvictionRegionConfigs(ercs1.get(i), ercs2.get(i));
         }
         
         // Cache loading
         CacheLoaderConfig clc1 = c.getCacheLoaderConfig();
         CacheLoaderConfig clc2 = clone.getCacheLoaderConfig();
         
         assertFalse(clc1 == clc2);
         
         assertFalse(clc2.isPassivation());
         assertTrue(clc2.isShared());
         
         List<IndividualCacheLoaderConfig> clcs1 = clc1.getIndividualCacheLoaderConfigs();
         List<IndividualCacheLoaderConfig> clcs2 = clc2.getIndividualCacheLoaderConfigs();
         assertEquals(clcs1.size(), clcs2.size());
         for (int i = 0; i < clcs1.size(); i++)
         {
            compareCacheLoaderConfigs(clcs1.get(i), clcs2.get(i));
         }
         
         RuntimeConfig rc1 = c.getRuntimeConfig();
         RuntimeConfig rc2 = clone.getRuntimeConfig();
         assertFalse(rc1 == rc2);
         assertEquals(rc1, rc2);
         
      }
      catch (CloneNotSupportedException e)
      {
         log.error(e.getMessage(), e);
         fail("Cloning failed -- " + e.getMessage());
      }
   }

   private void compareEvictionRegionConfigs(EvictionRegionConfig erc1,
         EvictionRegionConfig erc2)
   {
      assertEquals(erc1.getRegionName(), erc2.getRegionName());
      assertEquals(erc1.getRegionFqn(), erc2.getRegionFqn());
      assertEquals(erc1.getEventQueueSize(), erc2.getEventQueueSize());
      
      EvictionPolicyConfig epc1 = erc1.getEvictionPolicyConfig();
      EvictionPolicyConfig epc2 = erc2.getEvictionPolicyConfig();
      
      assertFalse(epc1 == epc2);
      assertEquals(epc1, epc2);
   }

   private void compareCacheLoaderConfigs(IndividualCacheLoaderConfig clc1,
         IndividualCacheLoaderConfig clc2)
   {
      assertFalse(clc1 == clc2);
      assertEquals(clc1, clc2);
      
      Properties p1 = clc1.getProperties();      
      Properties p2 = clc2.getProperties();
      assertFalse(p1 == p2);
      assertEquals(p1, p2);
      
      SingletonStoreConfig ssc1 = clc1.getSingletonStoreConfig();      
      SingletonStoreConfig ssc2 = clc2.getSingletonStoreConfig();
      assertFalse(ssc1 == ssc2);
      assertEquals(ssc1, ssc2);
   }

}
