package org.andork.codegen;
import static org.andork.japa.JavaParserUtils.getDeclaration;
import static org.andork.japa.JavaParserUtils.getQualifiedName;
import japa.parser.JavaParser;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.Node;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.andork.collect.InverseComparator;
import org.andork.japa.JavaParserUtils;
public class ModifiableCompilationUnit {
private CompilationUnit unit;
private List<String> lines;
private static final int TAB_SIZE = 8;
public static void main(String[] args) throws Exception {
List<String> lines = LineUtils.readLines(new FileInputStream("applet/src/gen/" + ModifiableCompilationUnit.class.getName().replace('.', '/') + ".java"));
ModifiableCompilationUnit compUnit = new ModifiableCompilationUnit(lines);
System.out.println(compUnit.getNode(ModifiableCompilationUnit.class.getName() + ".main(java.lang.String[])"));
System.out.println(compUnit.getNode(ModifiableCompilationUnit.class.getName() + ".ModifiableCompilationUnit(List)"));
System.out.println(compUnit.getNode(ModifiableCompilationUnit.class.getName() + ".parse(java.util.List)"));
Method m = Modifier.class.getMethod("replace", LineRegion.class, String.class);
System.out.println(getQualifiedName(m));
System.out.println(compUnit.getNode(getQualifiedName(m)));
compUnit.modify()
.replace(LineUtils.region(compUnit.getNode(ModifiableCompilationUnit.class.getName() + ".main(java.lang.String[])")),
"public static void main(String[] args) { }")
.replace(LineUtils.region(compUnit.getNode(ModifiableCompilationUnit.class.getName() + ".lines")),
"public List<String> blah;")
.commit();
System.out.println(compUnit.unit);
System.out.println(getDeclaration(compUnit.unit, Modifier.class));
System.out.println(getDeclaration(compUnit.unit, Modifier.class.getMethod("replace", LineRegion.class, String.class)));
System.out.println(getDeclaration(compUnit.unit, Modifier.class.getDeclaredField("replacements")));
}
public ModifiableCompilationUnit(List<String> lines) throws Exception {
unit = parse(lines);
this.lines = Collections.unmodifiableList(new ArrayList<String>(lines));
}
public Modifier modify() {
return new Modifier();
}
public List<String> getLines() {
return lines;
}
public CompilationUnit getCompilationUnit() {
return unit;
}
private static void write(List<String> lines, Writer writer) throws Exception {
for (String line : lines) {
writer.write(line);
writer.write("\n");
}
}
private static CompilationUnit parse(List<String> lines) throws Exception {
StringWriter writer = new StringWriter();
write(lines, writer);
CompilationUnit result = JavaParser.parse(new ByteArrayInputStream(writer.getBuffer().toString().getBytes()));
return result;
}
public class Modifier {
private TreeSetMultiMap<LineRegion, String> replacements = TreeSetMultiMap.newInstance(new InverseComparator<LineRegion>(LineRegion.OVERLAP_FORBIDDING_COMPARATOR));
public Modifier replace(LineRegion region, String replacement) {
replacements.put(region, replacement);
return this;
}
public Modifier delete(LineRegion region) {
return replace(region, "");
}
public Modifier insert(int line, int column, String insertion) {
return replace(new LineRegion(line, column), insertion);
}
public void commit() throws Exception {
List<String> newLines = new ArrayList<String>(lines);
for (Map.Entry<LineRegion, String> entry : replacements.entrySet()) {
LineRegion.replace(newLines, entry.getKey(), entry.getValue(), TAB_SIZE);
}
try {
unit = parse(newLines);
lines = Collections.unmodifiableList(newLines);
replacements = null;
} catch (Exception t) {
for (String line : newLines) {
System.out.println(line);
}
throw t;
}
}
}
public Node getNode(String fqName) {
return JavaParserUtils.getNode(unit, fqName);
}
}