package net.sourceforge.c4jplugin.internal.ap;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import net.sourceforge.c4j.ContractReference;
import net.sourceforge.c4jplugin.internal.ui.text.UIMessages;
import net.sourceforge.c4jplugin.internal.util.ContractReferenceUtil;
import org.eclipse.jdt.apt.core.env.EclipseAnnotationProcessorEnvironment;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.osgi.util.NLS;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.AnnotationMirror;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.AnnotationTypeElementDeclaration;
import com.sun.mirror.declaration.AnnotationValue;
import com.sun.mirror.declaration.Declaration;
public class ContractAnnotationProcessor implements AnnotationProcessor {
private AnnotationProcessorEnvironment env;
public ContractAnnotationProcessor(AnnotationProcessorEnvironment env) {
this.env = env;
}
public void process() {
// obtain the declaration of the annotation we want to process
AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)env.getTypeDeclaration(ContractReference.class.getName());
// get the annotated types
Collection<Declaration> annotatedTypes = env.getDeclarationsAnnotatedWith(annoDecl);
for (Declaration decl : annotatedTypes) {
Collection<AnnotationMirror> mirrors = decl.getAnnotationMirrors();
// for each annotation found, get a map of element name/value pairs
for (AnnotationMirror mirror : mirrors) {
Map<AnnotationTypeElementDeclaration, AnnotationValue> valueMap = mirror.getElementValues();
Set<Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue>> valueSet = valueMap.entrySet();
for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> annoKeyValue : valueSet) {
AnnotationValue annoValue = annoKeyValue.getValue(); // get the name
if (annoKeyValue.getKey().getSimpleName().equals("contractClassName")) {
Object contractValue = annoValue.getValue(); // get the value
if (contractValue instanceof String) {
// check if the contractValue represents a valid class-name
CompilationUnit compilationUnit = getEclipseAPE().getAST();
IJavaElement javaElement = compilationUnit.getJavaElement();
try {
IType type = ContractReferenceUtil.getType(javaElement);
String[][] matches = type.resolveType((String)contractValue);
if (matches == null) {
// could not resolve the contractValue as a type
env.getMessager().printError(annoValue.getPosition(), NLS.bind(UIMessages.AnnotationProcessor_error_contractNotFound, contractValue));
}
else if (matches.length > 1) {
// the contractValue is ambiguous
env.getMessager().printError(annoValue.getPosition(), NLS.bind(UIMessages.AnnotationProcessor_error_contractAmbiguous, contractValue));
}
else {
// check if the resolved contract has compilation errors
IType resolvedType = type.getJavaProject().findType(matches[0][0], matches[0][1]);
if (ContractReferenceUtil.hasJavaErrors(resolvedType))
env.getMessager().printWarning(annoValue.getPosition(), NLS.bind(UIMessages.AnnotationProcessor_warning_contractHasErrors, contractValue));
}
} catch (JavaModelException e) {}
}
}
}
}
}
}
private EclipseAnnotationProcessorEnvironment getEclipseAPE() {
return (EclipseAnnotationProcessorEnvironment)env;
}
}