Convert string to code in Java

I have a strange case. In this database, I received a record with the VARCHAR field, so in my entity model I added this field, as well as getters and setters. Now the fun begins:

The line below is actually the body of the method. It looks like this:

 if (score <= 0.7) {return 0;} else if (score <=0.8) {return 1;} else if (score <=0.9) {return 2;} else {return 3} 

and now - I need to make this line in the method, and honestly, I don’t know how to achieve this. This actual method should get a double mark from me and return an integer value depending on the given score.

Is anyone


EDIT

I know that the easiest way is not to use solutions like this, but this is not my call, in addition, there are so many records in the database, and each record is different. We cannot bear it. I have to deal with this - so, please, ideas for a solution only, and I promise that I will do everything hating and say this is stupid :)
Trust me, I, and I will, and I will complain for quite some time.

+7
java
source share
4 answers

Look at the java scripting API

 int eval(String code) { code = "function f () {" + code + "} f()"; // Or otherwise ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("JavaScript"); engine.put("score", 1.4); Number num = (Number) engine.eval(code); return num.intValue(); } 

Here I suggested that JavaScript syntax is possible; I had to fill out a score , you can somewhere intercept all unknown free variables.

+15
source share

You should look at the Java Scripting API . There are several projects that implement this API so that you can add the ability to run scripts in your Java code.

+6
source share

The best way to do this is to use the scripting API , as noted above. You can run JavaScript from there. If you want to dare more and try to run Java code (and point to it as eretic), you can try to compile the code using JavaCompiler and run it using the class loader.

BEWARE: This is one of the most ORRIFIC ways to use Java. You should use this only for debugging and only as a last resort. In any case, you should not use this in a production environment.

This will create the DontTryThisAtHome.java file in your class path. Remember how to use this strategy only for fun and very few other cases:

 public class MyClass{ public static void main(String[] args) throws Exception { JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null); File jf = new File("DontTryThisAtHome.java"); PrintWriter pw = new PrintWriter(jf); pw.println("public class DontTryThisAtHome{" + "static final int score = " + <your_score> + ";" + "public static void main(){}" + "public int getValue(){" + " return score<=0.7?0:score<=0.8?1: score<=0.9?2:3" + "} + "}"); pw.close(); Iterable<? extends JavaFileObject> fO = sjfm.getJavaFileObjects(jf); if(!jc.getTask(null,sjfm,null,null,null,fO).call()) { throw new Exception("compilation failed"); } URL[] urls = new URL[]{new File("").toURI().toURL()}; URLClassLoader ucl = new URLClassLoader(urls); Object o= ucl.loadClass("DontTryThisAtHome").newInstance(); int result = (int) o.getClass().getMethod("getValue").invoke(o); ucl.close(); } } 
+1
source share

I think the best solution is to change your architecture, but if you have to try it, try the following: You can find this code here

 public class DynamicProxy { public interface CalculateScore { double calculate(double score); } private static class JavaSourceFromString extends SimpleJavaFileObject { final String code; JavaSourceFromString(String name, String code) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.code = code; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } } private static class JavaClassObject extends SimpleJavaFileObject { protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); public JavaClassObject(String name, Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); } public byte[] getBytes() { return bos.toByteArray(); } @Override public OutputStream openOutputStream() throws IOException { return bos; } } private static class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { private JavaClassObject classObject; private final String className; public ClassFileManager(StandardJavaFileManager standardManager, String className) { super(standardManager); this.className = className; } @Override public ClassLoader getClassLoader(Location location) { return new SecureClassLoader(DynamicProxy.class.getClassLoader()) { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { if (name.contains(className)) { byte[] b = classObject.getBytes(); return super.defineClass(name, classObject.getBytes(), 0, b.length); } return super.findClass(name); } }; } @Override public JavaFileObject getJavaFileForOutput(Location location, String className, javax.tools.JavaFileObject.Kind kind, FileObject sibling) throws IOException { classObject = new JavaClassObject(className, kind); return classObject; } } private static class MyInvocationHandler implements InvocationHandler { private final String className; private final String classBody; public MyInvocationHandler(String implClassName, String classBody) { this.className = implClassName; this.classBody = classBody; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Class<?> clazz = compileClass(className, classBody); return method.invoke(clazz.newInstance(), args); } } private static Class<?> compileClass(String className, String classBody) throws Throwable { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); JavaFileObject file = new JavaSourceFromString(className, classBody); Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file); JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null), className); CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits); boolean success = task.call(); for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { System.out.println(diagnostic.getCode()); System.out.println(diagnostic.getKind()); System.out.println(diagnostic.getPosition()); System.out.println(diagnostic.getStartPosition()); System.out.println(diagnostic.getEndPosition()); System.out.println(diagnostic.getSource()); System.out.println(diagnostic.getMessage(null)); } if (success) { return fileManager.getClassLoader(null).loadClass(className); } return null; } @SuppressWarnings("unchecked") public static <T> T newProxyInstance(Class<T> clazz, String className, String classBody) { ClassLoader parentLoader = DynamicProxy.class.getClassLoader(); return (T) Proxy.newProxyInstance(parentLoader, new Class[] { clazz }, new MyInvocationHandler(className, classBody)); } public static CalculateScore create(String body) { StringWriter writer = new StringWriter(); PrintWriter out = new PrintWriter(writer); out.println("public class CalculateScoreImpl implements pl.softech.stackoverflow.javac.DynamicProxy.CalculateScore {"); out.println(" public double calculate(double score) {"); out.println(body); out.println(" }"); out.println("}"); out.close(); return newProxyInstance(CalculateScore.class, "CalculateScoreImpl", writer.toString()); } public static void main(String[] args) { CalculateScore calculator = create("if (score <= 0.7) {return 0;} else if (score <=0.8) {return 1;} else if (score <=0.9) {return 2;} else {return 3; }"); System.out.println(calculator.calculate(0.3)); } } 
+1
source share

All Articles