package test.examples;

import junit.framework.TestCase;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.aop.PojoCache;
import examples.Address;
import examples.Course;
//import examples.Person;
import examples.Student;

/**
 * Driver test to illustrate the sensor netowrk supervising system using pojo cache. By using the cache, it will have:
 * <ul>
 * <li>automatic state fail over</li>
 * <li>fine-grained replication</li>
 * <li>preservation of object graph relationship</li>
 * </ul>
 */
public class StudentMaintTest extends TestCase {

   private Student joe_;
   private Student mary_;
   private Course foo_;
   private Course bar_;

   // cache1 and cache2 are in the same clustering group.
   private PojoCache cache1_;
   private PojoCache cache2_;

   protected void setUp() throws Exception {
      cache1_ = createCache("TestCluster");
      cache2_ = createCache("TestCluster");
      init();
   }

   protected void tearDown() throws Exception {
      cache1_.remove("/");
      cache1_.stop();
      cache2_.stop();
   }

   private PojoCache createCache(String name) throws Exception {
      PojoCache tree = new PojoCache();
      PropertyConfigurator config = new PropertyConfigurator();   // configure the cache through injection
       // read in the replSync xml. Here we use synchronous mode replication.
      config.configure(tree, "META-INF/replSync-service.xml");
      tree.setClusterName(name); // We can set a different cluster group.
      tree.start(); // kick start the cache
      return tree;
   }

   /**
    * Populate the propagation tree.
    *
    * @throws Exception
    */
   protected void init() throws Exception {


      mary_ = new Student();
      mary_.setName("Mary Smith");

      Address address = new Address();
      address.setStreet("456 Oak Drive");
      address.setCity("Pleasantville, CA");
      address.setZip(94555);

      mary_.setAddress(address);


      joe_ = new Student();
      joe_.setName("Joe Smith");
      joe_.setSchool("Engineering");

      // Mary and Joe have the same address
      joe_.setAddress(address);

      foo_ = new Course();
      foo_.setTitle("Intro to Foo");
      foo_.setInstructor("Jones");

      joe_.addCourse(foo_);
      mary_.addCourse(foo_);

      bar_ = new Course();
      bar_.setTitle("Advanced Bar");
      bar_.setInstructor("Woods");
      bar_.setRoom("104 Encina");

   }

   public void testPropagation() throws Exception {

      // Here we ask the pojo cache to manage mary_ and joe_
      cache1_.putObject("/students/54321", mary_);
      cache1_.putObject("/students/65432", joe_);
      cache1_.putObject("/courses/101", foo_);
      cache1_.putObject("/courses/401", bar_);

      // Output
      printStatus("Initial state for Mary", mary_);
      printStatus("Initial state for Joe", joe_);

      // Retrieve the pojos from the Server #2
      Student mary2 = (Student) cache2_.getObject("/students/54321");
      Student joe2  = (Student) cache2_.getObject("/students/65432");
      Course  foo2  = (Course) cache2_.getObject("/courses/101");

      System.out.println("---------------------------------------------");
      System.out.println("Modified on Server #1");
       // Change state in one of the items. This will be fine-grained replicated
      foo_.setRoom("101 Alvarez"); // Modified state on cache #2
      printStatus("Course Update: id: 401  room: null->101 Alvarez (retrieved from cache #2)"
                  , foo2);

      System.out.println("---------------------------------------------");
      System.out.println("Modified on Server #2");
       // Change state in one of the items. This will be fine-grained replicated
      joe2.addCourse(bar_); // Modified state on cache #2
      printStatus("Student Update: id: 65432  addCourse: Advanced Bar (retrieved from cache #1)"
                  , joe_);

      System.out.println("---------------------------------------------");
      System.out.println("Modified on Server #1");
       // Change state in one of the items. This will be fine-grained replicated.
      mary_.setSchool("Engineering");
      printStatus("Student Update: id: 65432  school: null->Engineering (retrieved from cache #2)", mary2);

      if(!mary_.getSchool().equals(mary2.getSchool()))
      {
         throw new RuntimeException("School field is not replicated correctly. on cache1: " +mary_.getSchool() +
         " on cache2: " +mary2.getSchool());
      }

   }

   private void printStatus(String msg, Object obj) {
      System.out.println("---------------------------------------------");
      System.out.println(msg);
      System.out.println("---------------------------------------------");
      System.out.println(obj.toString());
   }

   public static void main(String[] args) throws Exception {
      StudentMaintTest smTest = new StudentMaintTest();
      smTest.setUp();
      smTest.testPropagation();
      smTest.tearDown();
   }
}
