Search code examples
javareferencescriptengine

Execute code from string with defined variables in Java


I've got the following class

class ListNode
{
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

My task is to write a method that:

  1. Takes int[] as a parameter.
  2. Reverses the array.
  3. Returns ListNode which has value of the current element in the array, has .next of a new created ListNode with the corresponding value in the array and so on.

Given the input of new int[]{0, 8, 7}; I expect to get a ListNode where value is 7, .next is a new node with the value of 8 and finally .next.next is a new node with the value of 0.

I wrote the following methods to accomplish such behaviour

public static ListNode reverseAndLinkToListNode(int [] arrayToReverse)
{
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("js");

    int finalDigitsArrayLength = arrayToReverse.length;

    ListNode finalNode = new ListNode();

    if (finalDigitsArrayLength > 0)
    {
        finalNode.val = arrayToReverse[finalDigitsArrayLength - 1];
        int j = 1;

        for (int i = finalDigitsArrayLength - 2; i >= 0; i--)
        {
            try
            {
                // create a new list node
                ListNode newlyCreatedNode = new ListNode(arrayToReverse[i]);
                // calculate how many 'nexts' I need
                String codeToExecute = returnNumberOfNexts(j);
                // set the next field with the list node I just created
                engine.eval(codeToExecute);
            }
            catch (Exception e)
            {
                System.out.println(e);
            }

            j++;
        }
    }

    return finalNode;
}


public static String returnNumberOfNexts(int nextCounter)
{
    String finalDotNextString = "finalNode";

    if (nextCounter > 0)
    {
        for (int i = 0; i < nextCounter; i++)
        {
            finalDotNextString += ".next";
        }
    }

    finalDotNextString += " = newlyCreatedNode;";

    return finalDotNextString;
}

The solution above returns the right code to execute, but when it comes to execution, I get:

javax.script.ScriptException: ReferenceError: "finalNode" is not defined in <eval> at line number 1

How do I define finalNode and newlyCreatedNode variables in the engine?


Solution

  • Your scriptengine fails when it tries to resolve the 'finalNode' variable. The reason is that finalNode is known in Java but not in the Javascript engine. So you need to tell the scriptengine how to resolve the variable. I did not test the code but it might look somewhat like this:

    ListNode finalNode = new ListNode();
    ScriptEngine engine = manager.getEngineByName("js");
    Bindings bindings = engine.getBindings(ScriptContext.GLOBAL_SCOPE);
    if (bindings==null) {
        bindings = engine.createBindings();
        engine.setBindings(ScriptContext.GLOBAL_SCOPE);
    }
    bindings.put("finalNode", finalNode);
    engine.eval(codeToExecute);