1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.scanner.classpath.types;
17
18 import java.util.Arrays;
19 import java.util.HashSet;
20 import java.util.Set;
21
22 import javassist.bytecode.MethodInfo;
23 import javassist.bytecode.ParameterAnnotationsAttribute;
24 import javassist.bytecode.annotation.Annotation;
25
26 import org.apache.commons.lang3.builder.EqualsBuilder;
27 import org.apache.commons.lang3.builder.HashCodeBuilder;
28 import org.jadira.scanner.classpath.ClasspathResolver;
29 import org.jadira.scanner.classpath.visitor.IntrospectionVisitor;
30 import org.jadira.scanner.core.exception.ClasspathAccessException;
31 import org.jadira.scanner.core.helper.JavassistMethodInfoHelper;
32
33 public class JParameter extends JVariable {
34
35 private JOperation enclosingOperation;
36 private int index;
37
38 protected JParameter(int index, JOperation enclosingOperation, ClasspathResolver resolver) {
39 super(JavassistMethodInfoHelper.getMethodParamNames(enclosingOperation.getMethodInfo())[index], resolver);
40 this.enclosingOperation = enclosingOperation;
41 this.index = index;
42 }
43
44 public static JParameter getJParameter(int index, JOperation enclosingOperation, ClasspathResolver resolver) {
45 return new JParameter(index, enclosingOperation, resolver);
46 }
47
48 public JOperation getEnclosingMethod() {
49 return enclosingOperation;
50 }
51
52 @Override
53 public JType getEnclosingType() {
54 return enclosingOperation.getEnclosingType();
55 }
56
57 @Override
58 public Set<JAnnotation<?>> getAnnotations() throws ClasspathAccessException {
59
60 ParameterAnnotationsAttribute paramsVisible = (ParameterAnnotationsAttribute) enclosingOperation.getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
61 ParameterAnnotationsAttribute paramsInvisible = (ParameterAnnotationsAttribute) enclosingOperation.getMethodInfo().getAttribute(ParameterAnnotationsAttribute.invisibleTag);
62
63 final Set<JAnnotation<?>> retVal = new HashSet<JAnnotation<?>>();
64 if (paramsVisible != null && paramsVisible.getAnnotations() != null) {
65 for (Annotation anns : paramsVisible.getAnnotations()[index]) {
66 retVal.add(JAnnotation.getJAnnotation(anns, this, getResolver()));
67 }
68 }
69 if (paramsInvisible != null && paramsInvisible.getAnnotations() != null) {
70 for (Annotation anns : paramsInvisible.getAnnotations()[index]) {
71 retVal.add(JAnnotation.getJAnnotation(anns, this, getResolver()));
72 }
73 }
74
75 return retVal;
76 }
77
78 @Override
79 public JType getType() throws ClasspathAccessException {
80
81 Class<?> clazz;
82 if (enclosingOperation instanceof JConstructor || enclosingOperation instanceof JMethod) {
83 MethodInfo methodInfo = ((JOperation) enclosingOperation).getMethodInfo();
84 String[] paramTypeNames = JavassistMethodInfoHelper.getMethodParamTypeNames(methodInfo);
85 clazz = decodeFieldType(paramTypeNames[getIndex()]);
86
87 } else {
88 throw new ClasspathAccessException("Invalid parameter index: " + index);
89 }
90
91 if (clazz.isAnnotation()) {
92 try {
93 return new JAnnotation<java.lang.annotation.Annotation>((java.lang.annotation.Annotation) clazz.newInstance(), this, getResolver());
94 } catch (InstantiationException e) {
95 throw new ClasspathAccessException("Problem instantiating annotation: " + e.getMessage(), e);
96 } catch (IllegalAccessException e) {
97 throw new ClasspathAccessException("Problem accessing annotation: " + e.getMessage(), e);
98 }
99 } else if (clazz.isInterface()) {
100 return new JInterface(clazz.getName(), getResolver());
101 } else {
102 JClass jClass = new JClass(clazz.getName(), getResolver());
103 return jClass;
104 }
105 }
106
107 public int getIndex() {
108 return index;
109 }
110
111 @Override
112 public void acceptVisitor(IntrospectionVisitor visitor) throws ClasspathAccessException {
113 visitor.visit(this);
114
115 for (JAnnotation<?> next : getAnnotations()) {
116 next.acceptVisitor(visitor);
117 }
118 }
119
120 @Override
121 public JOperation getEnclosingElement() {
122 return enclosingOperation;
123 }
124
125 @Override
126 public boolean equals(Object obj) {
127 if (obj == null) {
128 return false;
129 }
130 if (obj == this) {
131 return true;
132 }
133 if (obj.getClass() != getClass()) {
134 return false;
135 }
136 JParameter rhs = (JParameter) obj;
137 return new EqualsBuilder()
138 .appendSuper(super.equals(obj))
139 .append(enclosingOperation, rhs.enclosingOperation).isEquals();
140 }
141
142 @Override
143 public int hashCode() {
144 return new HashCodeBuilder(11, 47).append(super.hashCode())
145 .append(enclosingOperation).toHashCode();
146 }
147
148
149 private Class<?> decodeFieldType(String componentType) {
150
151 char type = componentType.charAt(0);
152 String fieldContent = componentType.substring(1);
153
154 switch (type) {
155
156 case 'L':
157 return getResolver().loadClass(fieldContent.replace('/', '.'));
158
159 case 'B':
160 return Byte.class;
161
162 case 'C':
163 return Character.class;
164
165 case 'D':
166 return Double.class;
167
168 case 'F':
169 return Float.class;
170
171 case 'I':
172 return Integer.class;
173
174 case 'J':
175 return Long.class;
176
177 case 'S':
178 return Short.class;
179
180 case 'Z':
181 return Boolean.class;
182
183 case '[':
184 return Arrays.class;
185 }
186 return null;
187 }
188 }