package org.jboss.cache.aop.loader;

import javax.transaction.Transaction;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.jboss.cache.Fqn;
import org.jboss.cache.aop.PojoCache;
import org.jboss.cache.aop.test.Person;
import org.jboss.cache.aop.test.Address;
import org.jboss.cache.loader.CacheLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Map;
import java.util.HashMap;

/**
 * Commons tests for all CacheLoaders. Aop version.
 *
 * @author bwang
 * @version $Id: ObjectGraphTestsBase.java 3420 2007-01-17 14:43:23Z bwang $
 */
abstract public class ObjectGraphTestsBase extends AbstractCacheLoaderTestBase {
   Log log=LogFactory.getLog(ObjectGraphTestsBase.class);
   PojoCache cache;
   CacheLoader loader = null;
   Transaction tx = null;
   static final Fqn FQN = new Fqn("key");

   protected void setUp() throws Exception {
      super.setUp();
      cache = new PojoCache();
      cache.setCacheMode("local");
      configureCache();
      cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
      cache.createService();
      cache.startService();
      loader = cache.getCacheLoader();
   }

   abstract protected void configureCache() throws Exception;

   protected void tearDown() throws Exception {
      super.tearDown();
      if (tx != null) {
         try {
            tx.commit();
         } catch (Throwable e) {
            e.printStackTrace();
         }
      }
      cache.remove("/");
      loader.remove(Fqn.fromString("/"));
      cache.stopService();
      cache.destroyService();
   }

   protected void addDelay() {
      ; // returns immediately in this case.  Subclasses may override where a delay is needed.
   }

   protected Person createPerson(String name, int age)
   {
      Person p = new Person();
      p.setName(name);
      p.setAge(age);
      return p;
   }

   public void testMultipleRefence() throws Exception
   {
      log.info("testMultipleReference() ...");
      cache.putObject("/person/joe", createPerson("Joe Black", 31));
      Person joe = (Person) cache.getObject("/person/joe");
      cache.putObject("/person/ben", createPerson("Ben Hogan", 51));
      Person ben = (Person) cache.getObject("/person/ben");

      Address addr = new Address();
      addr.setStreet("123 Albert Ave.");
      addr.setCity("Sunnyvale");
      addr.setZip(94087);

      // They share the sub-object: address
      log.info("testMultipleReference(): set Joe address");
      joe.setAddress(addr);
      log.info("testMultipleReference(): set Ben address");
      ben.setAddress(addr);

      log.info("testMultipleReference(): verify");
      Address add1 = (Address) ((Person)cache.getObject("/person/joe")).getAddress();
      Address add2 = (Address) ((Person)cache.getObject("/person/ben")).getAddress();
      assertEquals(add1.getCity(), add2.getCity());
      addr.setCity("Santa Clara");
      assertEquals(add1.getCity(), add2.getCity());

      cache.evict(Fqn.fromString("/person/joe"));
      cache.evict(Fqn.fromString("/person/ben"));

      log.info("testMultipleReference(): after eviction");
      add1 = (Address) ((Person)cache.getObject("/person/joe")).getAddress();
      add2 = (Address) ((Person)cache.getObject("/person/ben")).getAddress();
      assertEquals(add1.getCity(), add2.getCity());
      add1.setCity("Santa Clara");
      // Still not working now. Will need to support it. JCACHE-223
//      assertEquals(add1.getCity(), add2.getCity());
   }

   public void testObjectRemoved() throws Exception
   {
      log.info("testObjectRemoved() ...");
      cache.putObject("/person/joe", createPerson("Joe Black", 31));
      Person joe = (Person) cache.getObject("/person/joe");
      Address addr = new Address();
      addr.setStreet("123 Albert Ave.");
      addr.setCity("Sunnyvale");
      addr.setZip(94087);

      // They share the sub-object: address
      joe.setAddress(addr);

      log.info("testMultipleReference(): verify");
      Address add1 = (Address) ((Person)cache.getObject("/person/joe")).getAddress();

      Map map = new HashMap();
      map.put("1", "1");
      Map m1 = new HashMap();
      m1.put("2", "2");
      map.put("m1", m1);
      joe.setHobbies(map);

      cache.removeObject("/person/joe");
      joe = (Person) cache.getObject("/person/joe");
      assertNull("Joe should be null ", joe);
   }

   public static Test suite() {
      return new TestSuite(ObjectGraphTestsBase.class);
   }

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

}
