/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/ 
package org.jboss.test.annotation.factory.test;

import java.lang.annotation.Annotation;
import java.io.Serializable;

import org.jboss.annotation.factory.AnnotationCreator;
import org.jboss.annotation.factory.AnnotationValidationException;
import org.jboss.test.ContainerTest;
import org.jboss.test.annotation.factory.support.Complex;
import org.jboss.test.annotation.factory.support.MyEnum;
import org.jboss.test.annotation.factory.support.Name;
import org.jboss.test.annotation.factory.support.NameDefaults;
import org.jboss.test.annotation.factory.support.Simple;
import org.jboss.test.annotation.factory.support.SimpleValue;
import org.jboss.test.annotation.factory.support.NameImpl;

/**
 * 
 * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
 * @version $Revision: 80468 $
 */

public abstract class AnnotationCreatorTest extends ContainerTest
{
   public AnnotationCreatorTest(String name)
   {
      super(name);
   }
   
   public void testSimple() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.Simple";
      Annotation annotation = (Annotation)AnnotationCreator.createAnnotation(expr, Simple.class);
      assertEquals(Simple.class, annotation.annotationType());
   }
   
   public void testSimpleValue() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.SimpleValue(\"Test\")";
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, SimpleValue.class);
      assertEquals(SimpleValue.class, annotation.annotationType());
      assertEquals("Test", ((SimpleValue)annotation).value());
   }
   
   public void testSimpleValueWithPropertyReplacement() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.SimpleValue(\"${value1}\")";
      System.setProperty("value1", "Test");
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, SimpleValue.class, true);
      assertEquals(SimpleValue.class, annotation.annotationType());
      assertEquals("Test", ((SimpleValue)annotation).value());
   }
   
   public void testSimpleValueWithPropertyReplacementFromProperties() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.SimpleValue(\"${value1}\")";
      System.setProperty("value1", "Test");
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, SimpleValue.class, System.getProperties());
      assertEquals(SimpleValue.class, annotation.annotationType());
      assertEquals("Test", ((SimpleValue)annotation).value());
   }

   public void testComplex() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.Complex(ch='a', string=\"Test123\", flt=9.9, dbl=123456789.99, shrt=1, lng=987654321, integer=123, bool=true, annotation=@org.jboss.test.annotation.factory.support.SimpleValue(\"Yes\"), array={\"Test\", \"123\"}, clazz=java.lang.Long.class, enumVal=org.jboss.test.annotation.factory.support.MyEnum.TWO, primitiveArray={1,2,3})";
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, Complex.class);
      assertEquals(Complex.class, annotation.annotationType());
      Complex complex = (Complex)annotation;
      assertEquals('a', complex.ch());
      assertEquals("Test123", complex.string());
      assertEquals(9,9, complex.flt());
      assertEquals(123456789.99, complex.dbl());
      assertEquals(1, complex.shrt());
      assertEquals(987654321, complex.lng());
      assertEquals(123, complex.integer());
      assertEquals(true, complex.bool());
      assertEquals(Long.class, complex.clazz());
      assertEquals("Yes", complex.annotation().value());
      assertEquals(new String[]{"Test", "123"}, complex.array());
      assertEquals(MyEnum.TWO, complex.enumVal());
      assertArrays(new int[]{1, 2, 3}, complex.primitiveArray());
   }
   
   public void testComplexWithPropertyReplacement() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.Complex(ch='${ch}', string=\"${string}\", flt=${flt}, dbl=${dbl}, shrt=${shrt}, " +
      		"lng=${lng}, integer=${integer}, bool=${bool}, annotation=${annotation}, array=${array}, clazz=${clazz}, enumVal=${enumVal}, primitiveArray=${primitiveArray})";
      
      System.setProperty("ch", "a");
      System.setProperty("string", "Test123");
      System.setProperty("flt", "9.9");
      System.setProperty("dbl", "123456789.99");
      System.setProperty("shrt", "1");
      System.setProperty("lng", "987654321");
      System.setProperty("integer", "123");
      System.setProperty("bool", "true");
      System.setProperty("annotation", "@org.jboss.test.annotation.factory.support.SimpleValue(\"Yes\")");
      System.setProperty("array", "{\"Test\", \"123\"}");
      System.setProperty("clazz", "java.lang.Long.class");
      System.setProperty("enumVal", "org.jboss.test.annotation.factory.support.MyEnum.TWO");
      System.setProperty("primitiveArray", "{1, 2, 3}");
      
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, Complex.class, true);
      assertEquals(Complex.class, annotation.annotationType());
      Complex complex = (Complex)annotation;
      assertEquals('a', complex.ch());
      assertEquals("Test123", complex.string());
      assertEquals(9,9, complex.flt());
      assertEquals(123456789.99, complex.dbl());
      assertEquals(1, complex.shrt());
      assertEquals(987654321, complex.lng());
      assertEquals(123, complex.integer());
      assertEquals(true, complex.bool());
      assertEquals(Long.class, complex.clazz());
      assertEquals("Yes", complex.annotation().value());
      assertEquals(new String[]{"Test", "123"}, complex.array());
      assertEquals(MyEnum.TWO, complex.enumVal());
      assertArrays(new int[]{1, 2, 3}, complex.primitiveArray());
   }

   public void testSerializable() throws Exception
   {
      String expr = "@org.jboss.test.annotation.factory.support.Complex(ch='a', string=\"Test123\", flt=9.9, dbl=123456789.99, shrt=1, lng=987654321, integer=123, bool=true, annotation=@org.jboss.test.annotation.factory.support.SimpleValue(\"Yes\"), array={\"Test\", \"123\"}, clazz=java.lang.Long.class, enumVal=org.jboss.test.annotation.factory.support.MyEnum.TWO, primitiveArray={1,2,3})";
      Annotation annotation  = (Annotation)AnnotationCreator.createAnnotation(expr, Complex.class);
      assertInstanceOf(annotation, Serializable.class);
      byte[] bytes = serialize((Serializable)annotation);
      Object desAnn = deserialize(bytes);
      assertEquals(annotation, desAnn);
   }

   public void testMissingAttributeAndNoDefault() throws Exception
   {
      try
      {
         String expr = "@org.jboss.test.annotation.factory.support.SimpleValue";
         AnnotationCreator.createAnnotation(expr, SimpleValue.class);
         fail("Should have picked up on missing attribute");
      }
      catch (AnnotationValidationException expected)
      {
      }
   }

   public void testEquals()
      throws Exception
   {
      String expr = "@"+Name.class.getName() + "(type=\"type\",subtype=\"subtype\")";
      Name n0 = (Name) AnnotationCreator.createAnnotation(expr, Name.class);
      getLog().debug("n0: "+n0);
      Name n1 = NameDefaults.class.getAnnotation(Name.class);
      getLog().debug("n1: "+n1);
      assertEquals(n0, n1);
      assertEquals(n1, n0);

      Name defaultName = NameDefaults.defaultNameType();
      getLog().debug("defaultName: "+defaultName);
      // The jdk annotation should not equal the defaultName
      assertFalse(n1+" != "+defaultName, n1.equals(defaultName));
      assertFalse(defaultName+" != "+n1, defaultName.equals(n1));
      // The AnnotationCreator annotation should not equal the defaultName
      assertFalse(n0+" != "+defaultName, n0.equals(defaultName));
      assertFalse(defaultName+" != "+n0, defaultName.equals(n0));

      Name n2 = new NameImpl("type", "subtype");
      getLog().debug("n2: " + n2);
      assertEquals(n0, n2);
      assertEquals(n2, n0);
      assertEquals(n1, n2);
      assertEquals(n2, n1);

      Name n3 = new NameImpl();
      assertFalse(n0  + "!=" +  n3, n0.equals(n3));
      assertFalse(n3  + "!=" +  n0, n3.equals(n0));
      assertFalse(n1  + "!=" +  n3, n1.equals(n3));
      assertFalse(n3  + "!=" +  n1, n3.equals(n1));            
   }
}
