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.aop.proxy.ClassProxy;
import org.jboss.cache.aop.test.Person;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

//import org.jboss.test.JBossTestCase;


/**
 * LocalTestCase.java that uses standalone aop package.
 * @author Ben Wang
 */

public class LocalAopTest extends TestCase
{
   // TODO No need to use the TreeCacheAopTester now. 
//   Category log = getLog();
   Log log=LogFactory.getLog(LocalAopTest.class);
   TreeCacheAopTester tester;


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

   protected void setUp() throws Exception
   {
      super.setUp();
      log.info("setUp() ....");
      String configFile = "META-INF/local-service.xml";
      tester = new TreeCacheAopTester(configFile);
   }

   protected void tearDown() throws Exception
   {
      super.tearDown();
      tester.stop();
      tester = null;
   }

//   public void testDummy() {}

   public void testSetup()
   {
      log.info("testSetup() ....");
      try {
         tester.testSetup();
      } catch (Exception ex) {
         ex.printStackTrace();
         fail("testSetup(): fails. " + ex.toString());
      }
   }

   public void testSimple() throws Exception
   {
      log.info("testSimple() ....");
      tester.createPerson("/person/test1", "Joe Black", 32);
      assertEquals((Object) "Joe Black", (Object) tester.getName("/person/test1"));
//      assertTrue(tester.getAge("/person/test1") == 32);
//      tester.removePerson("/person/test1");
   }

   public void testMap() throws Exception
   {
      log.info("testMap() ....");
      tester.createPerson("/person/test1", "Ben Wang", 40);
      assertEquals((Object) "Ben Wang", (Object) tester.getName("/person/test1"));
      Person ben = (Person)tester.getPerson("/person/test1");
//      Map skills = new HashMap();
      Map hobbies = ben.getHobbies();
      if (hobbies == null) {
         hobbies = new HashMap();
         ben.setHobbies(hobbies);
         // NB: it is neccessary to get hobbies again to get advised version
         hobbies = ben.getHobbies();
      }
      hobbies.put("1", "English");
      hobbies.put("2", "French");
      if( !(hobbies instanceof ClassProxy)) {
         fail("Hobbies is not an instance of ClassProxy");
      }
//      ben.setHobbies(skills);
//      skills = ben.getHobbies();

      hobbies = ben.getHobbies();
      assertEquals("Hobbies size", 2, hobbies.size());
      log.debug("Hobbies is " + hobbies.toString());
   }

   public void testModification() throws Exception
   {
      tester.createPerson("/person/test2", "Joe", 32);
      tester.setName("/person/test2", "Joe Black");
      assertEquals((Object) tester.getName("/person/test2"), (Object) "Joe Black");
      tester.removePerson("/person/test2");
   }

   public void testRemove() throws Exception
   {
      tester.createPerson("/person/test3", "Joe", 32);
      tester.removePerson("/person/test3");
      try {
         tester.getName("/person/test3");
         fail("Object wasn't removed");
      } catch (Exception e) {
         // should be thrown
      }
   }

   public void testDynamicRefSwapping() throws Exception
   {
      tester.createPerson("/person/test3", "Joe", 32);
      Person person = (Person)tester.getPerson("/person/test3");
      try {
         person.setAge(30);
         List med = person.getMedication();
         assertNull("Medication should be null ", med);
         person.setAge(60);
         med = person.getMedication();
         assertEquals("Medication ", (Object)"Lipitor", (Object)med.get(0));
      } catch (Exception e) {
         // should be thrown
      }
   }

   public void testDependent() throws Exception
   {
      tester.createPerson("/person/test4", "Joe Black", 32);
      tester.setCity("/person/test4", "Mannheim");
      assertEquals((Object) tester.getCity("/person/test4"), (Object) "Mannheim");
   }


   public void testSerialization() throws Throwable
   {

      Person p = (Person) tester.testSerialization();
/*
      if (p instanceof Advised)
      {
         InstanceAdvisor advisor = ((Advised) p)._getInstanceAdvisor();
         Interceptor[] interceptors = advisor.getInterceptors();
         for (int i = 0; i < interceptors.length; i++)
         {
            assertTrue("CacheInterceptor shouldn't be serialized",
                !(interceptors[i] instanceof CacheInterceptor));
         }
      }
*/
      assertEquals((Object) "Joe Black", (Object) p.getName());
      assertEquals((Object) "Mannheim", (Object) p.getAddress().getCity());
   }

   public void testDeserialization() throws Throwable
   {

      Person p = new Person();
      p.setName("test6");
      tester.testDeserialization("/person/test6", p);
      String name = tester.getName("/person/test6");
      assertEquals((Object) "test6", (Object) name);
   }

   public void testMap2() throws Throwable
   {
      tester.createPerson("/person/test5", "Joe Black", 32);
      tester.setHobby("/person/test5", "music", "guitar");
      Object val = tester.getHobby("/person/test5", "music");
      assertEquals("guitar", val);
      tester.setHobby("/person/test5", "a", "b");
      tester.getHobby("/person/test5", "a");
      tester.printPerson("/person/test5");
   }

   public void testList() throws Throwable
   {
      tester.createPerson("/person/test6", "p6", 50);
      tester.addLanguage("/person/test6", "German");
      tester.addLanguage("/person/test6", "English");
      tester.addLanguage("/person/test6", "French");
      int size = tester.getLanguagesSize("/person/test6");
      assertTrue(size == 3);
      tester.printCache();
      tester.addLanguage("/person/test6", "asdf");
      tester.printCache();
      tester.removeLanguage("/person/test6", "asdf");
      tester.printCache();
      size = tester.getLanguagesSize("/person/test6");
      //	assertTrue(size==3);
      for (int i = 0; i < size; i++) {
         log.debug("" + i + " : " + tester.getLanguage("/person/test6", i));
      }
      assertEquals(new Integer(3), new Integer(size));
      String language = (String) tester.getLanguage("/person/test6", 1);
      assertEquals((Object) "English", (Object) language);
   }

   public void testSet() throws Throwable
   {
      tester.createPerson("/person/test7", "p7", 27);
      tester.addSkill("/person/test7", "Java");
      tester.addSkill("/person/test7", "Java");
      tester.addSkill("/person/test7", "Java");
      Set skills = tester.getSkills("/person/test7");
      assertEquals(new Integer(1), new Integer(skills.size()));
      tester.removeSkill("/person/test7", "Java");
      skills = tester.getSkills("/person/test7");
      assertTrue(skills.isEmpty());
      tester.addSkill("/person/test7", "Java");
      tester.addSkill("/person/test7", "J2EE");
      tester.addSkill("/person/test7", "JBoss");
      skills = tester.getSkills("/person/test7");
      assertEquals(new Integer(3), new Integer(skills.size()));
   }

   public void testFieldSynchronization() throws Throwable
   {
      String key = "/person/test8";
      tester.createPerson(key, "p8", 8);
      assertEquals(tester.getName(key), tester.getFieldValue(key, "name"));
      assertEquals(new Integer(tester.getAge(key)), tester.getFieldValue(key, "age"));
      tester.setName(key, "p8x");
      assertEquals(tester.getName(key), tester.getFieldValue(key, "name"));
      tester.setAge(key, 18);
      assertEquals(new Integer(tester.getAge(key)), tester.getFieldValue(key, "age"));
   }

   public void testInheritance() throws Exception
   {
      tester.createStudent("/person/joe", "Joe", 32, "Senior");
      tester.setName("/person/joe", "Joe Black");
      assertEquals((Object) tester.getName("/person/joe"), (Object) "Joe Black");
      tester.setYear("/person/joe", "Junior");
      assertEquals((Object) tester.getYear("/person/joe"), (Object) "Junior");
      tester.removePerson("/person/joe");
   }


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


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

}

