View Javadoc
1   /*
2    *  Copyright 2012 Chris Pheby
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.jadira.scanner.classpath.types;
17  
18  import java.util.HashSet;
19  import java.util.Set;
20  
21  import javassist.bytecode.annotation.Annotation;
22  
23  import org.apache.commons.lang3.builder.EqualsBuilder;
24  import org.apache.commons.lang3.builder.HashCodeBuilder;
25  import org.apache.commons.lang3.builder.ToStringBuilder;
26  import org.apache.commons.lang3.builder.ToStringStyle;
27  import org.jadira.scanner.classpath.ClasspathResolver;
28  import org.jadira.scanner.classpath.visitor.IntrospectionVisitor;
29  import org.jadira.scanner.core.exception.ClasspathAccessException;
30  import org.jadira.scanner.core.helper.JavassistAnnotationsHelper;
31  
32  public class JAnnotation<A extends java.lang.annotation.Annotation> extends JType {
33  
34      private JElement enclosingElement;
35  
36      protected JAnnotation(Annotation annotation, JElement enclosingElement, ClasspathResolver resolver) {
37          super(findClassFile(annotation.getTypeName(), resolver), resolver);
38          this.enclosingElement = enclosingElement;
39      }
40  
41      protected JAnnotation(java.lang.annotation.Annotation annotation, JElement enclosingElement, ClasspathResolver resolver) {
42          super(findClassFile(annotation.annotationType().getName(), resolver), resolver);
43          this.enclosingElement = enclosingElement;
44      }
45      
46      public JClass getSuperType() throws ClasspathAccessException {
47  
48          final String superClassFile = getClassFile().getSuperclass();
49          return JClass.getJClass(superClassFile, getResolver());
50      }
51      
52      public Class<?> getActualSuperType() throws ClasspathAccessException {
53          return getSuperType().getActualClass();
54      }
55  
56      public static JAnnotation<?> getJAnnotation(Annotation nextAnnotation, JElement enclosingElement, ClasspathResolver resolver) {
57          return new JAnnotation<java.lang.annotation.Annotation>(nextAnnotation, enclosingElement, resolver);
58      }
59  
60      public static <A extends java.lang.annotation.Annotation> JAnnotation<A> getJAnnotation(A nextAnnotation, JElement enclosingElement, ClasspathResolver resolver) {
61          return new JAnnotation<A>(nextAnnotation, enclosingElement, resolver);
62      }
63  
64      public A getActualAnnotation() throws ClasspathAccessException {
65  
66          final java.lang.annotation.Annotation[] annotations;
67          if (enclosingElement instanceof JOperation) {
68              annotations = JavassistAnnotationsHelper.getAnnotationsForMethod(((JOperation)enclosingElement).getMethodInfo());
69          } else if (enclosingElement instanceof JField) {
70              annotations = JavassistAnnotationsHelper.getAnnotationsForFieldInfo(((JField)enclosingElement).getFieldInfo());
71          } else if (enclosingElement instanceof JParameter) {
72              annotations = JavassistAnnotationsHelper.getAnnotationsForMethodParameter(((JMethod)enclosingElement).getMethodInfo(), ((JParameter)enclosingElement).getIndex());
73          } else if (enclosingElement instanceof JPackage) {
74              annotations = ((JPackage)enclosingElement).getAnnotationsForPackage();
75          } else {
76              annotations = JavassistAnnotationsHelper.getAnnotationsForClass(((JType)enclosingElement).getClassFile());
77          }
78  
79          String requiredName = getActualClass().getName();
80          for (java.lang.annotation.Annotation next : annotations) {
81              String nextName = next.annotationType().getName();
82              if (nextName.equals(requiredName)) {
83                  @SuppressWarnings("unchecked") final A retVal = (A) next;
84                  return retVal;
85              }
86          }
87          throw new ClasspathAccessException("Could not find annotation of type " + getActualClass() + " for " + enclosingElement);
88      }
89  
90      @Override
91      public Set<JAnnotation<?>> getAnnotations() throws ClasspathAccessException {
92  
93          Set<JAnnotation<?>> retVal = new HashSet<JAnnotation<?>>();
94          java.lang.annotation.Annotation[] anns = JavassistAnnotationsHelper.getAnnotationsForClass(getClassFile());
95          for(java.lang.annotation.Annotation next : anns) {
96              retVal.add(JAnnotation.getJAnnotation(next, this, getResolver()));
97          }
98          return retVal;
99      }
100 
101     @Override
102     public JPackage getPackage() throws ClasspathAccessException {
103         return JPackage.getJPackage(getName().substring(0, getName().lastIndexOf(".")), getResolver());
104     }
105 
106     @Override
107     public Class<A> getActualClass() throws ClasspathAccessException {
108 
109         @SuppressWarnings("unchecked")
110         Class<A> retVal = (Class<A>) getResolver().loadClass(getClassFile().getName());
111         return retVal;
112     }
113 
114     @Override
115     public void acceptVisitor(IntrospectionVisitor visitor) {
116         visitor.visit(this);
117     }
118 
119     @Override
120     public JElement getEnclosingElement() {
121         return enclosingElement;
122     }
123     
124     @Override
125     public String toString() {
126     	
127     	ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
128     	builder.append("name", getName());
129     	builder.append("enclosingElement", getEnclosingElement());
130     	
131     	return builder.toString();
132     }
133 
134     @Override
135 	public boolean equals(Object obj) {
136 		if (obj == null) {
137 			return false;
138 		}
139 		if (obj == this) {
140 			return true;
141 		}
142 		if (obj.getClass() != getClass()) {
143 			return false;
144 		}
145 		JAnnotation<?> rhs = (JAnnotation<?>) obj;
146 		return new EqualsBuilder()
147 			 	.appendSuper(super.equals(obj))
148 				.append(enclosingElement, rhs.enclosingElement).isEquals();
149 	}
150 
151     @Override
152 	public int hashCode() {
153 		return new HashCodeBuilder(11, 47).append(super.hashCode())
154 				.append(enclosingElement).toHashCode();
155 	}
156 }