Package com.singularsys.jep.misc.publishingvariable


package com.singularsys.jep.misc.publishingvariable
A set of classes implementing the Observer pattern via the Flow system of Flow.Publisher and Flow.Subscriber. Both the individual variables and the variable table can be subscribed to. The classes are:

A typical usage would be:

SubmissionPublisher<VariableTableAction> pub
    = PublishingVariableTable. createDefaultPublisher();
var vt = new PublishingVariableTable(pub);
PublishingVariableFactory vf = new PublishingVariableFactory(pub);
Jep jep = new Jep(vt, vf);
var vts = new VariableTableSubscriber() {
    @Override
    protected void variableAdded(String name, Object value) {
        System.out.println("variableAdded " + name + " " + value);
    }

    @Override
    protected void variableChanged(String name, Object oldValue, Object newValue) {
        System.out.println("variableChanged " + name + " " + newValue);
    }
};
pub.subscribe(vts);
jep.setVariable("x", 5.0);
Node n = jep.parse("y=x^2");
jep.evaluate(n);

Which will print:

 variableAdded x 5.0
 variableAdded y null
 variableChanged y 25.0
 

Several different configurations are possible.

Default configuration:

var pub = PublishingVariableTable. createDefaultPublisher();
var jep = new Jep(
    new PublishingVariableTable(pub),
    new PublishingVariableFactory(pub));
Here both the whole table, and individual variables can be watched.

Just watching table actions:

var pub = PublishingVariableTable. createDefaultPublisher();
var jep = new Jep(
    new PublishingVariableTable(pub));
Here a Jep instance is created with the standard VariableFactory. If you don't need to monitor variables values this will be most efficient.

Just watch particular variables:

var pub = PublishingVariableTable. createDefaultPublisher();
var jep = new Jep(new PublishingVariableFactory(null));
var vbl = (PublishingVariable) jep.addVariable("x", 5.0);
vbl.setPublisher(pub);
Here the Jep instance uses the StandardVariableTable, and a PublishingVariableFactory with its publisher set to null. Variables created by the factory also have a null publisher. Individual Variable you wish to monitor can have their publisher set.

Current thread configuration:

var pub = PublishingVariableTable.createCurrentThreadPublisher();
var jep = new Jep(
    new PublishingVariableTable(pub),
    new PublishingVariableFactory(pub));
All actions happen on the current thread, which can be simpler to use as there are not thread communication issues.

If is also possible to use custom SubmissionPublisher using different a Executor, and buffer sizes.

Subscribers

To subscribe to changes you can implement a Flow.Subscriber, in particular implementing the void onNext(VariableTableAction item) to respond to changes in the variable table and variables. The VariableTableAction.action signals the type of action one of ADD_VARIABLE, ADD_CONSTANT, REMOVE_VARIABLE, VARIABLE_VALUE_CHANGED, CLEAR_TABLE, CLEAR_NON_CONSTANT. The VariableTableAction also contains the name of the variable, and the old and new value if appropriate. Implementing of this method should always call subscription.request(1); to request the next update.

For example:

public class BasicSubscriber implements Subscriber<VariableTableAction> {
    Subscription subscription;
    public final LinkedBlockingQueue<String> messages = new LinkedBlockingQueue<>();

    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }

    @Override
    public void onNext(VariableTableAction item) {
        messages.add(item.toString());
        subscription.request(1);
    }

    @Override
    public void onError(Throwable throwable) {
        messages.add(throwable.toString());
    }

    @Override
    public void onComplete() {
        messages.add("complete");
    }

    public void cancel() {
        subscription.cancel();
    }
}

Alternatively you can implement VariableTableSubscriber this has methods for each type of action like variableAdded(String, Object) and there is no need to call subscription.request(1); as this is done by default. An example implementation can be found in the documentation for VariableTableSubscriber.

Another other is the VariableTableUpdater this can subscribe to one publisher and update a second variable table with the changes reported by the publisher, keeping the second variable table up to date with the first.

Since:
Jep 4.1
See Also: