package test.propagation;

import junit.framework.TestCase;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.aop.PojoCache;
import propagation.PropagationManager;
import propagation.impl.PropagationManagerImpl;

/**
 * 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 PropagationReplAopTest extends TestCase {
   private PropagationManager pm_;
   // 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");
      initPm();
   }

   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 initPm() throws Exception {
      pm_ = new PropagationManagerImpl();

      pm_.setRootNode("Japan");

      pm_.addNode("Japan", "Tokyo");   // Tokyo station

      pm_.addNode("Japan.Tokyo", "WindSensor1");   // Wind sensor device
      pm_.addStateItem("Japan.Tokyo.WindSensor1", 1000, "power supply", 1040); // power supply
      pm_.addStateItem("Japan.Tokyo.WindSensor1", 1001, "sensor unit", 1040); // sensor unit

      pm_.addNode("Japan.Tokyo", "RainSensor1");   // rain sensor device
      pm_.addStateItem("Japan.Tokyo.RainSensor1", 1002, "power supply", 1040); // power supply
      pm_.addStateItem("Japan.Tokyo.RainSensor1", 1003, "sensor unit", 1040); // sensor unit

      pm_.addNode("Japan", "Yokohama");   // Yokohama station

      pm_.addNode("Japan.Yokohama", "WindSensor2"); // wind sensor device
      pm_.addStateItem("Japan.Yokohama.WindSensor2", 1000, "power supply", 1040); // power supply
      pm_.addStateItem("Japan.Yokohama.WindSensor2", 1001, "sensor unit", 1040); // sensor unit

      pm_.addNode("Japan.Yokohama", "RainSensor2"); // rain sensor device
      pm_.addStateItem("Japan.Yokohama.RainSensor2", 1002, "power supply", 1040); // power supply
      pm_.addStateItem("Japan.Yokohama.RainSensor2", 1003, "sensor unit", 1040); // sensor unit

      pm_.createNode("WindSummary", "WindSummary"); // summary node for wind sensors in this network
      pm_.setUpperNode("WindSummary", "Japan.Tokyo.WindSensor1"); // assoication
      pm_.setUpperNode("WindSummary", "Japan.Yokohama.WindSensor2"); // association

      pm_.createNode("RainSummary", "RainSummary"); // summary node for rain sensor in this network.
      pm_.setUpperNode("RainSummary", "Japan.Tokyo.RainSensor1"); // association
      pm_.setUpperNode("RainSummary", "Japan.Yokohama.RainSensor2"); // association
   }

   public void testPropagation() throws Exception {
      // Here we ask the pojo cache to manage pm
      cache1_.putObject("/monitor", pm_);

      // Output
      printStatus("Initial state", pm_);

      // Retrieve the pojo from the Server #2
      PropagationManager pm2 = (PropagationManager) cache2_.getObject("monitor");

      System.out.println("---------------------------------------------");
      System.out.println("Modified on Server #1");
       // A state has been changed in one of the item. This will be fine-grained replicated.
      pm_.stateChange("Japan.Tokyo.RainSensor1", 1003, 1041);
      printStatus("Japan.Tokyo.RainSensor1: id: 1003  state: 1040->1041 (retrieved from cache #2)", pm2);

      System.out.println("---------------------------------------------");
      System.out.println("Modified on Server #2");
      // A state has been changed in one of the item. This will be fine-grained replicated.
      pm2.stateChange("Japan.Yokohama.WindSensor2", 1001, 1041); // Modified state on cache #2
      printStatus("Japan.Yokohama.WindSensor2: id: 1001  state: 1040->1041 (retrieved from cache #1)"
              , pm2);

   }

   private void printStatus(String msg, PropagationManager pm) {
      System.out.println("---------------------------------------------");
      System.out.println(msg);
      System.out.println("---------------------------------------------");
      pm.printNodes();
//      System.out.println("--------------------");
//      pm.printNodes("WindSummary");
//      System.out.println("--------------------");
//      pm.printNodes("RainSummary");
      System.out.println("\n\n");
   }

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