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.io.File;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 import javassist.bytecode.AnnotationsAttribute;
26 import javassist.bytecode.ClassFile;
27 import javassist.bytecode.MethodInfo;
28 import javassist.bytecode.annotation.Annotation;
29
30 import org.apache.commons.lang3.builder.EqualsBuilder;
31 import org.apache.commons.lang3.builder.HashCodeBuilder;
32 import org.jadira.scanner.classpath.ClasspathResolver;
33 import org.jadira.scanner.classpath.filter.JClassImplementsFilter;
34 import org.jadira.scanner.classpath.filter.JElementTypeFilter;
35 import org.jadira.scanner.classpath.filter.JTypeSubTypeOfFilter;
36 import org.jadira.scanner.classpath.projector.ClasspathProjector;
37 import org.jadira.scanner.classpath.visitor.IntrospectionVisitor;
38 import org.jadira.scanner.core.api.Projector;
39 import org.jadira.scanner.core.exception.ClasspathAccessException;
40
41 public class JInterface extends JType {
42
43 private static final Projector<File> CLASSPATH_PROJECTOR = ClasspathProjector.SINGLETON;
44
45 protected JInterface(String name, ClasspathResolver resolver) throws ClasspathAccessException {
46 this(findClassFile(name, resolver), resolver);
47 }
48
49 protected JInterface(ClassFile classFile, ClasspathResolver resolver) {
50 super(classFile, resolver);
51 if (!classFile.isInterface() || (classFile.getSuperclass().equals("java.lang.annotation.Annotation"))) {
52 throw new IllegalArgumentException("Argument was not interface: " + classFile.getName());
53 }
54 }
55
56
57 public static JInterface getJInterface(String name, ClasspathResolver resolver) throws ClasspathAccessException {
58 return new JInterface(name, resolver);
59 }
60
61 public static JInterface getJInterface(ClassFile classFile, ClasspathResolver resolver) {
62 return new JInterface(classFile, resolver);
63 }
64
65 public List<JInterface> getSuperInterfaces() throws ClasspathAccessException {
66
67 final List<JInterface> retVal = new ArrayList<JInterface>();
68 String[] interfaces = getClassFile().getInterfaces();
69
70 for (String next : interfaces) {
71 retVal.add(JInterface.getJInterface(next, getResolver()));
72 }
73 return retVal;
74 }
75
76 public List<Class<?>> getActualSuperInterfaces() throws ClasspathAccessException {
77
78 List<Class<?>> classes = new ArrayList<Class<?>>();
79 for (JInterface next : getSuperInterfaces()) {
80 classes.add(next.getActualClass());
81 }
82 return classes;
83 }
84
85 public List<JMethod> getMethods() {
86
87 final List<JMethod> retVal = new ArrayList<JMethod>();
88 @SuppressWarnings("unchecked")
89 final List<MethodInfo> methods = (List<MethodInfo>) getClassFile().getMethods();
90
91 for (MethodInfo next : methods) {
92 if (next.isMethod()) {
93 retVal.add(JMethod.getJMethod(next, this, getResolver()));
94 }
95 }
96 return retVal;
97 }
98
99 public Class<?> getActualInterface() throws ClasspathAccessException {
100
101 return getResolver().loadClass(getClassFile().getName());
102 }
103
104 @Override
105 public Set<JAnnotation<?>> getAnnotations() throws ClasspathAccessException {
106
107 AnnotationsAttribute visible = (AnnotationsAttribute) getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
108 AnnotationsAttribute invisible = (AnnotationsAttribute) getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
109
110 Set<JAnnotation<?>> annotations = new HashSet<JAnnotation<?>>();
111
112 List<Annotation> annotationsList = new ArrayList<Annotation>();
113 if (visible != null) {
114 annotationsList.addAll(Arrays.asList(visible.getAnnotations()));
115 }
116 if (invisible != null) {
117 annotationsList.addAll(Arrays.asList(invisible.getAnnotations()));
118 }
119
120 for (Annotation nextAnnotation : annotationsList) {
121 annotations.add(JAnnotation.getJAnnotation(nextAnnotation, this, getResolver()));
122 }
123
124 return annotations;
125 }
126
127 @Override
128 public JPackage getPackage() throws ClasspathAccessException {
129
130 String fqClassName = getClassFile().getName();
131
132 String packageName;
133 if (fqClassName.contains(".")) {
134 packageName = fqClassName.substring(0, fqClassName.lastIndexOf('.'));
135 } else {
136 packageName = "";
137 }
138
139 return JPackage.getJPackage(packageName, getResolver());
140 }
141
142 @Override
143 public Class<?> getActualClass() throws ClasspathAccessException {
144 return getActualInterface();
145 }
146
147 public Set<JInterface> getSubInterfaces() {
148
149 Set<JInterface> retVal = new HashSet<JInterface>();
150 List<? extends ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, CLASSPATH_PROJECTOR, new JTypeSubTypeOfFilter(this.getActualClass()), new JElementTypeFilter(JInterface.class));
151 for (ClassFile classFile : classes) {
152 retVal.add(JInterface.getJInterface(classFile, getResolver()));
153 }
154 return retVal;
155 }
156
157 public Set<JClass> getImplementingClasses() {
158
159 Set<JClass> retVal = new HashSet<JClass>();
160 List<? extends ClassFile> classes = getResolver().getClassFileResolver().resolveAll(null, CLASSPATH_PROJECTOR, new JClassImplementsFilter(this.getActualClass()), new JElementTypeFilter(JClass.class));
161 for (ClassFile classFile : classes) {
162 retVal.add(JClass.getJClass(classFile, getResolver()));
163 }
164 return retVal;
165 }
166
167 @Override
168 public void acceptVisitor(IntrospectionVisitor visitor) throws ClasspathAccessException {
169 visitor.visit(this);
170
171 for (JInterface next : getSuperInterfaces()) {
172 next.acceptVisitor(visitor);
173 }
174 for (JMethod next : getMethods()) {
175 next.acceptVisitor(visitor);
176 }
177 for (JAnnotation<?> next : getAnnotations()) {
178 next.acceptVisitor(visitor);
179 }
180 }
181
182 @Override
183 public JPackage getEnclosingElement() {
184 return getPackage();
185 }
186
187 @Override
188 public boolean equals(Object obj) {
189 if (obj == null) {
190 return false;
191 }
192 if (obj == this) {
193 return true;
194 }
195 if (obj.getClass() != getClass()) {
196 return false;
197 }
198
199 return new EqualsBuilder()
200 .appendSuper(super.equals(obj))
201 .isEquals();
202 }
203
204 @Override
205 public int hashCode() {
206 return new HashCodeBuilder(11, 47).append(super.hashCode())
207 .toHashCode();
208 }
209 }