package org.simantics.modeling.ui.diagram.monitor; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Stack; import org.simantics.basicexpression.analysis.DepthFirstAdapter; import org.simantics.basicexpression.analysis.EvaluationException; import org.simantics.basicexpression.node.AAddressValue; import org.simantics.basicexpression.node.AConstantValue; import org.simantics.basicexpression.node.AFunctionPrimary; import org.simantics.basicexpression.node.AMultMultiplicative; import org.simantics.basicexpression.node.APlusExpression; import org.simantics.basicexpression.node.ARangeValue; import org.simantics.basicexpression.node.ARviValue; import org.simantics.basicexpression.node.ASequenceArgList; import org.simantics.basicexpression.node.ASingleArgList; import org.simantics.basicexpression.node.ASingleRange; import org.simantics.basicexpression.node.AStringValue; import org.simantics.basicexpression.node.AVariablePrimary; import org.simantics.basicexpression.node.PArgList; import org.simantics.common.format.Formatter; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.ModelInstances; import org.simantics.db.layer0.request.VariableIndexRoot; import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; import org.simantics.scl.runtime.function.Function; public class MonitorExpressionVisitor extends DepthFirstAdapter { public static final boolean DEBUG_APPLICATION = false; public static final boolean DEBUG = false; public static class ApplicationException extends Exception { private static final long serialVersionUID = 1L; public ApplicationException(String message) { super(message); } } final ReadGraph graph; final Variable variable; final Formatter formatter; Stack stack = new Stack(); HashMap builtins = new HashMap(); public MonitorExpressionVisitor(ReadGraph graph, Formatter formatter, Variable variable) { this.graph = graph; this.formatter = formatter; this.variable = variable; } public Object getResult() { if(exception != null) return exception; return stack.pop(); } public void outAConstantValue(AConstantValue node) { if(DEBUG) System.out.println("outAConstantValue " + node); //$NON-NLS-1$ stack.push(Double.valueOf(node.toString())); } public void outAStringValue(AStringValue node) { if(DEBUG) System.out.println("outAStringValue " + node); //$NON-NLS-1$ String value = node.toString(); stack.push(value.substring(1, value.length() - 2)); } public void outAAddressValue(AAddressValue node) { if(DEBUG) System.out.println("outAAddressValue " + node); //$NON-NLS-1$ stack.push('&' + node.getRange().toString()); } @Override public void outASingleRange(ASingleRange node) { if(DEBUG) System.out.println("outASingleRange " + node); //$NON-NLS-1$ } @Override public void outARviValue(ARviValue node) { if(DEBUG) System.out.println("outARviValue " + node); //$NON-NLS-1$ String rvi = node.toString().trim(); try { Variable var = variable.browse(graph, rvi); stack.push(format(var.getValue(graph))); } catch (DatabaseException e) { Logger.defaultLogError(e); stack.push(""); //$NON-NLS-1$ //$NON-NLS-2$ } } @Override public void outAVariablePrimary(AVariablePrimary node) { if(DEBUG) System.out.println("outAVariablePrimary " + node); //$NON-NLS-1$ String identifier = node.toString().trim(); if("value".equals(identifier)) { //$NON-NLS-1$ try { stack.push(format(variable.getValue(graph))); } catch (DatabaseException e) { stack.push(e); } } else { stack.push(identifier); } } public void outARangeValue(ARangeValue node) { if(DEBUG) System.out.println("outARangeValue " + node); //$NON-NLS-1$ String identifier = node.getRange().toString().trim(); stack.push(identifier); } private String format(Object o) { if(formatter != null) return formatter.format(o); else return o != null ? o.toString() : ""; //$NON-NLS-1$ } private double extractValue(Object o) { if (o instanceof Number) { return ((Number) o).doubleValue(); } else if (o instanceof String) { String s = (String) o; if (s.isEmpty()) return 0; return Double.valueOf((String) o); } else { return Double.NaN; } } private Object extractSum(Object o1, Object o2) { if(o1 instanceof String) { return o1.toString() + o2; } else if (o2 instanceof String) { return o1.toString() + o2.toString(); } else if (o1 instanceof Number && o2 instanceof Number) { return ((Number) o1).doubleValue() + ((Number) o2).doubleValue(); } else { return o1.toString() + o2.toString(); } } public void outAPlusExpression(APlusExpression node) { if(DEBUG) System.out.println("outAPlusExpression " + node); //$NON-NLS-1$ Object o2 = stack.pop(); Object o1 = stack.pop(); Object out = extractSum(o1, o2); stack.push(out); } public void outAMultMultiplicative(AMultMultiplicative node) { if(DEBUG) System.out.println("outAMultiplicative " + node); //$NON-NLS-1$ Object o1 = stack.pop(); Object o2 = stack.pop(); double d1 = extractValue(o1); double d2 = extractValue(o2); stack.push(d1 * d2); } int countArguments(PArgList args) { if (args == null) return 0; if (args instanceof ASingleArgList) return 1; ASequenceArgList seq = (ASequenceArgList) args; return 1 + countArguments(seq.getArgList()); } public void outAFunctionPrimary(AFunctionPrimary node) { if(DEBUG) System.out.println("outAFunctionPrimary " + node); //$NON-NLS-1$ try { String functionName = node.getFunc().getText().replace("(", ""); //$NON-NLS-1$ //$NON-NLS-2$ if (DEBUG_APPLICATION) System.out.println("function apply " + functionName); //$NON-NLS-1$ Function function = builtins.get(functionName); if (function != null) { LinkedList args = new LinkedList(); int argc = countArguments(node.getArgList()); for (int i = 0; i < argc; i++) { args.addFirst(stack.pop()); } args.addFirst(formatter); args.addFirst(variable); args.addFirst(graph); Object result = function.applyArray(args); stack.push(format(result)); } else { // Instances instances = graph.adapt(L0.Function, Instances.class); // Collection functions = instances.find(graph, Variables.getModel(graph, variable), // "Name:" + functionName); // if (DEBUG_APPLICATION) // System.out.println("Found " + functions.size() + " matches."); // if (functions != null && functions.size() == 1) { Layer0 L0 = Layer0.getInstance(graph); Resource functionResource = null; Resource indexRoot = graph.sync(new VariableIndexRoot(variable)); if (indexRoot != null) { Map functions = graph.syncRequest( new ModelInstances(indexRoot, L0.Function), TransientCacheListener.> instance()); functionResource = functions.get(functionName); } if(functionResource != null) { // Resource functionResource = functions.iterator().next(); function = graph.adapt(functionResource, Function.class); LinkedList args = new LinkedList(); int argc = countArguments(node.getArgList()); for (int i = 0; i < argc; i++) { args.addFirst(stack.pop()); } args.addFirst(formatter); args.addFirst(variable); args.addFirst(graph); Object result = function.applyArray(args.toArray()); stack.push(format(result)); } else { //stack.push(null); throw new EvaluationException("Function not found in dependencies: '" + functionName + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } } } catch (DatabaseException e) { stack.push(null); } } }