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