package conditionAnnotation;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Messager;
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;
import java.io.*;
import com.sun.mirror.apt.Filer;
public class ConditionAnnotationProcessor implements AnnotationProcessor
{
public ConditionAnnotationProcessor(AnnotationProcessorEnvironment env)
{
_env = env;
}
public void process()
{
Messager messager = _env.getMessager();
File sourceFile = null;
ArrayList<ConditionStatement> csList = new ArrayList<ConditionStatement>();
// obtain the declaration of the annotation we want to process
AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)_env.getTypeDeclaration(ConditionAnnotation.class.getName());
// get the annotated types
Collection<Declaration> annotatedTypes = _env.getDeclarationsAnnotatedWith(annoDecl);
for (Declaration decl : annotatedTypes) {
ConditionStatement cs = new ConditionStatement();
cs.setLineNumber(decl.getPosition().line());
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();
// the annotation processor understands two elements: "Pre" and "Post"
for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> annoKeyValue : valueSet) {
AnnotationValue annoValue = annoKeyValue.getValue(); // get the name
sourceFile = annoValue.getPosition().file();
if (annoKeyValue.getKey().getSimpleName().equals("Pre")) {
Object PreValue = annoValue.getValue(); // get the value
if (!(PreValue instanceof String)) {// controllo che sia una stringa
messager.printError(annoValue.getPosition(), "Insert a string condition: Condition(Pre=String)");
}
else {
cs.setPreCondition(annoValue.getValue());
}
}
else if (annoKeyValue.getKey().getSimpleName().equals("Post")) {
Object PostValue = annoValue.getValue(); // get the value
if (!(PostValue instanceof String)) {// controllo che sia una stringa
messager.printError(annoValue.getPosition(), "Insert a string condition: Condition(Post=String)");
}
else {
cs.setPostCondition(annoValue.getValue());
}
}
else {// errore nell'inserimento del campo
messager.printError(annoValue.getPosition(), "@Condition accepts only Pre() and Post() parameters");
}
}
}
csList.add(cs);
}
try
{
BufferedReader in = new BufferedReader(new FileReader(sourceFile.getAbsoluteFile()));
BufferedReader inPack = new BufferedReader(new FileReader(sourceFile.getAbsoluteFile()));
String packageName = "";
String linea = "";
while((linea=inPack.readLine())!= null) {
if(linea.contains("package"))
{
packageName = linea.substring(8,linea.length()-1);
}
}
inPack.close();
Filer f = getEnvironment().getFiler();
String point = "";
if (packageName.length()!= 0) {
point=".";
}
PrintWriter pw = f.createSourceFile( getPackageName() + point + packageName +".
" + sourceFile.getName().substring(0, sourceFile.getName().length()-5));
pw.write("package " + getPackageName() + point + packageName + ";\n\n");
int lineaCorrente = 1;
int numGraffe = 0;
int numAnnotation = 0;
boolean noMoreAnnotation = false;
ConditionStatement cs = null;
Collections.sort(csList, new Comparator() {
public int compare(Object o1, Object o2) {
ConditionStatement cs1 = (ConditionStatement)o1;
ConditionStatement cs2 = (ConditionStatement)o2;
Integer i1 = new Integer(cs1.getLineNumber());
Integer i2 = new Integer(cs2.getLineNumber());
return i1.compareTo(i2);
}
});
while((linea=in.readLine())!= null ) {
if(!noMoreAnnotation) cs = (ConditionStatement)csList.get(numAnnotation);
String nuovaLinea = "";
if(!(linea.contains("import conditionAnnotation.") ||
linea.contains("@ConditionAnnotation") ||
linea.contains("package")))
nuovaLinea = linea + "\n";
if(lineaCorrente >= cs.getLineNumber()) {
if(linea.contains("{")) numGraffe++;
if(linea.contains("}")) numGraffe--;
if(linea.contains("{") && !cs.getPreCondition().equals("") && numGraffe == 1 && !noMoreAnnotation) {
nuovaLinea = linea.substring(0, linea.indexOf("{")+1) + "\n";
nuovaLinea += "if(!(" + cs.getPreCondition() + ")) throw new RuntimeException(\"Precondition not satisfied\");\n";
nuovaLinea += linea.substring(linea.indexOf("{")+1, linea.length()) + "\n";
if(cs.getPostCondition().equals("")) {
numAnnotation++;
if(numAnnotation == (csList.size())) noMoreAnnotation = true;
}
}
if(linea.contains("}") && !cs.getPostCondition().equals("") && numGraffe == 0 && !noMoreAnnotation) {
nuovaLinea = linea.substring(0, linea.indexOf("}")) + "\n";
nuovaLinea += "if(!(" + cs.getPostCondition() + ")) throw new RuntimeException(\"Postcondion not satisfied\");\n";
nuovaLinea += linea.substring(linea.indexOf("}"), linea.length()) + "\n";
numAnnotation++;
if(numAnnotation == (csList.size())) noMoreAnnotation = true;
}
}
pw.print(nuovaLinea);
lineaCorrente++;
}
in.close();
pw.close();
}
catch( IOException ioe )
{
ioe.printStackTrace();
}
}
public AnnotationProcessorEnvironment getEnvironment()
{
return _env;
}
AnnotationProcessorEnvironment _env;
public String getPackageName() {
return "generatedfilepackage";
}
}