Package org.boris.expr.engine

Source Code of org.boris.expr.engine.SimpleGraphEngine$EngineFunctionManager

/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
*     Peter Smith
*******************************************************************************/
package org.boris.expr.engine;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.boris.expr.Expr;
import org.boris.expr.ExprBoolean;
import org.boris.expr.ExprDouble;
import org.boris.expr.ExprError;
import org.boris.expr.ExprEvaluatable;
import org.boris.expr.ExprException;
import org.boris.expr.ExprInteger;
import org.boris.expr.ExprString;
import org.boris.expr.ExprVariable;
import org.boris.expr.IExprFunction;
import org.boris.expr.function.ExcelFunctionProvider;
import org.boris.expr.function.FunctionManager;
import org.boris.expr.function.IFunctionProvider;
import org.boris.expr.graph.Edge;
import org.boris.expr.graph.Graph;
import org.boris.expr.graph.GraphCycleException;
import org.boris.expr.parser.ExprParser;

/**
* Simple graph-based dependency engine.
*/
public class SimpleGraphEngine
{
    private EngineFunctionManager evaluator = new EngineFunctionManager();
    private Graph<String> graph = new Graph();
    private Map<String, Expr> inputs = new HashMap<String, Expr>();
    private Map<String, Expr> results = new HashMap<String, Expr>();
    private Set<IEngineListener> listeners = new HashSet<IEngineListener>();

    public SimpleGraphEngine() {
        addFunctions(new ExcelFunctionProvider());
        setValue("PI", ExprDouble.PI);
        setValue("TRUE", ExprBoolean.TRUE);
        setValue("FALSE", ExprBoolean.FALSE);
    }

    public void addEngineListener(IEngineListener listener) {
        listeners.add(listener);
    }

    public void addFunction(String name, IExprFunction function) {
        evaluator.add(name, function);
    }

    public void addFunctions(IFunctionProvider provider) {
        evaluator.add(provider);
    }

    public void setValue(String name, String value) {
        setValue(name, new ExprString(value));
    }

    public void setValue(String name, double value) {
        setValue(name, new ExprDouble(value));
    }

    public void setValue(String name, int value) throws GraphCycleException {
        setValue(name, new ExprInteger(value));
    }

    public void setValue(String name, boolean value) {
        setValue(name, new ExprBoolean(value));
    }

    public void set(String name, Expr value) throws GraphCycleException {
        setValue(name, value);
        for (ExprVariable v : ExprVariable.findVariables(value)) {
            graph.add(new Edge<String>(v.getName(), name));
        }
    }

    public void setFormula(String name, String expression) throws ExprException, GraphCycleException {
        set(name, parse(expression));
    }

    public void calculate() throws ExprException {
        for (String name : graph.sort()) {
            Expr input = inputs.get(name);
            if (input instanceof ExprEvaluatable) {
                Expr result = null;
                try {
                    fireBeforeCalculation(name);
                    result = ((ExprEvaluatable) input).evaluate();
                } catch (ExprException e) {
                    result = new ExprError(e);
                }
                results.put(name, result);
                fireAfterCalculation(name, result);
            }
        }
    }

    public Expr get(String name) {
        return results.get(name);
    }

    public Expr parse(String expression) throws ExprException {
        try {
            return ExprParser.parse(expression, evaluator).optimize();
        } catch (IOException e) {
            throw new ExprException(e);
        }
    }

    public void clear(String name) {
        inputs.remove(name);
        results.remove(name);
        graph.remove(name);
    }

    private void setValue(String name, Expr value) {
        inputs.put(name, value);
        if (value instanceof ExprEvaluatable)
            results.remove(name);
        else {
            results.put(name, value);
            fireAfterCalculation(name, value);
        }
        graph.clearInbounds(name);
        graph.add(name);
    }

    private void fireBeforeCalculation(String name) {
        for (IEngineListener l : listeners)
            l.beforeCalculation(name);
    }

    private void fireAfterCalculation(String name, Expr value) {
        for (IEngineListener l : listeners)
            l.afterCalculation(name, value);
    }

    private class EngineFunctionManager extends FunctionManager
    {
        public Expr evaluateVariable(ExprVariable variable) throws ExprException {
            Expr v = results.get(variable.getName());
            return v == null ? ExprError.NAME : v;
        }
    }
}
TOP

Related Classes of org.boris.expr.engine.SimpleGraphEngine$EngineFunctionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.