/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.cache.pojo.annotation;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNotSame;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;

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

import javax.naming.Context;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
import org.jboss.cache.pojo.PojoCache;
import org.jboss.cache.pojo.PojoCacheFactory;
import org.jboss.cache.pojo.test.Gadget;
import org.jboss.cache.pojo.test.Resource;
import org.jboss.cache.pojo.test.SpecialAddress;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
 * Test for JDK50 specific annotation.
 *
 * @author Ben Wang
 */
@Test(groups = {"functional"})
public class ReplicatedAnnotationTest 
{
   Log log_ = LogFactory.getLog(ReplicatedAnnotationTest.class);
   PojoCache cache_;
   PojoCache cache1_;


   @BeforeMethod(alwaysRun = true)
   protected void setUp() throws Exception
   {
      Properties prop = new Properties();
      prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
      boolean toStart = false;
      cache_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);

      cache1_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
      cache_.start();
      cache1_.start();
   }

   @AfterMethod(alwaysRun = true)
   protected void tearDown() throws Exception
   {
      cache_.stop();
      cache1_.stop();
   }

   public void testTransientAnnotation() throws Exception
   {
      log_.info("testTransientAnnotation() ....");
      Gadget ga = new Gadget();
      ga.setName("Printer");
      Resource res = new Resource();
      res.setName("Inet");
      res.setConnection("Eth0");
      ga.setResource(res);

      cache_.attach("/gadget", ga);
      Object obj = cache_.find("/gadget");
      assertEquals(ga, obj);

      Gadget ga1 = (Gadget) cache1_.find("/gadget");
      assertEquals("Name is ", ga.getName(), ga1.getName());

      assertNotNull("Resource should not be null on cache1 ", ga.getResource());
      assertNull("Resource should be null", ga1.getResource());
   }

   public void testSeriazableAnnotation() throws Exception
   {
      log_.info("testSerializableAnnotation() ....");
      Gadget ga = new Gadget();
      ga.setName("Printer");
      SpecialAddress addr = new SpecialAddress();
      addr.setAddr("10.1.2.2");
      ga.setAddr(addr);

      cache_.attach("/gadget", ga);
      Object obj = cache_.find("/gadget");
      assertEquals(ga, obj);

      Gadget ga1 = (Gadget) cache1_.find("/gadget");
      assertEquals("Name is ", ga.getName(), ga1.getName());

      SpecialAddress addr1 = (SpecialAddress) ga1.getAddr();
      addr1.setAddr("5152967326");

      assertNotSame("Special address should not be updated: ", addr1.getAddr(), addr.getAddr());

      ga1.setAddr(addr1);
      assertEquals("Special address should be the same", ga.getAddr().getAddr(), ga1.getAddr().getAddr());

      cache_.detach("/gadget");
   }

   /**
    * We haven't implemented this feature yet.
    *
    * @throws Exception
    */
   @Test(enabled = false)
   public void testSeriazableAnnotationWithRelationship() throws Exception
   {
      log_.info("testSerializableAnnotationWithRelationship() ....");
      Gadget ga = new Gadget();
      ga.setName("Printer");
      SpecialAddress addr = new SpecialAddress();
      addr.setAddr("10.1.2.2");
      ga.setAddr(addr);

      cache_.attach("/gadget1", ga);
      Object obj = cache_.find("/gadget1");
      assertEquals(ga, obj);

      Gadget ga2 = new Gadget();
      ga2.setName("Fax");
      ga2.setAddr(addr);
      cache_.attach("/gadget2", ga2);

      ga = (Gadget) cache1_.find("/gadget1");
      ga2 = (Gadget) cache1_.find("/gadget2");
      assertTrue("Sepecial address should be the same ", ga.getAddr() == ga2.getAddr());
   }

   /**
    * Test ClassProxy for generic List.
    *
    * @throws Exception
    */
   @SuppressWarnings("unchecked")
   public void testCollectionWithGenerics() throws Exception
   {
      log_.info("testCollectionWithGenerics() ....");
      List<String> list = new ArrayList<String>();
      list.add("1");
      list.add("2");

      cache_.attach("/test", list);

      List<String> list1 = (List<String>) cache_.find("/test");
      list1.add("3");
      String l3 = list1.get(2);
      assertEquals("String ", "3", l3);

      list1 = (List<String>) cache1_.find("/test");
      l3 = list1.get(2);
      assertEquals("String ", "3", l3);
   }




}
