]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java
Fixed InvertBasicExpressionVisitor bugs with subtractions and divisions
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / InvertBasicExpressionVisitor.java
index dac192936285bed1bd6049e1a53527867ac7abbf..6293cbac9fd7d9c9fe3c6989e33ac368b5784fe5 100644 (file)
@@ -1,16 +1,6 @@
 package org.simantics.modeling;
 
-import gnu.trove.map.hash.THashMap;
-
-import java.util.Stack;
-
 import org.simantics.basicexpression.Expressions;
-import org.simantics.basicexpression.analysis.DepthFirstAdapter;
-import org.simantics.basicexpression.node.AConstantValue;
-import org.simantics.basicexpression.node.ADivMultiplicative;
-import org.simantics.basicexpression.node.AMultMultiplicative;
-import org.simantics.basicexpression.node.APlusExpression;
-import org.simantics.basicexpression.node.AVariablePrimary;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
@@ -21,125 +11,30 @@ import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.Triple;
 
-public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
-
-       Stack<Object> stack = new Stack<Object>();
-
-       public Object getResult() {
-               if(stack.size() != 1) return null; 
-               return stack.pop();
-       }
-
-       public void outAConstantValue(AConstantValue node) {
-               stack.push(Double.valueOf(node.toString()));
-       }
-
-       @Override
-       public void outAVariablePrimary(AVariablePrimary node) {
-        String value = node.toString().trim();
-        stack.push(Triple.make(1.0, 0.0, value));
-       }
-       
-       @SuppressWarnings("unchecked")
-    public void outAPlusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 + (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMinusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third ));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second - (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 - (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMultMultiplicative(AMultMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 * (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outADivMultiplicative(ADivMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       stack.push(Double.NaN);
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double,Double, String>)o1;
-                       stack.push(Triple.make(p.first / (Double)o2, p.second / (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 / (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
+public class InvertBasicExpressionVisitor extends InvertBasicExpressionVisitorBase {
 
        private static final String MAGIC = "_111_";
-       
+
        private static String replaced(String expression) {
            return expression.replaceAll("\\.([A-Za-z])", MAGIC + "$1");
        }
-       
+
     public static void invert(WriteGraph graph, Variable base, String expression, Object value) throws DatabaseException {
         InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
         Expressions.evaluate(replaced(expression), visitor);
-        Object pair = visitor.getResult();
-        if(pair == null) return;
-        if(pair instanceof Triple) {
+        Object result = visitor.getResult();
+        if(result == null) return;
+        if(result instanceof Triple) {
             @SuppressWarnings("unchecked")
-            Triple<Double, Double, String> data = (Triple<Double, Double, String>)pair;
+            Triple<Double, Double, String> data = (Triple<Double, Double, String>)result;
             String key = data.third.replace(MAGIC, ".");
             String path = getVariablePath(graph, base, key);
             Variable targetVariable = base.browse(graph, path);
             if(value instanceof Number) {
                 if(Math.abs(data.first) > 1e-9) {
-                    Double inverted = (((Number)value).doubleValue() - data.second) / data.first;
-                    targetVariable.setValue(graph, inverted);
+                    double inverted = (double) (((Number)value).doubleValue() - data.second) / data.first;
+                    Object invertedValue = numericValueInType(inverted, value.getClass());
+                    targetVariable.setValue(graph, invertedValue);
                 }
             } else if (value instanceof Boolean) {
                 // TODO: support 'not'
@@ -148,7 +43,20 @@ public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
         }
         
     }
-    
+
+    private static Object numericValueInType(double value, Class<?> type) {
+        if (type == Integer.class) {
+            return (int) value;
+        } else if (type == Long.class) {
+            return (long) value;
+        } else if (type == Byte.class) {
+            return (byte) value;
+        } else if (type == Float.class) {
+            return (float) value;
+        }
+        return value;
+    }
+
     private static String getVariablePath(ReadGraph graph, Variable base, String key) throws DatabaseException {
         StructuralResource2 STR = StructuralResource2.getInstance(graph);
         Resource type = base.getPossibleType(graph);
@@ -196,24 +104,36 @@ public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
         
     }
 
-    public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+    @SuppressWarnings("unchecked")
+    private static Triple<Double, Double, String> possibleInvertibleExpression(ReadGraph graph, Variable base, String expression) throws DatabaseException {
         if (base == null || expression == null || expression.isEmpty())
             return null;
         InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
         //System.out.println("invert : " + expression + " -> " + replaced(expression) + " for " + base.getURI(graph));
         Expressions.evaluate(replaced(expression), visitor);
-        Object pair = visitor.getResult();
-        if(pair == null)
-            return null;
-        if(pair instanceof Triple) {
-            @SuppressWarnings("unchecked")
-            Triple<Double, Double, String> data = (Triple<Double, Double, String>)pair;
-            String key = data.third.replace(MAGIC,".");
-            String path = getVariablePath(graph, base, key);
-            Variable targetVariable = base.browsePossible(graph, path);
-            return targetVariable;
-        }
+        Object result = visitor.getResult();
+        if (result instanceof Triple)
+            return (Triple<Double, Double, String>) result;
         return null;
     }
 
+    public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+        Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
+        if (data == null)
+            return null;
+        String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
+        return path != null ? base.browsePossible(graph, path) : null;
+    }
+
+    public static Triple<Double, Double, Variable> possibleInvertibleExpressionReferencedTransformedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+        Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
+        if (data == null)
+            return null;
+        String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
+        if (path == null)
+            return null;
+        Variable targetVariable = base.browsePossible(graph, path);
+        return targetVariable != null ? Triple.make(data.first, data.second, targetVariable) : null;
+    }
+
 }