package org.yamcs.xtceproc;
import org.codehaus.janino.CompileException;
import org.codehaus.janino.Location;
import org.codehaus.janino.SimpleCompiler;
import org.codehaus.janino.util.LocatedException;
import org.yamcs.xtce.JavaExpressionCalibrator;
public class JavaExpressionCalibratorFactory {
/**
* Compiles the expression into an executable calibrator processor
* @param c
* @return a calibrator processor
* @throws IllegalArgumentException if the expression cannot be compiled
*/
public static CalibratorProc compile(JavaExpressionCalibrator c) {
String className = "Expression"+c.hashCode();
StringBuilder sb = new StringBuilder();
sb.append("package org.yamcs.xtceproc.jecf;\n")
.append("public class ").append(className).append(" implements org.yamcs.xtceproc.CalibratorProc {\n")
.append(" public double calibrate(double rv) {\n")
.append("return ").append(c.getFormula()).append(";\n")
.append(" }\n")
.append("}\n");
try {
SimpleCompiler compiler = new SimpleCompiler();
compiler.cook(sb.toString());
Class<?> cexprClass = compiler.getClassLoader().loadClass("org.yamcs.xtceproc.jecf."+className);
return (CalibratorProc) cexprClass.newInstance();
} catch (LocatedException e) {
String msg = e.getMessage();
Location l = e.getLocation();
if(l!=null) {
//we change the location in the message because it refers to the fabricated code
//it is still not perfect, if the expression is not properly closed
// , janino will complain about the next line that the user doesn't know about...
Location l1 = new Location(null, (short)(l.getLineNumber()-3), (short)(l.getColumnNumber()-7));
msg = l1.toString()+": "+msg.substring(l.toString().length()+1);
}
throw new IllegalArgumentException("Cannot compile expression '"+c.getFormula()+"': "+msg, e);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot compile expression '"+c.getFormula()+"'", e);
}
}
}