Package org.jboss.seam.remoting

Source Code of org.jboss.seam.remoting.AnnotationsParser$AnyQualifier

package org.jboss.seam.remoting;

import java.io.StringReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.util.AnnotationLiteral;

import org.jboss.seam.remoting.annotationparser.AnnotationParser;
import org.jboss.seam.remoting.annotationparser.ParseException;
import org.jboss.seam.remoting.annotationparser.syntaxtree.AnnotationsUnit;
import org.jboss.seam.remoting.annotationparser.syntaxtree.BooleanLiteral;
import org.jboss.seam.remoting.annotationparser.syntaxtree.ClassOrInterfaceType;
import org.jboss.seam.remoting.annotationparser.syntaxtree.Literal;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MarkerAnnotation;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValue;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValuePair;
import org.jboss.seam.remoting.annotationparser.syntaxtree.MemberValuePairs;
import org.jboss.seam.remoting.annotationparser.syntaxtree.Name;
import org.jboss.seam.remoting.annotationparser.syntaxtree.Node;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeListOptional;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeOptional;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeSequence;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NodeToken;
import org.jboss.seam.remoting.annotationparser.syntaxtree.NormalAnnotation;
import org.jboss.seam.remoting.annotationparser.syntaxtree.SingleMemberAnnotation;
import org.jboss.seam.remoting.annotationparser.visitor.DepthFirstVisitor;

/**
* Parses a comma-separated list of annotation expressions and produces an
* array of Annotation instances.
* @author Shane Bryzak
*/
public class AnnotationsParser extends DepthFirstVisitor
{   
   protected class AnnotationMetadata
   {
      private Class<? extends Annotation> annotationType;
      private Map<String,Object> memberValues = new HashMap<String,Object>();
     
      public AnnotationMetadata(String name)
      {
         this.annotationType = determineAnnotationType(name, beanType);
      }     
     
      public void addMemberValue(String name, Object value)
      {
         memberValues.put(name, value);
      }
     
      public Map<String,Object> getMemberValues()
      {
         return memberValues;
      }
     
      public Class<? extends Annotation> getAnnotationType()
      {
         return annotationType;
      }
   }
  
   @SuppressWarnings("all")
   private class AnyQualifier extends AnnotationLiteral<Any> implements Any {};

   private Class<?> beanType;
   private BeanManager beanManager;
   private List<AnnotationMetadata> meta = new ArrayList<AnnotationMetadata>();
  
   private Annotation[] annotations;
  
   public AnnotationsParser(Class<?> beanType, String declaration, BeanManager beanManager)
   {
      this.beanType = beanType;
      this.beanManager = beanManager;
     
      // TODO cache the results somewhere
     
      AnnotationParser parser = new AnnotationParser(new StringReader(declaration));
     
      try
      {
         Node root = parser.AnnotationsUnit();
         root.accept(this);
      }
      catch (ParseException e)
      {
         throw new IllegalArgumentException(
               "Error while parsing annotation declaration: " + declaration, e);
      }
     
      annotations = new Annotation[meta.size()];
     
      for (int i = 0; i < meta.size(); i++)
      {
         AnnotationMetadata ann = meta.get(i);
         InvocationHandler handler = new AnnotationInvocationHandler(
               (Class<? extends Annotation>) ann.getAnnotationType(), ann.getMemberValues());
         annotations[i] = (Annotation) Proxy.newProxyInstance(
               ann.getAnnotationType().getClassLoader(),
               new Class[] {ann.getAnnotationType()}, handler);
      }
     
      meta = null;
   }
  
   public Annotation[] getAnnotations()
   {
      return annotations;
   }
  
   @SuppressWarnings("unchecked")
   private Class<? extends Annotation> determineAnnotationType(String name, Class<?> beanType)
   {
      try
      {
         return (Class<? extends Annotation>) Class.forName(name);
      }
      catch (ClassNotFoundException e)
      {
         // Iterate through the annotations on the bean type and look for a simple name match
         for (Annotation beanAnnotation : beanType.getAnnotations())
         {
            if (name.equals(beanAnnotation.annotationType().getSimpleName()))
            {
               return beanAnnotation.annotationType();
            }
         }
        
         // Couldn't find the annotation on the bean type itself - let's look at all beans
         // with the same type
         Set<Bean<?>> beans = beanManager.getBeans(beanType, new AnyQualifier());
         for (Bean<?> bean : beans)
         {
            for (Annotation beanAnnotation : bean.getBeanClass().getAnnotations())
            {
               if (name.equals(beanAnnotation.annotationType().getSimpleName()))
               {
                  return beanAnnotation.annotationType();
               }
            }
         }       
        
         if ("Default".equals(name))
         {
            return Default.class;
         }
         else if ("Any".equals(name))
         {
            return Any.class;
         }
        
         return null;        
      }
   }
  
   @Override
   public void visit(AnnotationsUnit node)
   {
      List<org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation> annotations =
         new ArrayList<org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation>();
     
      // TODO messy! turn this into a recursive function
     
      NodeOptional n = (NodeOptional) node.f0;
      if (n.present())
      {
         if (n.node instanceof NodeSequence)
         {
            NodeSequence ns = (NodeSequence) n.node;
            {
               for (Node nsNode : ns.nodes)
               {
                  if (nsNode instanceof org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation)
                  {
                     annotations.add((org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation) nsNode);
                  }
                  else if (nsNode instanceof NodeListOptional)
                  {
                     NodeListOptional nlo = (NodeListOptional) nsNode;
                     if (nlo.present())
                     {
                        for (Node nloNode : nlo.nodes)
                        {
                           if (nloNode instanceof NodeSequence)
                           {
                              for (Node cn : ((NodeSequence) nloNode).nodes)
                              {
                                 if (cn instanceof org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation)
                                 {
                                    annotations.add((org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation) cn);
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      }
     
      for (org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation a : annotations)
      {
         processAnnotation(a);
      }
     
      super.visit(node);
   }
  
   private void processAnnotation(org.jboss.seam.remoting.annotationparser.syntaxtree.Annotation node)
   {          
      if (node.f0.choice instanceof MarkerAnnotation)
      {
         meta.add(new AnnotationMetadata(extractName(((MarkerAnnotation) node.f0.choice).f1)));
      }
      else if (node.f0.choice instanceof NormalAnnotation)
      {
         NormalAnnotation ann = (NormalAnnotation) node.f0.choice;
         AnnotationMetadata metadata = new AnnotationMetadata(extractName(ann.f1));
        
         if (ann.f3.present() && ann.f3.node instanceof MemberValuePairs)
         {
            MemberValuePairs mvp = (MemberValuePairs) ann.f3.node;
            extractMemberValue(metadata, mvp.f0.f0.tokenImage, mvp.f0.f2);
           
            if (mvp.f1.present())
            {
               for (Node n : mvp.f1.nodes)
               {
                  if (n instanceof NodeSequence)
                  {
                     for (Node nsn : ((NodeSequence) n).nodes)
                     {                       
                        if (nsn instanceof MemberValuePair)
                        {
                           MemberValuePair p = (MemberValuePair) nsn;
                           extractMemberValue(metadata, p.f0.tokenImage, p.f2);
                        }                       
                     }
                  }
               }
            }
         }
         meta.add(metadata);
      }
      else if (node.f0.choice instanceof SingleMemberAnnotation)
      {
         AnnotationMetadata metadata = new AnnotationMetadata(
               extractName(((SingleMemberAnnotation) node.f0.choice).f1));
         extractMemberValue(metadata, "value", ((SingleMemberAnnotation) node.f0.choice).f3);
         meta.add(metadata);
      }
        
   }
  
   private void extractMemberValue(AnnotationMetadata metadata, String memberName,
         MemberValue memberValue)
   {
      Class<?> memberType = null;
     
      for (Method m : metadata.getAnnotationType().getMethods())
      {
         if (memberName.equals(m.getName()))
         {
            memberType = m.getReturnType();
            break;
         }
      }
     
      if (memberType == null)
      {
         throw new RuntimeException("Annotation member " + memberName +
               " not found on annotation type " + metadata.getAnnotationType().getName());
      }
     
      Object value = null;
     
      switch (memberValue.f0.which)
      {       
         // TODO add the missing conversions
         case 0: // Annotation 
            break;
         case 1: // MemberValueArray
            // not supported - array member values are non-binding
            break;
         case 2: // Literal
            value = convertLiteral((Literal) memberValue.f0.choice);
            break;
         case 3: // ClassOrInterfaceType
            value = convertClassOrInterfaceType(
                  (ClassOrInterfaceType) memberValue.f0.choice, memberType);
            break;
      }
     
      metadata.addMemberValue(memberName, value);
   }
  
   private Object convertLiteral(Literal literal)
   {    
      switch (literal.f0.which)
      {
         case 0: // <INTEGER_LITERAL>
            return Integer.parseInt(((NodeToken) literal.f0.choice).tokenImage);
         case 1: // <FLOATING_POINT_LITERAL>
            return Float.parseFloat(((NodeToken) literal.f0.choice).tokenImage);
         case 2: // <CHARACTER_LITERAL>
            return ((NodeToken) literal.f0.choice).tokenImage.charAt(1); // ignore the single quotes
         case 3: // <STRING_LITERAL>
            String stringVal = ((NodeToken) literal.f0.choice).tokenImage;
            return stringVal.substring(1, stringVal.length() - 1); // strip the double quotes
         case 4: // BooleanLiteral()
            return "true".equals(((NodeToken) ((BooleanLiteral) literal.f0.choice).f0.choice).tokenImage);
         case 5: // NullLiteral()
            return null;
      }     
      return null;
   }
  
   private Object convertClassOrInterfaceType(ClassOrInterfaceType node, Class<?> memberType)
   {
      StringBuilder sb = new StringBuilder();
      sb.append(node.f0.tokenImage);
     
      if (node.f1.present())
      {
         for (Node n : node.f1.nodes)
         {
            if (n instanceof NodeSequence)
            {
               for (Node nsn : ((NodeSequence) n).nodes)
               {
                  if (nsn instanceof NodeToken)
                  {
                     sb.append(((NodeToken) nsn).tokenImage);
                  }
               }
            }
         }
      }
     
      String className = sb.toString();
     
      if (memberType.isEnum())
      {
         for (Object e : memberType.getEnumConstants())
         {
            if (className.equals(((Enum<?>) e).name())) return e;
         }
      
         throw new IllegalArgumentException(
               "Invalid enum specified for annotation member value: " + className);
      }
      else
      {
         try
         {
            return Class.forName(className);
         }
         catch (ClassNotFoundException e)
         {
            if (!className.startsWith("java.lang."))
            {
               // try finding the class in the java.lang package
               try
               {
                  return Class.forName("java.lang." + className);
               }
               catch (ClassNotFoundException e1) { }           
            }
  
            throw new IllegalArgumentException(
                  "Invalid class name specified for annotation member value: " + className);
         }
      }
   }
     
   private String extractName(Name name)
   {
      StringBuilder sb = new StringBuilder();
     
      sb.append(name.f0.tokenImage);
     
      NodeListOptional nodeList = ((NodeListOptional) name.f1);
      if (nodeList.present())
      {
         for (Node node : nodeList.nodes)
         {
            if (node instanceof NodeSequence)
            {
               for (Node n : ((NodeSequence) node).nodes)
               {
                  if (n instanceof NodeToken)
                  {
                     sb.append(((NodeToken) n).tokenImage);
                  }
               }
            }
         }
      }     
     
      return sb.toString();
   }
}
TOP

Related Classes of org.jboss.seam.remoting.AnnotationsParser$AnyQualifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.