From 97e6269352f0a3340e50d5dcb8308966fd0db96b Mon Sep 17 00:00:00 2001 From: miettinen Date: Fri, 17 Jan 2014 06:28:17 +0000 Subject: [PATCH] =?utf8?q?Unit=20equivalents=20to=20Sysdyn=20unit=20parser?= =?utf8?q?=20(refs=20#4628).=20Allow=20%,=20$,=20=C2=A3,=20and=20euro=20sy?= =?utf8?q?mbols,=20as=20well=20as=20greek=20letters=20in=20unit=20parser?= =?utf8?q?=20(refs=20#4425).?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28650 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ontology/graph.tg | Bin 165228 -> 165463 bytes .../graph/Validation.pgraph | 5 +- .../org/simantics/sysdyn/SysdynResource.java | 6 + .../ui/properties/ConfigurationTab.java | 32 +++- .../widgets/EquivalentUnitsWidget.java | 143 ++++++++++++++++++ .../sysdyn/ui/validation/UnitFunction.java | 12 +- .../src/org/simantics/sysdyn/TestParser.java | 36 ++--- .../representation/utils/UnitUtils.java | 51 +++++-- .../sysdyn/unitParser/UnitCheckingNode.java | 9 +- .../sysdyn/unitParser/UnitParser.jjt | 2 +- .../sysdyn/unitParser/nodes/AddOp.java | 8 +- .../sysdyn/unitParser/nodes/Arithmetic.java | 12 +- .../unitParser/nodes/ArrayDefinition.java | 12 +- .../nodes/ComponentReferenceFull.java | 16 +- .../sysdyn/unitParser/nodes/Divide.java | 8 +- .../sysdyn/unitParser/nodes/Factor.java | 11 +- .../sysdyn/unitParser/nodes/ForIndex.java | 8 +- .../sysdyn/unitParser/nodes/FunctionCall.java | 8 +- .../sysdyn/unitParser/nodes/IfThenElse.java | 8 +- .../unitParser/nodes/Multiplication.java | 8 +- .../sysdyn/unitParser/nodes/Power.java | 4 +- .../sysdyn/unitParser/nodes/RelOp.java | 8 +- .../sysdyn/unitParser/nodes/Relation.java | 12 +- .../sysdyn/unitParser/nodes/Term.java | 12 +- .../sysdyn/unitParser/nodes/UnitResult.java | 74 ++++++++- .../sysdyn/unitParser/nodes/Value.java | 8 +- 26 files changed, 409 insertions(+), 104 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/EquivalentUnitsWidget.java diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index 27edbee88049cbfcdf0649ef11d89f8fc0a5b046..afa595a6e4d2dfbdce0ff3b4c4f8fb787af6c971 100644 GIT binary patch literal 165463 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 z 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 yJg&(^yEn-to87P_5Q-E9M5-W& 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 jMMCuRl53-2d;c-- VALIDATIONS.Units.UnitIssueSource.allowEquivalents >-- L0.Boolean >() { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/EquivalentUnitsWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/EquivalentUnitsWidget.java new file mode 100644 index 00000000..13106559 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/EquivalentUnitsWidget.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2014 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.sysdyn.ui.properties.widgets; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.simantics.browsing.ui.swt.widgets.impl.SelectionListenerImpl; +import org.simantics.browsing.ui.swt.widgets.impl.Widget; +import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.PossibleObjectWithType; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.management.ISessionContext; +import org.simantics.issues.ontology.IssueResource; +import org.simantics.operation.Layer0X; +import org.simantics.sysdyn.SysdynResource; +import org.simantics.utils.ui.ISelectionUtils; + +/** + * Widget for equivalent units selection. + * @author Tuomas Miettinen + * + */ +public class EquivalentUnitsWidget implements Widget{ + + Resource model = null; + org.simantics.browsing.ui.swt.widgets.Button unitEquivalents; + + public EquivalentUnitsWidget(Composite parent, WidgetSupport support, int style) { + support.register(this); + unitEquivalents = new org.simantics.browsing.ui.swt.widgets.Button(parent, support, style |= SWT.CHECK); + unitEquivalents.setText("Unit equivalents"); + unitEquivalents.getWidget().setToolTipText("Supported equivalent units:\n" + + "$, $s, dollar, dollars, usd\n"+ + "\u20ac, \u20acs, eur, euro, euros, e, ecu\n"+ + "£, £s, pound, pounds, gbp\n"+ + "Unit, Units\n"+ + "Person, People, Persons\n"+ + "second, seconds, sec, s\n"+ + "minute, minutes, min\n"+ + "hour, hours, h, hr\n"+ + "day, days, d\n"+ + "month, months, mon, mth, mo, mos\n"+ + "year, years, a, y, yr"); + + } + + @Override + public void setInput(ISessionContext context, Object input) { + if(input instanceof ISelection) { + ISelection selection = (ISelection)input; + if(selection instanceof IStructuredSelection) { + Resource resource = ISelectionUtils.filterSingleSelection(selection, Resource.class); + if(resource != null) { + model = resource; + } + } + } + + if(model == null) return; + + try { + context.getSession().syncRequest(new ReadRequest() { + + @Override + public void run(ReadGraph graph) throws DatabaseException { + // Determine if unit validation is enabled. + SysdynResource sr = SysdynResource.getInstance(graph); + final Resource unitIssueSource = graph.syncRequest( + new PossibleObjectWithType(model, + Layer0X.getInstance(graph).Activates, + sr.Validations_Units_UnitIssueSource)); + IssueResource ISSUE = IssueResource.getInstance(graph); + final Boolean issueSource_active = graph.getPossibleRelatedValue(unitIssueSource, ISSUE.IssueSource_active, Bindings.BOOLEAN); + + Boolean result = false; + if(unitIssueSource != null) { + result = graph.getPossibleRelatedValue(unitIssueSource, sr.Validations_Units_UnitIssueSource_allowEquivalents, Bindings.BOOLEAN); + } + + final boolean enable = result; + final Button button = getWidget(); + button.getDisplay().asyncExec(new Runnable() { + + @Override + public void run() { + if(button.isDisposed()) return; + + // Is unit validation is enabled, enable the button. + getWidget().setEnabled(unitIssueSource!=null && issueSource_active); + if(Boolean.TRUE.equals(enable)) + button.setSelection(true); + else + button.setSelection(false); + } + }); + } + }); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + unitEquivalents.addSelectionListener(new SelectionListenerImpl(context) { + + @Override + public void apply(WriteGraph graph, Resource model) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(graph); + Resource unitIssueSource = graph.syncRequest( + new PossibleObjectWithType(model, + Layer0X.getInstance(graph).Activates, + sr.Validations_Units_UnitIssueSource)); + if(unitIssueSource == null) + return; + + Boolean result = graph.getPossibleRelatedValue(unitIssueSource, sr.Validations_Units_UnitIssueSource_allowEquivalents, Bindings.BOOLEAN); + if(result == null) + result = false; + graph.claimLiteral(unitIssueSource, sr.Validations_Units_UnitIssueSource_allowEquivalents, Boolean.FALSE.equals(result)); + } + }); + } + + public Button getWidget() { + return unitEquivalents.getWidget(); + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java index 24e3c80c..ff07b394 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/validation/UnitFunction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.ui.validation; @@ -36,6 +37,7 @@ import org.simantics.sysdyn.manager.SysdynModelManager; import org.simantics.sysdyn.representation.IndependentVariable; import org.simantics.sysdyn.representation.expressions.IExpression; import org.simantics.sysdyn.representation.utils.UnitUtils; +import org.simantics.sysdyn.utils.ModelUtils; public class UnitFunction { @@ -113,6 +115,7 @@ public class UnitFunction { if(configuration == null) return Collections.emptyList(); + SysdynModel model = ModelUtils.getModel(graph, module); String result = null; ArrayList issues = new ArrayList(); for(Resource outputRelation : graph.getObjects(module, SR.Variable_isTailOf)) { @@ -123,7 +126,7 @@ public class UnitFunction { continue; String left = graph.getPossibleRelatedValue(output, SR.Variable_unit); String right = graph.getPossibleRelatedValue(reference, SR.Variable_unit); - result = UnitUtils.matchUnits(left, right); + result = UnitUtils.matchUnits(left, right, UnitUtils.allowEquivalents(graph, model)); if(result != null) issues.add(new ModuleStandardIssue(SR.Validations_ModuleOutputUnitWarning, module, output, reference)); } @@ -136,7 +139,7 @@ public class UnitFunction { continue; String left = graph.getPossibleRelatedValue(variable, SR.Variable_unit); String right = graph.getPossibleRelatedValue(reference, SR.Variable_unit); - result = UnitUtils.matchUnits(left, right); + result = UnitUtils.matchUnits(left, right, UnitUtils.allowEquivalents(graph, model)); if(result != null) issues.add(new ModuleStandardIssue(SR.Validations_ModuleInputUnitWarning, module, variable, reference)); } @@ -226,7 +229,8 @@ public class UnitFunction { if(right == null || right.isEmpty()) return "No unit defined for " + NameUtils.getSafeName(graph, rightResource); - String result = UnitUtils.matchUnits(left, right); + SysdynModel model = ModelUtils.getModel(graph, leftResource); + String result = UnitUtils.matchUnits(left, right, UnitUtils.allowEquivalents(graph, model)); if(result != null) result = prefix + result + suffix; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java index f12f8281..95393832 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/TestParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn; @@ -28,24 +29,25 @@ public class TestParser { public static void main(String[] args) { HashMap units = new HashMap(); - - doScenario(scenario1(units), units); - doScenario(scenario2(units), units); - doScenario(scenario3(units), units); - doScenario(scenario4(units), units); - doScenario(scenario5(units), units); - doScenario(scenario6(units), units); - doScenario(scenario7(units), units); - doScenario(scenario8(units), units); - doScenario(scenario9(units), units); - doScenario(scenario10(units), units); - doScenario(scenario11(units), units); - doScenario(scenario12(units), units); - doScenario(scenario13(units), units); + boolean allowEquivalents = true; + + doScenario(scenario1(units), units, allowEquivalents); + doScenario(scenario2(units), units, allowEquivalents); + doScenario(scenario3(units), units, allowEquivalents); + doScenario(scenario4(units), units, allowEquivalents); + doScenario(scenario5(units), units, allowEquivalents); + doScenario(scenario6(units), units, allowEquivalents); + doScenario(scenario7(units), units, allowEquivalents); + doScenario(scenario8(units), units, allowEquivalents); + doScenario(scenario9(units), units, allowEquivalents); + doScenario(scenario10(units), units, allowEquivalents); + doScenario(scenario11(units), units, allowEquivalents); + doScenario(scenario12(units), units, allowEquivalents); + doScenario(scenario13(units), units, allowEquivalents); } - private static void doScenario(String expression, HashMap units) { + private static void doScenario(String expression, HashMap units, boolean allowEquivalents) { System.out.println("-----------------------------------"); System.out.println("Expression: " + expression); System.out.println("Units: "); @@ -58,7 +60,7 @@ public class TestParser { UnitCheckingNode node = (UnitCheckingNode) parser.expr(); try { - UnitResult u = node.getUnits(units); + UnitResult u = node.getUnits(units, allowEquivalents); System.out.println("Result: " + u.getCleanFullUnit()); } catch (UnitCheckingException e) { e.printStackTrace(); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java index 758cc8b2..4949b478 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/representation/utils/UnitUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.representation.utils; @@ -16,12 +17,15 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Set; +import org.simantics.databoard.Bindings; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; +import org.simantics.db.common.request.PossibleObjectWithType; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; import org.simantics.db.exception.ServiceException; import org.simantics.db.layer0.request.PossibleModel; +import org.simantics.operation.Layer0X; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.manager.SysdynModel; import org.simantics.sysdyn.representation.Configuration; @@ -48,10 +52,12 @@ public class UnitUtils { HashMap units = UnitUtils.findUnits(graph, model, configuration, components); try { - node.getUnits(units); + node.getUnits(units, allowEquivalents(graph, model)); } catch (UnitCheckingException e) { return e.getMessage(); - } + } catch (DatabaseException e) { + e.printStackTrace(); + } } catch (ParseException e) { e.printStackTrace(); @@ -59,6 +65,30 @@ public class UnitUtils { return null; } + /** + * Determine if the Unit Equivalents checkbox is selected + * @param graph + * @param model SysdynModel of which configuration is queried + * @return true iff equivalent units are allowed + * @throws DatabaseException + */ + public static boolean allowEquivalents(ReadGraph graph, SysdynModel model) throws DatabaseException { + Resource modelResource = graph.syncRequest(new PossibleModel(model.getConfigurationResource())); + SysdynResource sr = SysdynResource.getInstance(graph); + Resource unitIssueSource = graph.syncRequest( + new PossibleObjectWithType(modelResource, + Layer0X.getInstance(graph).Activates, + sr.Validations_Units_UnitIssueSource)); + if(unitIssueSource == null) + return false; + + Boolean result = graph.getPossibleRelatedValue(unitIssueSource, sr.Validations_Units_UnitIssueSource_allowEquivalents, Bindings.BOOLEAN); + if(result == null) + result = false; + + return result; + } + public static String matchUnits(ReadGraph graph, SysdynModel model, Configuration configuration, String unit, String expression) { if(unit == null) return "Unit not defined"; @@ -77,14 +107,17 @@ public class UnitUtils { leftReader.close(); try { - UnitResult rightUnits = right.getUnits(units); - UnitResult leftUnits = left.getUnits(null); + boolean allowEquivalents = allowEquivalents(graph, model); + UnitResult rightUnits = right.getUnits(units, allowEquivalents); + UnitResult leftUnits = left.getUnits(null, allowEquivalents); if(!rightUnits.equals(leftUnits)) return leftUnits.getCleanFullUnit() + " != " + rightUnits.getCleanFullUnit(); } catch (UnitCheckingException e) { return e.getMessage(); - } + } catch (DatabaseException e) { + e.printStackTrace(); + } } catch (ParseException e) { e.printStackTrace(); @@ -180,7 +213,7 @@ public class UnitUtils { } - public static String matchUnits(String left, String right) throws DatabaseException { + public static String matchUnits(String left, String right, boolean allowEquivalents) throws DatabaseException { if(left == null || right == null || left.isEmpty() || right.isEmpty()) return "No unit defined"; @@ -197,8 +230,8 @@ public class UnitUtils { rightReader.close(); try { - UnitResult leftUnits = leftNode.getUnits(null); - UnitResult rightUnits = rightNode.getUnits(null); + UnitResult leftUnits = leftNode.getUnits(null, allowEquivalents); + UnitResult rightUnits = rightNode.getUnits(null, allowEquivalents); if(!rightUnits.equals(leftUnits)) return leftUnits.getCleanFullUnit() + " != " + rightUnits.getCleanFullUnit(); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java index 399d04d8..2233c88e 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitCheckingNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser; @@ -22,15 +23,15 @@ public class UnitCheckingNode extends SimpleNode { super(id); } - public UnitResult getUnits(HashMap units) throws UnitCheckingException{ - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException{ + UnitResult result = new UnitResult(allowEquivalents); if(jjtGetNumChildren() == 0){ String node = printNode(); result.append(node); } else { for(int i = 0; i < jjtGetNumChildren(); i++) { - result.appendResult(((UnitCheckingNode)jjtGetChild(i)).getUnits(units)); + result.appendResult(((UnitCheckingNode)jjtGetChild(i)).getUnits(units, allowEquivalents)); } } return result; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt index 60acd1a6..8227241b 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/UnitParser.jjt @@ -44,7 +44,7 @@ TOKEN: | "*" | "/" | ".*" | "./" | "^" | ".^" | "=" | ":=" -| +| | { matchedToken.image = matchedToken.image.substring(1,matchedToken.image.length()-1); } | diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java index 9c3374c8..026b8a1c 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/AddOp.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class AddOp extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class AddOp extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.OPERATOR); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java index d844bb7c..396bcb1d 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Arithmetic.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Arithmetic extends UnitCheckingNode { @@ -30,8 +32,8 @@ public class Arithmetic extends UnitCheckingNode { @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); UnitCheckingNode base = null; UnitCheckingNode operator = null; @@ -39,12 +41,12 @@ public class Arithmetic extends UnitCheckingNode { for(int i = 0; i < jjtGetNumChildren(); i++) { candidateNode = ((UnitCheckingNode)jjtGetChild(i)); - UnitResult candidateUnits = candidateNode.getUnits(units); + UnitResult candidateUnits = candidateNode.getUnits(units, allowEquivalents); if(candidateUnits.getUnitType() == UnitType.OPERATOR) { continue; } else if(base == null || result.getUnitType() == UnitType.SCALAR || result.getUnitType() == UnitType.ANY) { base = ((UnitCheckingNode)jjtGetChild(i)); - result.appendResult(base.getUnits(units)); + result.appendResult(base.getUnits(units, allowEquivalents)); continue; } else if(candidateUnits.getUnitType() == UnitType.SCALAR) { continue; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ArrayDefinition.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ArrayDefinition.java index 4b46e718..7b300b21 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ArrayDefinition.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ArrayDefinition.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -21,6 +22,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class ArrayDefinition extends UnitCheckingNode { @@ -31,8 +33,8 @@ public class ArrayDefinition extends UnitCheckingNode { @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); result.setUnitType(UnitType.SCALAR); UnitCheckingNode base = null; @@ -41,13 +43,13 @@ public class ArrayDefinition extends UnitCheckingNode { FunctionArguments functionArguments = (FunctionArguments) jjtGetChild(0); for(UnitCheckingNode candidateNode : gatherExpressions(functionArguments, new ArrayList())) { - UnitResult candidateUnits = candidateNode.getUnits(units); + UnitResult candidateUnits = candidateNode.getUnits(units, allowEquivalents); if(candidateUnits.getUnitType() == UnitType.SCALAR) { continue; } else if(base == null) { base = candidateNode; UnitType oldUnitType = result.getUnitType(); - result.appendResult(base.getUnits(units)); + result.appendResult(base.getUnits(units, allowEquivalents)); /* * Make sure unit type persist diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java index f5399282..c110fcb2 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ComponentReferenceFull.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -23,6 +24,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class ComponentReferenceFull extends UnitCheckingNode { @@ -31,12 +33,12 @@ public class ComponentReferenceFull extends UnitCheckingNode { super(id); } - protected UnitResult parseUnits(String units) { + protected UnitResult parseUnits(String units, boolean allowEquivalents) { StringReader sr = new StringReader(units); UnitParser parser = new UnitParser(sr); try { UnitCheckingNode node = (UnitCheckingNode) parser.expr(); - return node.getUnits(null); + return node.getUnits(null, allowEquivalents); } catch (ParseException e) { e.printStackTrace(); } catch (UnitCheckingException e) { @@ -46,11 +48,11 @@ public class ComponentReferenceFull extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { String node = printNode(); if("dmnl".equals(node)) { - UnitResult result = new UnitResult(); + UnitResult result = new UnitResult(allowEquivalents); result.setUnitType(UnitType.DMNL); return result; } @@ -59,10 +61,10 @@ public class ComponentReferenceFull extends UnitCheckingNode { if(!units.containsKey(node) || units.get(node) == null) throw new UnitCheckingException("No units defined for " + node); else { - return parseUnits(units.get(node)); + return parseUnits(units.get(node), allowEquivalents); } } else { - UnitResult result = new UnitResult(); + UnitResult result = new UnitResult(allowEquivalents); result.addDivident(node); result.append(node); return result; diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java index 4c2ec48e..2c090ea2 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Divide.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Divide extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class Divide extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.OPERATOR); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java index 6e5b1fe8..369f67b6 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Factor.java @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -31,8 +32,8 @@ public class Factor extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); UnitCheckingNode current = null; UnitCheckingNode operator = null; @@ -40,10 +41,10 @@ public class Factor extends UnitCheckingNode { for(int i = 0; i < jjtGetNumChildren(); i++) { current = ((UnitCheckingNode)jjtGetChild(i)); - UnitResult currentUnits = current.getUnits(units); + UnitResult currentUnits = current.getUnits(units, allowEquivalents); if(currentUnits.getUnitType() == UnitType.ANY) { - result = new UnitResult(); + result = new UnitResult(allowEquivalents); result.setUnitType(UnitType.ANY); return result; } else if(currentUnits.getUnitType() == UnitType.OPERATOR) { @@ -58,7 +59,7 @@ public class Factor extends UnitCheckingNode { UnitType unitType = currentUnits.getUnitType(); if(unitType == UnitType.SCALAR) { int exponent; - UnitResult baseUnits = base.getUnits(units); + UnitResult baseUnits = base.getUnits(units, allowEquivalents); try { exponent = Integer.valueOf(currentUnits.getFullUnit()); } catch (NumberFormatException e) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java index 0d934f12..4a185f7b 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/ForIndex.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -19,6 +20,7 @@ import org.simantics.sysdyn.unitParser.UnitCheckingNode; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class ForIndex extends UnitCheckingNode { @@ -28,8 +30,8 @@ public class ForIndex extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - return new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + return new UnitResult(allowEquivalents); } } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/FunctionCall.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/FunctionCall.java index e165cc56..a99be2ec 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/FunctionCall.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/FunctionCall.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class FunctionCall extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class FunctionCall extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); result.setUnitType(UnitType.ANY); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java index 3529a15e..4234acaa 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/IfThenElse.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -19,6 +20,7 @@ import org.simantics.sysdyn.unitParser.UnitCheckingNode; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class IfThenElse extends UnitCheckingNode { @@ -29,14 +31,14 @@ public class IfThenElse extends UnitCheckingNode { @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { UnitResult base = null; UnitCheckingNode baseNode = null; UnitCheckingNode candidateNode = null; for(int i = 0; i < jjtGetNumChildren(); i++) { candidateNode = ((UnitCheckingNode)jjtGetChild(i)); - UnitResult candidateUnits = candidateNode.getUnits(units); + UnitResult candidateUnits = candidateNode.getUnits(units, allowEquivalents); if(!(candidateNode instanceof Condition)) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java index 53cdc783..43b13aae 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Multiplication.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Multiplication extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class Multiplication extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.OPERATOR); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java index 14799461..ab1d9adf 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Power.java @@ -29,8 +29,8 @@ public class Power extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.OPERATOR); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java index 57098ba1..d7a62ade 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/RelOp.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class RelOp extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class RelOp extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.OPERATOR); return result; } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java index 6d8711c1..2fd22f3b 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Relation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -19,6 +20,7 @@ import org.simantics.sysdyn.unitParser.UnitCheckingNode; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Relation extends UnitCheckingNode { @@ -28,8 +30,8 @@ public class Relation extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); UnitCheckingNode base = null; UnitCheckingNode operator = null; @@ -40,14 +42,14 @@ public class Relation extends UnitCheckingNode { base = ((UnitCheckingNode)jjtGetChild(1)); if(base instanceof Arithmetic) { - result.appendResult(base.getUnits(units)); + result.appendResult(base.getUnits(units, allowEquivalents)); for(int i = 2; i < jjtGetNumChildren(); i = i + 2) { candidateNode = ((UnitCheckingNode)jjtGetChild(i)); if(!(candidateNode instanceof Value)) { operator = ((UnitCheckingNode)jjtGetChild(i-1)); - UnitResult candidateUnits = candidateNode.getUnits(units); + UnitResult candidateUnits = candidateNode.getUnits(units, allowEquivalents); if(!result.equals(candidateUnits)) { result.equals(candidateUnits); throw new UnitCheckingException("Not equals exception: " + diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java index 77f9c409..344cf7eb 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Term.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -21,6 +22,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Term extends UnitCheckingNode { @@ -30,8 +32,8 @@ public class Term extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = new UnitResult(); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = new UnitResult(allowEquivalents); UnitCheckingNode current = null; UnitCheckingNode operator = null; @@ -39,10 +41,10 @@ public class Term extends UnitCheckingNode { for(int i = 0; i < jjtGetNumChildren(); i++) { current = ((UnitCheckingNode)jjtGetChild(i)); - UnitResult currentUnits = current.getUnits(units); + UnitResult currentUnits = current.getUnits(units, allowEquivalents); if(currentUnits.getUnitType() == UnitType.ANY) { - result = new UnitResult(); + result = new UnitResult(allowEquivalents); result.setUnitType(UnitType.ANY); return result; } else if(currentUnits.getUnitType() == UnitType.OPERATOR) { diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java index 72fcb73d..74cf4dd9 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/UnitResult.java @@ -28,6 +28,7 @@ import java.util.Iterator; * clean representation of the unit. ( e.g. m * s / m -> s ) * * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class UnitResult { @@ -39,7 +40,47 @@ public class UnitResult { private StringBuilder fullUnit = new StringBuilder(); private UnitType unitType; - public UnitResult() { + // Equivalent forms of units: + private final Equivalent[] EQUIVALENTS = { + new Equivalent("$","$s","dollar","dollars","usd"), + new Equivalent("\u20ac","\u20acs","eur","euro","euros","e","ecu"), + new Equivalent("£","£s","pound","pounds","gbp"), + new Equivalent("Unit","Units"), + new Equivalent("Person","People","Persons"), + new Equivalent("second","seconds","sec","s"), + new Equivalent("minute","minutes","min"), + new Equivalent("hour","hours","h","hr"), + new Equivalent("day","days","d"), + new Equivalent("month","months","mon","mth","mo","mos"), + new Equivalent("year","years","a","y","yr") + }; + private boolean allowEquivalents; + + private class Equivalent { + public ArrayList forms; + + Equivalent(String ... forms) { + this.forms = new ArrayList(); + for (String f : forms) + this.forms.add(f); + } + + public boolean contains(String form) { + for (String f : forms) + if (f.equalsIgnoreCase(form)) + return true; + return false; + } + + public String getDefault() { + if (forms.size() > 0) + return forms.get(0); + else return null; + } + } + + public UnitResult(boolean allowEquivalents) { + this.allowEquivalents = allowEquivalents; setUnitType(UnitType.NORMAL); } @@ -159,6 +200,22 @@ public class UnitResult { if(copyDividers1.size() != copyDividers2.size()) return false; + if (allowEquivalents) { + // Replace and sort all once again. + for(int i = 0; i < copyDividents1.size(); i++) { + copyDividents1.set(i, getDefaultForm(copyDividents1.get(i))); + copyDividents2.set(i, getDefaultForm(copyDividents2.get(i))); + Collections.sort(copyDividents1); + Collections.sort(copyDividents2); + } + for(int i = 0; i < copyDividers1.size(); i++) { + copyDividers1.set(i, getDefaultForm(copyDividers1.get(i))); + copyDividers2.set(i, getDefaultForm(copyDividers2.get(i))); + Collections.sort(copyDividers1); + Collections.sort(copyDividers2); + } + } + for(int i = 0; i < copyDividents1.size(); i++) { String a = copyDividents1.get(i); String b = copyDividents2.get(i); @@ -166,7 +223,6 @@ public class UnitResult { return false; } } - for(int i = 0; i < copyDividers1.size(); i++) { String a = copyDividers1.get(i); String b = copyDividers2.get(i); @@ -178,7 +234,19 @@ public class UnitResult { return true; } - public void reduceUnitLists(ArrayList originalDividents, ArrayList copyDividents, ArrayList copyDividers) { + /** + * Get the default form of a unit (e.g. dollars -> $). + * @param unit + * @return default form of unit + */ + private String getDefaultForm(String unit) { + for (Equivalent e : EQUIVALENTS) + if (e.contains(unit)) + return e.getDefault(); + return unit; + } + + public void reduceUnitLists(ArrayList originalDividents, ArrayList copyDividents, ArrayList copyDividers) { for(String s : originalDividents) { if(copyDividers.contains(s)) { copyDividers.remove(s); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java index 1ba0fc00..7e26c569 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/Value.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 Association for Decentralized Information Management in + * Copyright (c) 2013-2014 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,6 +8,7 @@ * * Contributors: * Semantum Oy - initial API and implementation + * VTT Technical Research Centre of Finland *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; @@ -20,6 +21,7 @@ import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; /** * See UnitCheckingNodeFactory for mapping * @author Teemu Lempinen + * @author Tuomas Miettinen * */ public class Value extends UnitCheckingNode { @@ -29,8 +31,8 @@ public class Value extends UnitCheckingNode { } @Override - public UnitResult getUnits(HashMap units) throws UnitCheckingException { - UnitResult result = super.getUnits(units); + public UnitResult getUnits(HashMap units, boolean allowEquivalents) throws UnitCheckingException { + UnitResult result = super.getUnits(units, allowEquivalents); result.setUnitType(UnitType.SCALAR); return result; } -- 2.47.1