X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2FInvertBasicExpressionVisitor.java;fp=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2FInvertBasicExpressionVisitor.java;h=dac192936285bed1bd6049e1a53527867ac7abbf;hp=75660a1c5d63201b0a415196a82087855b001877;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java index 75660a1c5..dac192936 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java @@ -1,219 +1,219 @@ -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; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.scl.compiler.types.Type; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.datastructures.Triple; - -public class InvertBasicExpressionVisitor extends DepthFirstAdapter { - - Stack stack = new Stack(); - - 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 p = (Triple)o2; - stack.push(Triple.make(p.first, p.second + (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third )); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)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); - } - - } - - 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) { - @SuppressWarnings("unchecked") - Triple data = (Triple)pair; - 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); - } - } else if (value instanceof Boolean) { - // TODO: support 'not' - targetVariable.setValue(graph, value); - } - } - - } - - private static String getVariablePath(ReadGraph graph, Variable base, String key) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource type = base.getPossibleType(graph); - if(type == null) - return null; - boolean procedural = graph.isInstanceOf(type, STR.ProceduralComponentType); - Pair pair; - if(procedural) - pair = graph.sync(new ProceduralSubstructureMapRequest(base)).get(key); - else - pair = ComponentTypeSubstructure.forType(graph, type).possibleTypedRVI(key); - if(pair == null) - return null; - return pair.first; - } - - /** - * @param graph - * @param base - * @param expression the expression to check for invertibility. An empty is expression is not invertible. - * @return - * @throws DatabaseException - * @throws NullPointerException for null expression - */ - public static boolean isInvertible(ReadGraph graph, Variable base, String expression) throws DatabaseException { - if (expression == null) - throw new NullPointerException("null expression for variable " + base.getURI(graph)); - if (expression.isEmpty()) - return false; - - Resource type = base.getPossibleType(graph); - if(type == null) return false; - - InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor(); - Expressions.evaluate(replaced(expression), visitor); - Object pair = visitor.getResult(); - if(pair == null) return false; - if(pair instanceof Triple) { - @SuppressWarnings("unchecked") - Triple data = (Triple)pair; - String key = data.third.replace(MAGIC,"."); - return getVariablePath(graph, base, key) != null; - } - return false; - - } - - public static Variable possibleInvertibleExpressionReferencedProperty(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 data = (Triple)pair; - String key = data.third.replace(MAGIC,"."); - String path = getVariablePath(graph, base, key); - Variable targetVariable = base.browsePossible(graph, path); - return targetVariable; - } - return null; - } - -} +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; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.scl.compiler.types.Type; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.datastructures.Triple; + +public class InvertBasicExpressionVisitor extends DepthFirstAdapter { + + Stack stack = new Stack(); + + 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 p = (Triple)o2; + stack.push(Triple.make(p.first, p.second + (Double)o1, p.third)); + } else if (o2 instanceof Double && o1 instanceof Triple) { + Triple p = (Triple)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 p = (Triple)o2; + stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third )); + } else if (o2 instanceof Double && o1 instanceof Triple) { + Triple p = (Triple)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 p = (Triple)o2; + stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third)); + } else if (o2 instanceof Double && o1 instanceof Triple) { + Triple p = (Triple)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 p = (Triple)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); + } + + } + + 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) { + @SuppressWarnings("unchecked") + Triple data = (Triple)pair; + 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); + } + } else if (value instanceof Boolean) { + // TODO: support 'not' + targetVariable.setValue(graph, value); + } + } + + } + + private static String getVariablePath(ReadGraph graph, Variable base, String key) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource type = base.getPossibleType(graph); + if(type == null) + return null; + boolean procedural = graph.isInstanceOf(type, STR.ProceduralComponentType); + Pair pair; + if(procedural) + pair = graph.sync(new ProceduralSubstructureMapRequest(base)).get(key); + else + pair = ComponentTypeSubstructure.forType(graph, type).possibleTypedRVI(key); + if(pair == null) + return null; + return pair.first; + } + + /** + * @param graph + * @param base + * @param expression the expression to check for invertibility. An empty is expression is not invertible. + * @return + * @throws DatabaseException + * @throws NullPointerException for null expression + */ + public static boolean isInvertible(ReadGraph graph, Variable base, String expression) throws DatabaseException { + if (expression == null) + throw new NullPointerException("null expression for variable " + base.getURI(graph)); + if (expression.isEmpty()) + return false; + + Resource type = base.getPossibleType(graph); + if(type == null) return false; + + InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor(); + Expressions.evaluate(replaced(expression), visitor); + Object pair = visitor.getResult(); + if(pair == null) return false; + if(pair instanceof Triple) { + @SuppressWarnings("unchecked") + Triple data = (Triple)pair; + String key = data.third.replace(MAGIC,"."); + return getVariablePath(graph, base, key) != null; + } + return false; + + } + + public static Variable possibleInvertibleExpressionReferencedProperty(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 data = (Triple)pair; + String key = data.third.replace(MAGIC,"."); + String path = getVariablePath(graph, base, key); + Variable targetVariable = base.browsePossible(graph, path); + return targetVariable; + } + return null; + } + +}