FunctionIndexProcessor { public static PropertyState tryCalculateValue(String path, NodeState state, String[] functionCode) { Deque<PropertyState> stack = new ArrayDeque<>(); for (int i = functionCode.length - 1; i > 0; i--) { String token = functionCode[i]; PropertyState ps; if (token.startsWith("@")) { String propertyName = token.substring(1); ps = getProperty(path, state, propertyName); } else { ps = calculateFunction(token, stack); } if (ps == null) { ps = EMPTY_PROPERTY_STATE; } stack.push(ps); } PropertyState ret = stack.pop(); return ret==EMPTY_PROPERTY_STATE ? null : ret; } protected  FunctionIndexProcessor(String function); static String[] getProperties(String[] functionCode); static PropertyState tryCalculateValue(String path, NodeState state, String[] functionCode); static String[] getFunctionCode(String functionDescription); static String convertToPolishNotation(String function);  }
@Test public void tryCalculateValue() { assertEquals("value = 11", FunctionIndexProcessor.tryCalculateValue("x", EMPTY_NODE.builder().setProperty("data", "Hello World").getNodeState(), new String[]{"function", "length", "@data"}).toString()); assertEquals("value = 100", FunctionIndexProcessor.tryCalculateValue("x", EMPTY_NODE.builder().setProperty("data", new ArrayBasedBlob(new byte[100]), Type.BINARY).getNodeState(), new String[]{"function", "length", "@data"}).toString()); assertEquals("value = HELLO WORLD", FunctionIndexProcessor.tryCalculateValue("x", EMPTY_NODE.builder().setProperty("data", "Hello World").getNodeState(), new String[]{"function", "upper", "@data"}).toString()); assertEquals("value = hello world", FunctionIndexProcessor.tryCalculateValue("x", EMPTY_NODE.builder().setProperty("data", "Hello World").getNodeState(), new String[]{"function", "lower", "@data"}).toString()); }