I'm not sure if I understood your requirements correctly.

It seems to me that if your scripts are truly and totally dynamic, then you cannot know before hand what variables will need to be populated into the interpreter context - the user could write anything.

I once used beanshell to create a perfectly workable expression calculator and rules engine for a financial services application.
I had such mechanisms as:
-------------
public interface Populatable extends Dynamic
{
  void setCode(String code);
  Class getContextClass();
}
-------------
public interface Calculatable extends Populatable, Checkable
{
    String getCalculation();
}
-------------
public interface CalculatorContext
{
    Populatable[] getPopulatables();
}
-------------
/**
 * Populates the Spring ApplicationContext into the Beanshell's shared namespace.
 */
public class ApplicationContextAwareCalculatorPopulator implements ApplicationContextAware
{
  public void setApplicationContext( ApplicationContext cxt )
    throws BeansException
  {
    try
    {
      Interpreter i = new Interpreter();
      i.set( Calculator.APPLICATION_CONTEXT, cxt);
      i.eval("bsh.shared." + Calculator.APPLICATION_CONTEXT + " = " + Calculator.APPLICATION_CONTEXT);
    }
    catch(EvalError e)
    {
.......
    }
  }
}
-------------
//Calculator class
  public Calculator( CalculatorHolder holder )
    throws EvalError
  {
    this.interpreter = new Interpreter();
interpreter.getNameSpace().importCommands( Calculator.class.getPackage().getName() ); // pre-defined calculator functions
// gives access to spring beans via bsh.shared
    interpreter.eval( APPLICATION_CONTEXT + " = bsh.shared." + APPLICATION_CONTEXT );
.......
}

  public void init( CalculatorContext populateFromContext )
    throws EvalError
  {
    Populatable[] populatables = populateFromContext.getPopulatables();
    for ( int i = 0; i < populatables.length; i++ )
    {
........etc
-------------

I have absolutely no idea if this is helpful to you or not.
The calculation expressions and "populatables" were configured through a database, so that ultimately there was a well defined set of expression variables. The expressions could be changed at runtime by the user and did reference objects (the "populatables") fetched via hibernate and injected into the calculator context, as well as all the Spring beans my app was built upon.
If the user tried to reference a populatable or bean that didn't exist, I'd just catch the EvalError and report it to the user.
Ultimately, what else can you do? If the user doesn't set "xpos", then it's an error, plain and simple.
You've constructed a list of unset variable that the user needs to set before the expression is run, but if the user doesn't set one, what can you do that's different to a general EvalError? I suppose you can pinpoint specifically what is not set, and include that in your friendly error message.



2008/6/23 Brent Easton <b.easton@exemail.com.au>:
Thanks Stewart,
 
I was aware of those, but the problem is how do you find out which variables are undefined and need to be set? The set of variables available is not canonical.
 
I have got something working by subclassing NameSpace with a custom getVariableImpl implementation that builds a list of undefined variables. When an expression is created, I do a test evaluation and record the list of undefined variables. When the expression is to be evaluated for real, I use bind the known undefined variables to the current property values.

This seems to be working fine for the limited use of evaluating a single expression. My next task is to implement a more general script object. What I really need to work out is how to dynamically reference property values in my main application from within beanscript. Slowly getting there.

Regards,

Brent.


*********** REPLY SEPARATOR ***********


On 23/06/2008 at 11:21 AM Stewart Cambridge wrote:

Check the bsh.Interpreter class. The methods set(), unset() and eval() may help you.


2008/6/22 Brent Easton <b.easton@exemail.com.au>:

I am trying to work out the best way to integrate Beanshell into my application. I want to use Beanshell to add the ability to parse and evaluate arbitrarily complex expressions typed in by users.

For example

 20 * xpos + ypos/2

The expressions are entered and validated at one point of time, but are evaluated much later, in a different phase of operation of the program when xpos and ypos will have determinable values.

I have successfully used the Parser to parse and validate the structure of expression.

My problem is determining and binding values to the variables in the expression at runtime. The variables 'xpos' and 'ypos' (plus a host of other 'variables') are not predetermined at the time the expression is created.

At evaluation time, I need to determine what variables are used in the expression are undefined, then bind them to values from my application, evaluate the expression and then return the result to my application.

Any pointers would be appreciated.

Regards,
Brent.







-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Beanshell-users mailing list
Beanshell-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/beanshell-users


____________________________________________________________
Brent Easton                      
Analyst/Programmer                              
University of Western Sydney                                  
Email:
b.easton@uws.edu.au