/*******************************************************************************
* Copyright (c) 2007, 2014 Spring IDE Developers
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.core.type.asm;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.asm.AnnotationVisitor;
import org.springframework.asm.Attribute;
import org.springframework.asm.ClassVisitor;
import org.springframework.asm.FieldVisitor;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.springframework.asm.SpringAsmInfo;
import org.springframework.ide.eclipse.core.type.ClassMetadata;
import org.springframework.util.ClassUtils;
/**
* ASM class visitor which looks only for the class name and implemented types,
* exposing them through the {@link org.springframework.core.type.ClassMetadata}
* interface.
*
* @author Rod Johnson
* @author Costin Leau
* @author Mark Fisher
* @author Ramnivas Laddad
* @author Martin Lippert
* @since 2.5
*/
public class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {
private String className;
private boolean isInterface;
private boolean isAnnotation;
private boolean isAbstract;
private boolean isFinal;
private String enclosingClassName;
private boolean independentInnerClass;
private String superClassName;
private String[] interfaces;
private Set<String> memberClassNames = new LinkedHashSet<String>();
public ClassMetadataReadingVisitor() {
super(SpringAsmInfo.ASM_VERSION);
}
public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) {
this.className = ClassUtils.convertResourcePathToClassName(name);
this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0);
this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0);
this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0);
this.isFinal = ((access & Opcodes.ACC_FINAL) != 0);
if (supername != null) {
this.superClassName = ClassUtils.convertResourcePathToClassName(supername);
}
this.interfaces = new String[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]);
}
}
public void visitOuterClass(String owner, String name, String desc) {
this.enclosingClassName = ClassUtils.convertResourcePathToClassName(owner);
}
public void visitInnerClass(String name, String outerName, String innerName, int access) {
if (outerName != null) {
String fqName = ClassUtils.convertResourcePathToClassName(name);
String fqOuterName = ClassUtils.convertResourcePathToClassName(outerName);
if (this.className.equals(fqName)) {
this.enclosingClassName = fqOuterName;
this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);
}
else if (this.className.equals(fqOuterName)) {
this.memberClassNames.add(fqName);
}
}
}
public void visitSource(String source, String debug) {
// no-op
}
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
// no-op
return new EmptyAnnotationVisitor();
}
public void visitAttribute(Attribute attr) {
// no-op
}
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
// no-op
return new EmptyFieldVisitor();
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
// no-op
return new EmptyMethodVisitor();
}
public void visitEnd() {
// no-op
}
public String getClassName() {
return this.className;
}
public boolean isInterface() {
return this.isInterface;
}
public boolean isAnnotation() {
return this.isAnnotation;
}
public boolean isAbstract() {
return this.isAbstract;
}
public boolean isConcrete() {
return !(this.isInterface || this.isAbstract);
}
public boolean isFinal() {
return this.isFinal;
}
public boolean isIndependent() {
return (this.enclosingClassName == null || this.independentInnerClass);
}
public boolean hasEnclosingClass() {
return (this.enclosingClassName != null);
}
public String getEnclosingClassName() {
return this.enclosingClassName;
}
public boolean hasSuperClass() {
return (this.superClassName != null);
}
public String getSuperClassName() {
return this.superClassName;
}
public String[] getInterfaceNames() {
return this.interfaces;
}
public String[] getMemberClassNames() {
return this.memberClassNames.toArray(new String[this.memberClassNames.size()]);
}
}