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.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 		// JInterface rhs = (JInterface) obj;
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 }