/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.cache.pojo.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * Test class for PojoCache.
 * Person is a POJO that will be instrumented with CacheFieldInterceptor
 *
 * @version $Revision: 5153 $
 *          <p>Below is the annotation that signifies this class is "prepared" under JBossAop. This is used in
 *          conjunction with a special jboss-aop.xml (supplied by PojoCache). In addition, this is JDK1.4 style,
 *          so a annoc Ant build target is needed to pre-compile it.</p>
 *          <p>To use this approach, just apply this line to your pojo and run annoc (and possibly aopc).</p>
 */
// We are using JDK1.5 annotation.
@org.jboss.cache.pojo.annotation.Replicable
public class Person
{
   private String name = null;
   private int age = 0;
   private Map<String, String> hobbies = null;
   private Address address = null;
   private Set<String> skills;
   private List<String> languages;
   // Test for transient field non-replication
   private transient String currentStatus = "Active";
   // Test swapping out the Collection ref with proxy one
   // medication will be different when age limit is exceeded.
   private List<String> medication = null;
   private static final int AGE1 = 50;
   private static final int AGE2 = 60;
   private final Map<String, String> finalMap;

   public Person()
   {
      this(null);
   }
   
   public Person(Map<String, String> map)
   {
      finalMap = map;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }

   public void setCurrentStatus(String status)
   {
      currentStatus = status;
   }

   public String getCurrentStatus()
   {
      return currentStatus;
   }

   public void setName(Object obj)
   {
      this.name = (String) obj;
   }

   public int getAge()
   {
      return age;
   }

   public void setAge(int age)
   {

      this.age = age;

      // This will swap out the reference dynamically
      if (age < AGE1)
      {
         if (medication != null)
         {
            medication.clear();
            medication = null;
         }
      } else
      {
         if (age >= AGE1)
         {
            addMedication("Lipitor");
         }

         if (age >= AGE2)
         {
            addMedication("Vioxx");
         }
      }


   }

   void addMedication(String name)
   {
      if (medication == null)
         medication = new ArrayList<String>();
      if (!medication.contains(name))
         medication.add(name);
   }

   public Map<String, String> getHobbies()
   {
      return hobbies;
   }

   public void setHobbies(Map<String, String> hobbies)
   {
      this.hobbies = hobbies;
   }

   public Address getAddress()
   {
      return address;
   }

   public void setAddress(Address address)
   {
      this.address = address;
   }

   public Set<String> getSkills()
   {
      return skills;
   }

   public void setSkills(Set<String> skills)
   {
      this.skills = skills;
   }

   public List<String> getMedication()
   {
      return medication;
   }

   public void setMedication(List<String> medication)
   {
      this.medication = medication;
   }

   public List<String> getLanguages()
   {
      return languages;
   }

   public void setLanguages(List<String> languages)
   {
      this.languages = languages;
   }
   
   public Map<String, String> getFinalMap()
   {
      return this.finalMap;
   }

   public String toString()
   {
      StringBuffer sb = new StringBuffer();
      sb.append("name=").append(getName()).append(", age=").append(getAge()).append(", hobbies=")
              .append(print(getHobbies())).append(", address=").append(getAddress()).append(", skills=")
              .append(skills).append(", languages=").append(languages).toString();
      if (medication != null)
         sb.append(", medication=" + medication);
      return sb.toString();
   }

   private static boolean equals(Object o1, Object o2)
   {
      if (o1 == o2)
         return true;

      if (o1 == null || o2 == null)
         return false;

      return o1.equals(o2);
   }

   public boolean equals(Object o)
   {
      if (! (o instanceof Person))
         return false;

      if (o == this)
         return true;

      Person other = (Person) o;
      return other.age == age && equals(other.name, name) && equals(other.hobbies, hobbies) && equals(other.address, address)
         && equals(other.skills, skills) && equals(other.languages, languages) && equals(other.currentStatus, currentStatus)
         && equals(other.medication, medication);
   }

   public int hashCode()
   {
      int result = 629 * name.hashCode() * 37 * age;

      if (hobbies != null)
         result = 37 * result + hobbies.hashCode();

      if (address != null)
         result = 37 * result + address.hashCode();

      if (skills != null)
         result = 37 * result + skills.hashCode();

      if (languages != null)
         result = 37 * result + languages.hashCode();

      if (currentStatus != null)
         result = 37 * result + currentStatus.hashCode();

      if (medication != null)
         result = 37 * medication.hashCode();

      return result;
   }

   public String print(Map<?, ?> m)
   {
      StringBuffer sb = new StringBuffer();
      Map.Entry<?, ?> entry;
      if (m != null)
      {
         for (Iterator<?> it = m.entrySet().iterator(); it.hasNext();)
         {
            entry = (Map.Entry<?, ?>) it.next();
            sb.append(entry.getKey()).append(": ").append(entry.getValue());
            sb.append("\n");
         }
      }
      return sb.toString();
   }
}
