package org.jboss.cache.aop;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCacheListener;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.cache.aop.test.Person;
import org.jboss.aop.proxy.ClassProxy;
import org.jgroups.View;

import java.util.Map;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;


/**
 * New LocalAopTest that doesn't use TreeCacheAopTester. There should have no need for it not.
 *
 * @author Ben Wang
 */

public class NewLocalAopTest extends TestCase
{
   Log log_=LogFactory.getLog(NewLocalAopTest.class);
   PojoCache cache_;

   public NewLocalAopTest(String name)
   {
      super(name);
   }

   protected void setUp() throws Exception
   {
      super.setUp();
      log_.info("setUp() ....");
      String configFile = "META-INF/local-service.xml";
      cache_ = new PojoCache();
      PropertyConfigurator config = new PropertyConfigurator();
      config.configure(cache_, configFile); // read in generic replSync xml
      MyListener listener = new MyListener();
      cache_.addTreeCacheListener(listener);
      cache_.start();
   }

   protected void tearDown() throws Exception
   {
      super.tearDown();
      cache_.stop();
   }

//   public void testDummy() {}

   public void testBadFqn() throws Exception
   {
      log_.info("testBadFqn() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);
      result.setAge(20);

      try {
         cache_.putObject(InternalDelegate.JBOSS_INTERNAL, test);
         fail("putObject under JBoss_Internal should fail");
      } catch (IllegalArgumentException iex)
      {
         // ok
      }

      try {
         cache_.removeObject(InternalDelegate.JBOSS_INTERNAL);
         fail("putObject under JBoss_Internal should fail");
      } catch (IllegalArgumentException iex)
      {
         // ok
      }
   }

   public void testPutRemove() throws Exception
   {
      log_.info("testPutRemove() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);
      result.setAge(20);
      cache_.removeObject("/a");
      assertNull("Object should be null ", cache_.getObject("/a"));
      assertEquals("Age should be updated as ", 20, test.getAge());
   }

   public void testRemoveProxyList() throws Exception
   {
      log_.info("testRemoveProxyList() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      ArrayList list = new ArrayList();
      list.add("English");
      list.add("Taiwanese");
      test.setLanguages(list);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getLanguages() instanceof ClassProxy);

      Person r1 = (Person)cache_.removeObject("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getLanguages() instanceof ClassProxy);
      assertEquals("Same Collection instance", list, result.getLanguages());
   }

   public void testRemoveProxySet() throws Exception
   {
      log_.info("testRemoveProxySet() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      HashSet set = new HashSet();
      set.add("Golf");
      set.add("Cooking");
      test.setSkills(set);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getSkills() instanceof ClassProxy);

      Person r1 = (Person)cache_.removeObject("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getSkills() instanceof ClassProxy);
      assertEquals("Same Collection instance", set, result.getSkills());
   }

   public void testRemoveProxyMap() throws Exception
   {
      log_.info("testRemoveProxyMap() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);

      HashMap map = new HashMap();
      map.put("1", "Golf");
      map.put("2", "Surfing");
      test.setHobbies(map);

      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);

      assertTrue("Instance of proxyclass ", result.getHobbies() instanceof ClassProxy);

      Person r1 = (Person)cache_.removeObject("/a");

      assertEquals("Same instance ", result, r1);
      assertFalse("Instance of proxyclass ", result.getHobbies() instanceof ClassProxy);
      assertEquals("Same Collection instance", map, result.getHobbies());
   }

   public void testPutRemoveNodeExistence() throws Exception
   {
      log_.info("testPutRemove() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);
      result.setAge(20);
      cache_.removeObject("/a");
      assertNull("Object should be null ", cache_.getObject("/a"));
      assertEquals("Age should be updated as ", 20, test.getAge());

      assertNull("DataNode should not exisit ", cache_.get("/a"));
   }

   public void testFindObjects() throws Exception
   {
      log_.info("testFindObjects() ....");
      Map map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 0, map.size());
      Person ben = new Person();
      ben.setName("Ben");
      ben.setAge(10);
      cache_.putObject("/a/b/c", ben);
      cache_.putObject("/e", ben); // multiple keys, same pojo
      Person joe = new Person();
      joe.setName("Joe");
      joe.setAge(10);
      cache_.putObject("/f/joe", joe);
      map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 3, map.size());

      map = cache_.findObjects("/a");
      assertEquals("Objects size should be ", 1, map.size());
      cache_.removeObject("/e");
      map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 2, map.size());
   }

   public void testFindObjectsWithGenericFqn() throws Exception
   {
      log_.info("testFindObjectsWithGenericFqn() ....");
      Map map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 0, map.size());
      Person ben = new Person();
      ben.setName("Ben");
      ben.setAge(10);
      cache_.putObject("/a/b/c", ben);
      cache_.putObject("/e", ben); // multiple keys, same pojo
      Person joe = new Person();
      joe.setName("Joe");
      joe.setAge(10);
      Fqn base = Fqn.fromString("/a");
      Fqn fqn = new Fqn(base, new Long(3));
      cache_.putObject(fqn, joe);
      map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 3, map.size());

      map = cache_.findObjects("/a");
      assertEquals("Objects size should be ", 2, map.size());
      cache_.removeObject("/e");
      map = cache_.findObjects("/");
      assertEquals("Objects size should be ", 2, map.size());
   }

   public void testPutArray1() throws Exception
   {
      log_.info("testPutArray1() ....");
      long[] arr = new long[] {1, 2};
      cache_.putObject("array", arr);
   }

   public void testPutArray2() throws Exception
   {
      log_.info("testPutArray2() ....");
      Person p1 = new Person();
      p1.setName("Ben");
      p1.setAge(10);

      Person p2 = new Person();
      p2.setName("Joe");
      p2.setAge(20);
      Person[] arr = new Person[] {p1, p2};
      cache_.putObject("array", arr);
   }

   public void testNotification() throws Exception
   {
      log_.info("testNotification() ....");
      Person test = new Person();
      test.setName("Ben");
      test.setAge(10);
      cache_.putObject("/a", test);
      Person result = (Person)cache_.getObject("/a");
      assertEquals(" ", test, result);
   }

   public static Test suite() throws Exception
   {
      return new TestSuite(NewLocalAopTest.class);
   }


   public static void main(String[] args) throws Exception
   {
      junit.textui.TestRunner.run(suite());
   }

   public class MyListener implements TreeCacheListener
   {

      public void nodeCreated(Fqn fqn) {
         System.out.println("**** Node created : " +fqn);
      }

      public void nodeRemoved(Fqn fqn) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void nodeLoaded(Fqn fqn) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void nodeEvicted(Fqn fqn) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void nodeModified(Fqn fqn) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void nodeVisited(Fqn fqn) {
         System.out.println("**** Node visited : " +fqn);
      }

      public void cacheStarted(TreeCache cache) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void cacheStopped(TreeCache cache) {
         //To change body of implemented methods use File | Settings | File Templates.
      }

      public void viewChange(View new_view)  // might be MergeView after merging
      {
         //To change body of implemented methods use File | Settings | File Templates.
      }
   }
}

