package org.jboss.tools.seam.ui.text.java.scanner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.seam.internal.core.scanner.ScannerException;
import org.jboss.tools.seam.internal.core.scanner.java.ASTVisitorImpl;
import org.jboss.tools.seam.internal.core.scanner.java.AnnotatedASTNode;
import org.jboss.tools.seam.internal.core.scanner.java.ResolvedAnnotation;
import org.jboss.tools.seam.ui.SeamGuiPlugin;
public class JavaAnnotationScanner {
public JavaAnnotationScanner() {}
/**
* Returns component or list of component
* TODO change return type
* @param f
* @return
* @throws ScannerException
*/
/* public LoadedDeclarations parse(IFile f) throws ScannerException {
ICompilationUnit u = null;
try {
u = getCompilationUnit(f);
} catch (CoreException e) {
throw new ScannerException(
NLS.bind(SeamCoreMessages.JAVA_SCANNER_CANNOT_GET_COMPILATION_UNIT_FOR,f), e);
}
if(u == null) return null;
ASTRequestorImpl requestor = new ASTRequestorImpl(f);
ICompilationUnit[] us = new ICompilationUnit[]{u};
ASTParser p = ASTParser.newParser(AST.JLS3);
p.setSource(u);
p.setResolveBindings(true);
p.createASTs(us, new String[0], requestor, null);
return requestor.getDeclarations();
}
*/
/**
* Returns component or list of component
* TODO change return type
* @param u
* @return
* @throws ScannerException
*/
public void parse(ICompilationUnit u) throws ScannerException {
resolvedAnnotations = null;
resolvedType = null;
if(u == null) return;
ASTRequestorImpl requestor = new ASTRequestorImpl(u);
ICompilationUnit[] us = new ICompilationUnit[]{u};
ASTParser p = ASTParser.newParser(AST.JLS3);
p.setSource(u);
p.setResolveBindings(true);
p.createASTs(us, new String[0], requestor, null);
resolvedType = requestor.getType();
resolvedAnnotations = requestor.getAnnotations();
}
Map<ResolvedAnnotation, AnnotatedASTNode<ASTNode>> resolvedAnnotations = null;
IType resolvedType = null;
public Map<ResolvedAnnotation, AnnotatedASTNode<ASTNode>> getResolvedAnnotations() {
return resolvedAnnotations;
}
public IType getResolvedType() {
return resolvedType;
}
private ICompilationUnit getCompilationUnit(IFile f) throws CoreException {
IProject project = f.getProject();
IJavaProject javaProject = (IJavaProject)project.getNature(JavaCore.NATURE_ID);
IResource[] rs = EclipseResourceUtil.getJavaSourceRoots(project);
for (int i = 0; i < rs.length; i++) {
if(rs[i].getFullPath().isPrefixOf(f.getFullPath())) {
IPath path = f.getFullPath().removeFirstSegments(rs[i].getFullPath().segmentCount());
IJavaElement e = javaProject.findElement(path);
if(e instanceof ICompilationUnit) {
return (ICompilationUnit)e;
}
}
}
return null;
}
class ASTRequestorImpl extends ASTRequestor {
private ASTVisitorImpl visitor = new ASTVisitorImpl();
// LoadedDeclarations ds = new LoadedDeclarations();
List<ResolvedAnnotation> annotations = new ArrayList<ResolvedAnnotation>();
IResource resource;
IPath sourcePath;
ICompilationUnit unit;
public ASTRequestorImpl(IResource resource) {
this.resource = resource;
this.sourcePath = resource.getFullPath();
}
public ASTRequestorImpl(ICompilationUnit unit) {
this.unit = unit;
this.resource = unit.getResource();
this.sourcePath = resource.getFullPath();
}
// public LoadedDeclarations getDeclarations() {
// return ds;
// }
public Map<ResolvedAnnotation, AnnotatedASTNode<ASTNode>> getAnnotations() {
return annotationMap;
}
public IType getType() {
return type;
}
public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
IType[] ts = null;
try {
ts = source.getTypes();
} catch (JavaModelException e) {
SeamGuiPlugin.getDefault().logError(e);
}
if(ts == null || ts.length == 0) return;
for (int i = 0; i < ts.length; i++) {
visitor.setType(null);
int f = 0;
try {
f = ts[i].getFlags();
} catch (JavaModelException e) {
//ignore
continue;
}
if(Flags.isPublic(f)) {
visitor.setType(ts[i]);
ast.accept(visitor);
if(!visitor.hasSeamComponent()) continue;
processTypeData(visitor.root);
}
}
}
IType type = null;
AnnotatedASTNode<AbstractTypeDeclaration> annotatedType = null;
Set<AnnotatedASTNode<FieldDeclaration>> annotatedFields = null;
Set<AnnotatedASTNode<MethodDeclaration>> annotatedMethods = null;
Map<ResolvedAnnotation, AnnotatedASTNode<ASTNode>> annotationMap = new HashMap<ResolvedAnnotation, AnnotatedASTNode<ASTNode>>();
private void processTypeData(ASTVisitorImpl.TypeData data) {
type = data.type;
annotatedType = data.annotatedType;
annotatedFields = data.annotatedFields;
annotatedMethods = data.annotatedMethods;
ResolvedAnnotation[] annotations = annotatedType.getAnnotations();
for (int i = 0; annotations != null && i < annotations.length; i++) {
annotationMap.put(annotations[i], (AnnotatedASTNode)annotatedType);
}
if (annotatedMethods != null) {
for (AnnotatedASTNode annotatedMethod : annotatedMethods) {
annotations = annotatedMethod.getAnnotations();
for (int i = 0; annotations != null && i < annotations.length; i++) {
annotationMap.put(annotations[i], (AnnotatedASTNode)annotatedMethod);
}
}
}
if (annotatedFields != null) {
for (AnnotatedASTNode annotatedField : annotatedFields) {
annotations = annotatedField.getAnnotations();
for (int i = 0; annotations != null && i < annotations.length; i++) {
annotationMap.put(annotations[i], (AnnotatedASTNode)annotatedField);
}
}
}
// this.annotations = annotations;
}
}
public ResolvedAnnotation findAnnotationByValueOffset(int offset) {
if (resolvedAnnotations == null)
return null;
for (ResolvedAnnotation a : resolvedAnnotations.keySet()) {
if (a.getAnnotation() instanceof SingleMemberAnnotation) {
SingleMemberAnnotation sma = (SingleMemberAnnotation)a.getAnnotation();
Object vpd = sma.getStructuralProperty(SingleMemberAnnotation.VALUE_PROPERTY);
if (vpd instanceof ASTNode) {
ASTNode node = (ASTNode)vpd;
int start = node.getStartPosition();
int length = node.getLength();
if (offset >= start && offset < start + length) {
return a;
}
}
} else if (a.getAnnotation() instanceof NormalAnnotation) {
NormalAnnotation na = (NormalAnnotation)a.getAnnotation();
Object vpd = na.getStructuralProperty(NormalAnnotation.VALUES_PROPERTY);
if (vpd instanceof List) {
for (Object item : (List)vpd) {
if (item instanceof ASTNode) {
ASTNode node = (ASTNode)item;
if (node.getNodeType() != ASTNode.MEMBER_VALUE_PAIR)
continue;
MemberValuePair mvp = (MemberValuePair)node;
SimpleName name = mvp.getName();
if (!"value".equals(name.getIdentifier())) {
continue;
}
int start = node.getStartPosition();
int length = node.getLength();
if (offset >= start && offset < start + length) {
return a;
}
}
}
}
}
}
return null;
}
/**
* Returns the annotation's value text
*
* @param annotation
* @return
*/
public String getAnnotationValue(ResolvedAnnotation annotation) {
if (annotation.getAnnotation() instanceof SingleMemberAnnotation) {
SingleMemberAnnotation sma = (SingleMemberAnnotation)annotation.getAnnotation();
Object vpd = sma.getStructuralProperty(SingleMemberAnnotation.VALUE_PROPERTY);
if (vpd instanceof StringLiteral) {
return ((StringLiteral)vpd).getLiteralValue();
}
return vpd.toString();
} else if (annotation.getAnnotation() instanceof NormalAnnotation) {
NormalAnnotation na = (NormalAnnotation)annotation.getAnnotation();
Object vpd = na.getStructuralProperty(NormalAnnotation.VALUES_PROPERTY);
if (vpd instanceof List) {
for (Object item : (List)vpd) {
if (item instanceof ASTNode) {
ASTNode node = (ASTNode)item;
if (node.getNodeType() != ASTNode.MEMBER_VALUE_PAIR)
continue;
MemberValuePair mvp = (MemberValuePair)node;
SimpleName name = mvp.getName();
if (!"value".equals(name.getIdentifier())) {
continue;
}
return ((StringLiteral)mvp.getValue()).getLiteralValue();
}
}
}
}
return null;
}
/**
* Returns the annotation's value region
*
* @param annotation
* @return
*/
public IRegion getAnnotationValueRegion(ResolvedAnnotation annotation) {
if (annotation.getAnnotation() instanceof SingleMemberAnnotation) {
SingleMemberAnnotation sma = (SingleMemberAnnotation)annotation.getAnnotation();
Object vpd = sma.getStructuralProperty(SingleMemberAnnotation.VALUE_PROPERTY);
if (vpd instanceof StringLiteral) {
StringLiteral sl = (StringLiteral)vpd;
return new Region(sl.getStartPosition() + 1, sl.getLength());
}
if (vpd instanceof ASTNode) {
ASTNode astNode = (ASTNode)vpd;
return new Region(astNode.getStartPosition(),astNode.getLength());
}
return null;
} else if (annotation.getAnnotation() instanceof NormalAnnotation) {
NormalAnnotation na = (NormalAnnotation)annotation.getAnnotation();
Object vpd = na.getStructuralProperty(NormalAnnotation.VALUES_PROPERTY);
if (vpd instanceof List) {
for (Object item : (List)vpd) {
if (item instanceof ASTNode) {
ASTNode node = (ASTNode)item;
if (node.getNodeType() != ASTNode.MEMBER_VALUE_PAIR)
continue;
MemberValuePair mvp = (MemberValuePair)node;
SimpleName name = mvp.getName();
if (!"value".equals(name.getIdentifier())) {
continue;
}
Object sValuesObj = mvp.getStructuralProperty(MemberValuePair.VALUE_PROPERTY);
if (sValuesObj instanceof StringLiteral) {
StringLiteral sl = (StringLiteral)sValuesObj;
return new Region(sl.getStartPosition() + 1, sl.getLength());
}
if (sValuesObj instanceof ASTNode) {
ASTNode astNode = (ASTNode)sValuesObj;
return new Region(astNode.getStartPosition(),astNode.getLength());
}
return null;
}
}
}
}
return null;
}
/**
* Detects if the type of annotation equals to the selected SeamAnnotations' type
*
* @param annotation
* @param typeName
*
* @return
*/
public boolean isAnnotationOfType(ResolvedAnnotation annotation, String typeName) {
if (annotation == null || typeName == null)
return false;
return (typeName.equals(annotation.getType()));
}
static String getResolvedType(IType type, String n) {
String[][] rs;
try {
rs = type.resolveType(n);
if(rs != null && rs.length > 0) {
return (rs[0][0].length() == 0) ? rs[0][1] : rs[0][0] + "." + rs[0][1]; //$NON-NLS-1$
}
} catch (JavaModelException e) {
SeamGuiPlugin.getDefault().logError(e);
}
return n;
}
}