1 package org.simantics.modeling;
3 import org.simantics.basicexpression.Expressions;
4 import org.simantics.db.ReadGraph;
5 import org.simantics.db.Resource;
6 import org.simantics.db.WriteGraph;
7 import org.simantics.db.exception.DatabaseException;
8 import org.simantics.db.layer0.variable.Variable;
9 import org.simantics.scl.compiler.types.Type;
10 import org.simantics.structural.stubs.StructuralResource2;
11 import org.simantics.utils.datastructures.Pair;
12 import org.simantics.utils.datastructures.Triple;
14 public class InvertBasicExpressionVisitor extends InvertBasicExpressionVisitorBase {
16 private static final String MAGIC = "_111_";
18 private static String replaced(String expression) {
19 return expression.replaceAll("\\.([A-Za-z])", MAGIC + "$1");
22 public static void invert(WriteGraph graph, Variable base, String expression, Object value) throws DatabaseException {
23 InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
24 Expressions.evaluate(replaced(expression), visitor);
25 Object result = visitor.getResult();
26 if(result == null) return;
27 if(result instanceof Triple) {
28 @SuppressWarnings("unchecked")
29 Triple<Double, Double, String> data = (Triple<Double, Double, String>)result;
30 String key = data.third.replace(MAGIC, ".");
31 String path = getVariablePath(graph, base, key);
32 Variable targetVariable = base.browse(graph, path);
33 if(value instanceof Number) {
34 if(Math.abs(data.first) > 1e-9) {
35 double inverted = (double) (((Number)value).doubleValue() - data.second) / data.first;
36 Object invertedValue = numericValueInType(inverted, value.getClass());
37 targetVariable.setValue(graph, invertedValue);
39 } else if (value instanceof Boolean) {
40 // TODO: support 'not'
41 targetVariable.setValue(graph, value);
47 private static Object numericValueInType(double value, Class<?> type) {
48 if (type == Integer.class) {
50 } else if (type == Long.class) {
52 } else if (type == Byte.class) {
54 } else if (type == Float.class) {
60 private static String getVariablePath(ReadGraph graph, Variable base, String key) throws DatabaseException {
61 StructuralResource2 STR = StructuralResource2.getInstance(graph);
62 Resource type = base.getPossibleType(graph);
65 boolean procedural = graph.isInstanceOf(type, STR.ProceduralComponentType);
66 Pair<String, Type> pair;
68 pair = graph.sync(new ProceduralSubstructureMapRequest(base)).get(key);
70 pair = ComponentTypeSubstructure.forType(graph, type).possibleTypedRVI(key);
79 * @param expression the expression to check for invertibility. An empty is expression is not invertible.
81 * @throws DatabaseException
82 * @throws NullPointerException for null expression
84 public static boolean isInvertible(ReadGraph graph, Variable base, String expression) throws DatabaseException {
85 if (expression == null)
86 throw new NullPointerException("null expression for variable " + base.getURI(graph));
87 if (expression.isEmpty())
90 Resource type = base.getPossibleType(graph);
91 if(type == null) return false;
93 InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
94 Expressions.evaluate(replaced(expression), visitor);
95 Object pair = visitor.getResult();
96 if(pair == null) return false;
97 if(pair instanceof Triple) {
98 @SuppressWarnings("unchecked")
99 Triple<Double, Double, String> data = (Triple<Double, Double, String>)pair;
100 String key = data.third.replace(MAGIC,".");
101 return getVariablePath(graph, base, key) != null;
107 @SuppressWarnings("unchecked")
108 private static Triple<Double, Double, String> possibleInvertibleExpression(ReadGraph graph, Variable base, String expression) throws DatabaseException {
109 if (base == null || expression == null || expression.isEmpty())
111 InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
112 //System.out.println("invert : " + expression + " -> " + replaced(expression) + " for " + base.getURI(graph));
113 Expressions.evaluate(replaced(expression), visitor);
114 Object result = visitor.getResult();
115 if (result instanceof Triple)
116 return (Triple<Double, Double, String>) result;
120 public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
121 Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
124 String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
125 return path != null ? base.browsePossible(graph, path) : null;
128 public static Triple<Double, Double, Variable> possibleInvertibleExpressionReferencedTransformedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
129 Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
132 String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
135 Variable targetVariable = base.browsePossible(graph, path);
136 return targetVariable != null ? Triple.make(data.first, data.second, targetVariable) : null;