String to Expression

To add an ExpressionPropertyAdapter adapter to my vision window's FPMIWindow.InteractionController I need to run setExpression() on the adapter.

Is there a quick way to parse my expression string to the object structure expected by ExpressionPropertyAdapter.setExpression?

private void bindExpression(InteractionController ic, JComponent target, String propName, String expression, Class<?> valueClass) {
        // EXAMPLE
        // String expression = "getBit({Root Container.test_template_3.tag2},10) &&\ngetBit({Root Container.test_template_3.tag3},10)"

        ExpressionPropertyAdapter a = new ExpressionPropertyAdapter();

        // build expression
        com.inductiveautomation.ignition.common.expressions.Expression e = null; // <--- How to initialize this from String expression ?

        a.setExpression(e);
        a.setExpressionSource(expression);
        a.setTarget(target);
        a.setTargetPropertyDynamic(true);
        a.setTargetPropertyName(propName);
        a.setValueClass(valueClass);

        ic.setPropertyAdapter(target, propName, a);
    }

Check this out:

Note that the work is in preparing an ExpressionParseContext for your target component's environment.

Thanks,

ELParserHarness requires an ExpressionParseContext, which is where I get stuck.

Trying to figure out how to use ExpressionParseContext right now. Tips?

EDIT: @pturmel yessir. Wondering if there's a builtin ExpressionParseContext?

I know of this one by @paul-griffith :

Pretty sure you need this one, but I'm not sure how to set it up properly.

:man_shrugging:

I suspect some of the key bits you need for Vision aren't in the javadocs.

I found that one too! :slight_smile:

Looks promising. Trying to get intellj to resolve the classpath right now...

Edit: Not sure if it's available at the designer scope. classpath goes [...]igntion.gateway.[...]

    ELParserHarness parser = new ELParserHarness();
    FunctionFactory functionFactory = new ComponentFunctionFactory(context);
    ExpressionParseContext binder =
        BindUtilities.newBinder(window, context.getTagManager(), null, functionFactory);

EDIT: Though I'll mention, it looks like potential problems abound:

    ExpressionPropertyAdapter newAdapter = new ExpressionPropertyAdapter();

    // Go through the expression tree and connect all of the BoundVariableExpressions
    try {
      BindUtilities.connectBindings(window, context.getTagManager(), expr, newAdapter, newAdapter);
    } catch (RuntimeException e) {
      if (e.getMessage().isEmpty()) {
        ErrorUtil.showError("Unknown error occurred during bound variable connection.", e);
      } else {
        ErrorUtil.showError(e.getMessage(), e);
      }
      return false;
    }

    Component component = context.getComponent();

    context.getController().removePropertyAdapter(component, propName);
    newAdapter.setExpression(expr);
    newAdapter.setExpressionSource(binding.expression);
    newAdapter.setOverlayOptOut(binding.overlayOptOut);

Winner, winner, chicken dinner!
Massive, unbelievable dubs today, guys. Thank you so much for your help @bmusson @pturmel @paul-griffith !

private void bindExpression(BindingRoot win, JComponent target, String propName, String expression, Class<?> valueClass) {
        // EXAMPLE
        // String expression = "getBit({Root Container.test_template_3.tag2},10) &&\ngetBit({Root Container.test_template_3.tag3},10)"

        ExpressionPropertyAdapter a = new ExpressionPropertyAdapter();

        // build expression
        ELParserHarness p = new ELParserHarness();
        FunctionFactory ff = context.getExpressionFunctionFactory();
        ExpressionParseContext ctx = BindUtilities.newBinder(win, context.getTagManager(), null, ff);
        Expression e = null;
        try {
            e = p.parse(expression, ctx);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }

        // Go through the expression tree and connect the BoundVariableExpressions
        try {
            BindUtilities.connectBindings(win, context.getTagManager(), e, a, a);
        } catch (RuntimeException ex) {
            if (ex.getMessage().isEmpty()) {
                ErrorUtil.showError("Unknown error occurred during bound variable connection.", ex);
            } else {
                ErrorUtil.showError(ex.getMessage(), ex);
            }
        }

        a.setExpression(e);
        a.setExpressionSource(expression);
        a.setTarget(target);
        a.setTargetPropertyDynamic(true);
        a.setTargetPropertyName(propName);
        a.setValueClass(valueClass);

        win.getInteractionController().setPropertyAdapter(target, propName, a);
    }