package com.google.code.joto;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.code.joto.ast.beanstmt.BeanAST;
import com.google.code.joto.ast.beanstmt.BeanAST.BeanStmt;
import com.google.code.joto.ast.beanstmt.impl.BeanASTPrettyPrinter;
import com.google.code.joto.ast.beanstmt.impl.BeanASTToStringFormatter;
import com.google.code.joto.ast.valueholder.ValueHolderAST.AbstractObjectValueHolder;
import com.google.code.joto.ast.valueholder.util.ObjectToValueHolderBuilder;
import com.google.code.joto.ast.valueholder.util.ValueHolderPrettyPrinter;
import com.google.code.joto.reflect.ReflectUtils;
import com.google.code.joto.util.graph.DecoratorGraph;
import com.google.code.joto.util.graph.IGraph;
import com.google.code.joto.util.graph.TopologicalSort;
import com.google.code.joto.util.graph.helper.GraphPrinter;
import com.google.code.joto.value2java.VHToStmt;
import com.google.code.joto.value2java.impl.ObjectStmtInfo;
import com.google.code.joto.value2java.impl.VarDefUseDependencyGraphBuilder;
/**
* main class for using Joto : Value to Java Stmt code generator
*/
public class ObjectToCodeGenerator {
private static final Logger log = LoggerFactory.getLogger(ObjectToCodeGenerator.class);
private boolean debug = false;
private boolean debugValueHolder = false;
private boolean debugLinksFromValueHolder = false;
private boolean debugDependencyGraph = false;
private JotoConfig config;
//-------------------------------------------------------------------------
public ObjectToCodeGenerator(JotoConfig config) {
this.config = config;
}
public ObjectToCodeGenerator() {
this(new JotoConfig());
}
//-------------------------------------------------------------------------
public void setDebug(boolean p) {
this.debug = p;
}
public void setDebugValueHolder(boolean p) {
this.debugValueHolder = p;
}
public void setDebugLinksFromValueHolder(boolean p) {
this.debugLinksFromValueHolder = p;
}
// public void setDebugDependencyGraph(boolean debugDependencyGraph) {
// this.debugDependencyGraph = debugDependencyGraph;
// }
/**
* @param declaredObjClass
* @param obj
* @param objName
* @return
*/
public String objToStmtsString(Class<?> declaredObjClass, Object obj, String objName,
StringBuilder resStmtsText) {
if (obj == null) {
return null;
}
if (declaredObjClass != null && declaredObjClass.isPrimitive()
&& ReflectUtils.primitiveTypeToWrapperType(declaredObjClass) == obj.getClass() // check!
) {
// encode primitive value directly!
return obj.toString();
}
String stmtsText = objToStmtsString(obj, objName);
if (stmtsText != null) {
resStmtsText.append(stmtsText);
}
return objName;
}
/**
*
* @param obj
* @param objName
* @return
*/
public String objToStmtsString(Object obj, String objName) {
List<BeanStmt> stmts = objToStmts(obj, objName);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bout);
BeanASTPrettyPrinter stmtPrinter = new BeanASTPrettyPrinter(out);
for(BeanStmt stmt : stmts) {
stmt.visit(stmtPrinter);
}
return bout.toString();
}
/**
*
* @param obj
* @param objName
* @return
*/
public List<BeanStmt> objToStmts(Object obj, String objName) {
ObjectToValueHolderBuilder b = new ObjectToValueHolderBuilder();
b.buildValue(obj);
Map<Object,AbstractObjectValueHolder> resMap = b.getResultMap();
AbstractObjectValueHolder objVH = resMap.get(obj);
if (debug && debugValueHolder) {
log.info("ObjectToValueHolderBuilder => " + resMap.size() + " obj valueHolder(s)");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ValueHolderPrettyPrinter printer = new ValueHolderPrettyPrinter(new PrintStream(buffer));
printer.setPrintLinksFrom(debugLinksFromValueHolder);
objVH.visit(printer);
log.info(buffer.toString());
}
VHToStmt b2jVisitor = new VHToStmt(config);
b2jVisitor.visitRootObject(objVH, objName);
Map<AbstractObjectValueHolder, ObjectStmtInfo> objInitInfos =
b2jVisitor.getResultObjInitInfoMap();
List<BeanStmt> tmpUnsortedStmts = new ArrayList<BeanStmt>();
for(Map.Entry<AbstractObjectValueHolder,ObjectStmtInfo> e : objInitInfos.entrySet()) {
ObjectStmtInfo objInfo = e.getValue();
tmpUnsortedStmts.add(objInfo.getVarDeclStmt());
tmpUnsortedStmts.addAll(objInfo.getInitStmts());
}
if (b2jVisitor.getLogVarDeclStmt() != null) {
tmpUnsortedStmts.add(b2jVisitor.getLogVarDeclStmt());
}
// TODO TEMPORARY HACK FOR COMPARISON
//boolean debugNoSort = false;
//if (debugNoSort) {
// return tmpUnsortedStmts;
//}
// build graph for topological sort
IGraph<BeanAST> graph = new DecoratorGraph<BeanAST>();
for(BeanStmt p : tmpUnsortedStmts) {
graph.addVertex(p);
}
VarDefUseDependencyGraphBuilder graphBuilder =
new VarDefUseDependencyGraphBuilder(graph);
for(BeanStmt p : tmpUnsortedStmts) {
p.visit(graphBuilder, p);
}
if (debug && debugDependencyGraph) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
GraphPrinter<BeanAST> graphPrinter = new GraphPrinter<BeanAST>(new PrintStream(buffer), BeanASTToStringFormatter.getInstance());
graphPrinter.printGraph(graph);
log.info("stmt dependency graph: {" + buffer.toString() + "} // stmt dependency graph");
}
// topological sort
TopologicalSort<BeanAST> topologicalSort = new TopologicalSort<BeanAST>(graph);
List<BeanAST> sortedASTs = topologicalSort.topologicalSort();
List<BeanStmt> res = new ArrayList<BeanStmt>();
for(BeanAST sortedAST : sortedASTs) {
if (sortedAST instanceof BeanStmt) {
res.add((BeanStmt) sortedAST);
} else {
// should not occur?!
throw new IllegalStateException();
}
}
return res;
}
}