From: miettinen Date: Wed, 29 Jan 2014 10:04:48 +0000 (+0000) Subject: Unit validation for Sysdyn functions: determination of function output unit based... X-Git-Tag: 1.8.1~151 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=bfa8df093e9c7f55e798b1cbe776dbd7d6687de3;p=simantics%2Fsysdyn.git Unit validation for Sysdyn functions: determination of function output unit based on input units (refs #4320). git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28722 ac1ea38d-2e2b-0410-8846-a27921b304fc --- diff --git a/org.simantics.sysdyn.ontology/graph.tg b/org.simantics.sysdyn.ontology/graph.tg index 130eceff..4d3bfdfb 100644 Binary files a/org.simantics.sysdyn.ontology/graph.tg and b/org.simantics.sysdyn.ontology/graph.tg differ diff --git a/org.simantics.sysdyn.ontology/graph/ModelicaFunctions.pgraph b/org.simantics.sysdyn.ontology/graph/ModelicaFunctions.pgraph index 942591ad..86ea5cd5 100644 --- a/org.simantics.sysdyn.ontology/graph/ModelicaFunctions.pgraph +++ b/org.simantics.sysdyn.ontology/graph/ModelicaFunctions.pgraph @@ -148,13 +148,13 @@ Cosine. Returns the cosine of u, with -INF < u < INF Argument u needs to be an Integer or Real expression.""" SYSDYN.SysdynModelicaFunction.inputs _ : L0.List @L0.list - MF.ceil.u : SYSDYN.SysdynModelicaFunction.Input + MF.cos.u : SYSDYN.SysdynModelicaFunction.Input SYSDYN.Variable.type "Real" SYSDYN.SysdynModelicaFunction.optional false SYSDYN.SysdynModelicaFunction.unit "ANY" SYSDYN.SysdynModelicaFunction.outputs _ : L0.List @L0.list - MF.ceil.y : SYSDYN.SysdynModelicaFunction.Output + MF.cos.y : SYSDYN.SysdynModelicaFunction.Output SYSDYN.Variable.type "Real" SYSDYN.SysdynModelicaFunction.unit "1" SYSDYN.SysdynModelicaFunction.modelicaFunctionInterface """ input Real u; @@ -364,7 +364,7 @@ Returns the base e logarithm of u, with u > 0. Argument u needs to be an Integer @L0.list MF.log.y : SYSDYN.SysdynModelicaFunction.Output SYSDYN.Variable.type "Real" - SYSDYN.SysdynModelicaFunction.unit "1" + SYSDYN.SysdynModelicaFunction.unit "1" SYSDYN.SysdynModelicaFunction.modelicaFunctionInterface """ input Real u(unit = "1"); output Real y(unit = "1");""" diff --git a/org.simantics.sysdyn.ontology/graph/VensimFunctions.pgraph b/org.simantics.sysdyn.ontology/graph/VensimFunctions.pgraph index 3684f3f0..87c506f6 100644 --- a/org.simantics.sysdyn.ontology/graph/VensimFunctions.pgraph +++ b/org.simantics.sysdyn.ontology/graph/VensimFunctions.pgraph @@ -315,7 +315,7 @@ Returns 0.0 until the step time and then returns height.""" VF.STEP.height : SYSDYN.SysdynModelicaFunction.Input SYSDYN.Variable.type "Real" SYSDYN.SysdynModelicaFunction.optional false - SYSDYN.SysdynModelicaFunction.unit ".p" + SYSDYN.SysdynModelicaFunction.unit "'p" VF.STEP.stepTime : SYSDYN.SysdynModelicaFunction.Input SYSDYN.Variable.type "Real" SYSDYN.SysdynModelicaFunction.optional false diff --git a/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java b/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java index 11f5bf51..ef34edf7 100644 --- a/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java +++ b/org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java @@ -123,10 +123,11 @@ public class SysdynResource { public final Resource Built$in_Functions_Modelica_Functions_atan_u; public final Resource Built$in_Functions_Modelica_Functions_atan_y; public final Resource Built$in_Functions_Modelica_Functions_ceil; - public final Resource Built$in_Functions_Modelica_Functions_ceil_u; public final Resource Built$in_Functions_Modelica_Functions_ceil_x; public final Resource Built$in_Functions_Modelica_Functions_ceil_y; public final Resource Built$in_Functions_Modelica_Functions_cos; + public final Resource Built$in_Functions_Modelica_Functions_cos_u; + public final Resource Built$in_Functions_Modelica_Functions_cos_y; public final Resource Built$in_Functions_Modelica_Functions_cosh; public final Resource Built$in_Functions_Modelica_Functions_cosh_u; public final Resource Built$in_Functions_Modelica_Functions_cosh_y; @@ -890,10 +891,11 @@ public class SysdynResource { public static final String Built$in_Functions_Modelica_Functions_atan_u = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/atan/u"; public static final String Built$in_Functions_Modelica_Functions_atan_y = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/atan/y"; public static final String Built$in_Functions_Modelica_Functions_ceil = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/ceil"; - public static final String Built$in_Functions_Modelica_Functions_ceil_u = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/ceil/u"; public static final String Built$in_Functions_Modelica_Functions_ceil_x = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/ceil/x"; public static final String Built$in_Functions_Modelica_Functions_ceil_y = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/ceil/y"; public static final String Built$in_Functions_Modelica_Functions_cos = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cos"; + public static final String Built$in_Functions_Modelica_Functions_cos_u = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cos/u"; + public static final String Built$in_Functions_Modelica_Functions_cos_y = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cos/y"; public static final String Built$in_Functions_Modelica_Functions_cosh = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cosh"; public static final String Built$in_Functions_Modelica_Functions_cosh_u = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cosh/u"; public static final String Built$in_Functions_Modelica_Functions_cosh_y = "http://www.simantics.org/Sysdyn-1.1/Built-in%20Functions/Modelica%20Functions/cosh/y"; @@ -1667,10 +1669,11 @@ public class SysdynResource { Built$in_Functions_Modelica_Functions_atan_u = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_atan_u); Built$in_Functions_Modelica_Functions_atan_y = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_atan_y); Built$in_Functions_Modelica_Functions_ceil = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_ceil); - Built$in_Functions_Modelica_Functions_ceil_u = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_ceil_u); Built$in_Functions_Modelica_Functions_ceil_x = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_ceil_x); Built$in_Functions_Modelica_Functions_ceil_y = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_ceil_y); Built$in_Functions_Modelica_Functions_cos = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cos); + Built$in_Functions_Modelica_Functions_cos_u = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cos_u); + Built$in_Functions_Modelica_Functions_cos_y = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cos_y); Built$in_Functions_Modelica_Functions_cosh = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cosh); Built$in_Functions_Modelica_Functions_cosh_u = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cosh_u); Built$in_Functions_Modelica_Functions_cosh_y = getResourceOrNull(graph, URIs.Built$in_Functions_Modelica_Functions_cosh_y); diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java index 5a394332..56488ec7 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java @@ -110,7 +110,8 @@ public class ShortcutTabWidget implements Widget { for(Function function : functionList){ item = new TableItem(functionTable, SWT.NONE); item.setText(function.getName() + "()"); - item.setData(function.getName() + "(" + function.getParameterList() + ")"); + String parameterList = Function.inputListToString(function.getInputList()); + item.setData(function.getName() + "(" + parameterList + ")"); item.setImage(getImage(this.resourceManager, function)); } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/CompletionProcessor.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/CompletionProcessor.java index 9f640b22..af2ea930 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/CompletionProcessor.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/CompletionProcessor.java @@ -171,13 +171,14 @@ public class CompletionProcessor implements IContentAssistProcessor { for (Function function : functions) { if (token.length() == 0 || function.getName().toUpperCase().startsWith(token.toUpperCase())) { Image image = ShortcutTabWidget.getImage(resourceManager, function); + String parameterList = Function.inputListToString(function.getInputList()); array.add(new CompletionProposal( - function.getName() + "(" + function.getParameterList() + ")", + function.getName() + "(" + parameterList + ")", offset - token.length(), token.length(), function.getName().length() + 1, image, - function.getName() + "(" + function.getParameterList() + ")", + function.getName() + "(" + parameterList + ")", null, function.getDescriptionHTML())); } diff --git a/org.simantics.sysdyn/META-INF/MANIFEST.MF b/org.simantics.sysdyn/META-INF/MANIFEST.MF index 6780adff..6c9fef50 100644 --- a/org.simantics.sysdyn/META-INF/MANIFEST.MF +++ b/org.simantics.sysdyn/META-INF/MANIFEST.MF @@ -56,5 +56,6 @@ Export-Package: org.simantics.sysdyn, Bundle-Activator: org.simantics.sysdyn.Activator Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.ui, + org.simantics.sysdyn.utils, org.simantics.ui Bundle-Vendor: VTT Technical Reserarch Centre of Finland 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 fb04557a..a82b1c52 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 @@ -12,13 +12,19 @@ *******************************************************************************/ package org.simantics.sysdyn.unitParser.nodes; +import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; +import org.simantics.sysdyn.unitParser.ParseException; import org.simantics.sysdyn.unitParser.UnitCheckingException; import org.simantics.sysdyn.unitParser.UnitCheckingNode; +import org.simantics.sysdyn.unitParser.UnitParser; import org.simantics.sysdyn.unitParser.nodes.UnitResult.UnitType; import org.simantics.sysdyn.utils.Function; +import org.simantics.sysdyn.utils.Function.Input; +import org.simantics.sysdyn.utils.Function.Output; +import org.simantics.sysdyn.utils.Function.Parameter; /** * See UnitCheckingNodeFactory for mapping @@ -31,12 +37,182 @@ public class FunctionCall extends UnitCheckingNode { public FunctionCall(int id) { super(id); } - + @Override public UnitResult getUnits(HashMap units, ArrayList functions, boolean allowEquivalents) throws UnitCheckingException { UnitResult result = new UnitResult(allowEquivalents); - result.setUnitType(UnitType.ANY); - return result; + UnitCheckingNode functionLabelNode = ((UnitCheckingNode)jjtGetChild(0)); + String functionLabel = functionLabelNode.printNode(); + + UnitCheckingNode functionArgumentsWithParenthesisNode = ((UnitCheckingNode)jjtGetChild(1)); + UnitCheckingNode functionArgumentsNode = ((UnitCheckingNode)functionArgumentsWithParenthesisNode.jjtGetChild(1)); + + UnitCheckingException u = null; + + for (Function f : functions) { + if (f.getName().equals(functionLabel)) { + // Get the expected inputs + ArrayList inputs = f.getInputList(); + // Get arguments from parser. + ArrayList argumentUnits = getArgumentsOf(functionArgumentsNode, units, functions, allowEquivalents); + + // If the function input parameter units are OK, set the output unit accordingly. + if (matchInputs(inputs, argumentUnits)) { + result = setUnitResult(units, result, inputs, argumentUnits, f, functions, allowEquivalents); + return result; + } + + // Create the exception when we first time arrive here, since the functions + // are sorted so that scalar functions are before vector ones and there are + // a few duplicates, so this way the exception message is more likely useful. + if (u == null) + u = getException(functionLabelNode, inputs, argumentUnits); + // There may be similarly named functions, so if one doesn't succeed, go through the rest of the list anyway. + } + } + + if (u == null) { + result.setUnitType(UnitType.ANY); // The function was not found. + return result; + } + + throw u; } + private UnitResult setUnitResult( + HashMap units, + UnitResult result, + ArrayList inputs, + ArrayList argumentUnits, + Function f, + ArrayList functions, + boolean allowEquivalents) throws UnitCheckingException { + Output o = f.getOutputList().get(0); // Support only single return value functions. + + if (Parameter.ANY.equals(o.unit)) { + result.setUnitType(UnitType.ANY); + } else if ("1".equals(o.unit)) { // TODO: see if this should be changed to something else + result.setUnitType(UnitType.SCALAR); + } else { + // Replace TIME with actual time unit. + String timeUnit = units.get("time"); + String timeReplaced = o.unit.replace(Parameter.TIME, timeUnit); + + // Replace 'p, 'q, etc. in output with units from actual inputs. + HashMap correspondencies = getReplacementUnitCorrespondencies(inputs, argumentUnits); + String correspondenciesReplaced = replaceCorrespondencies(f, timeReplaced, correspondencies); + + try { + StringReader outputReader = new StringReader(correspondenciesReplaced); + UnitParser outputParser = new UnitParser(outputReader); + UnitCheckingNode output; + output = (UnitCheckingNode) outputParser.expr(); + outputReader.close(); + result.appendResult(output.getUnits(null, functions, allowEquivalents)); + result.setUnitType(UnitType.NORMAL); + } catch (ParseException e) { + e.printStackTrace(); + } catch (UnitCheckingException e) { + e.printStackTrace(); + } + + } + + return result; + } + + private String replaceCorrespondencies(Function f, String original, + HashMap correspondencies) throws UnitCheckingException { + int index; + String ret = new String(original); + // Go through the unit as long as there are part of form 'p, 'q, etc. and replace them. + while ((index = ret.indexOf('\'')) >= 0) { + String replaced = ret.substring(index, index + 2); // The replaced units are always of length 2. + try { + ret = ret.replace(replaced, correspondencies.get(replaced)); + } catch (NullPointerException npe) { + throw new UnitCheckingException("Function " + f.getName() + " output unit could not be determined. Replacement unit " + + replaced + " not found in input unit definitions."); + } + } + return ret; + } + + private HashMap getReplacementUnitCorrespondencies( + ArrayList inputs, ArrayList argumentUnits) { + // TODO: General case. Currently each 'p, 'q etc. must exist as an atomic unit. + HashMap correspondencies = new HashMap(); + for (int i = 0; i < inputs.size(); ++i) { + if (inputs.get(i).unit.matches("'[a-zA-Z]")) { + if (argumentUnits.size() > i) { // Skip optional + correspondencies.put(inputs.get(i).unit, argumentUnits.get(i).getCleanFullUnit()); + } + } + } + return correspondencies; + } + + private boolean matchInputs(ArrayList inputs, + ArrayList argumentUnits) { + // TODO Auto-generated method stub + return true; + } + + /** + * Get the exception (text) shown to user. + * @param functionLabelNode + * @param inputs + * @param argumentUnits + * @return + */ + private UnitCheckingException getException(UnitCheckingNode functionLabelNode, ArrayList inputs, ArrayList argumentUnits) { + String exception = new String("Function arguments do not have correct units. Expected " + functionLabelNode.printNode() + "("); + + for (int i = 0; i < inputs.size(); ++i) { + Input input = inputs.get(i); + if (i == 0) + exception += " "; + exception += "[" + input.unit + "]"; + if (input.variableLength) { + exception += "... "; + } + + if (i != inputs.size() - 1) + exception += ", "; + } + exception += " ), got " + functionLabelNode.printNode() + "("; + for (int i = 0; i < argumentUnits.size(); ++i) { + UnitResult argumentUnit = argumentUnits.get(i); + if (i == 0) + exception += " "; + exception += "[" + argumentUnit.getCleanFullUnit() + "]"; + + if (i != inputs.size() - 1) + exception += ", "; + + } + exception += " )."; + + return new UnitCheckingException(exception); + } + + private ArrayList getArgumentsOf( + UnitCheckingNode functionArgumentsNode, + HashMap units, + ArrayList functions, + boolean allowEquivalents) throws UnitCheckingException { + // Arguments are defined recursively in OpenModelica + ArrayList argumentUnits = new ArrayList(); + if (functionArgumentsNode instanceof FunctionArguments) { + UnitCheckingNode firstArg = ((UnitCheckingNode) functionArgumentsNode.jjtGetChild(0)); + argumentUnits.add(firstArg.getUnits(units, functions, allowEquivalents)); + if (functionArgumentsNode.jjtGetNumChildren() > 1) { + UnitCheckingNode next = ((UnitCheckingNode) functionArgumentsNode.jjtGetChild(1)); + argumentUnits.addAll(getArgumentsOf(next, units, functions, allowEquivalents)); + } + + } + return argumentUnits; + } + } diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/Function.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/Function.java index b01c62f6..90d20239 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/Function.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/Function.java @@ -26,13 +26,24 @@ public class Function implements Comparable{ private final String name; private final Type type; - private final String parameterList; + private final ArrayList inputList; + private final ArrayList outputList; private final String description; public static class Parameter { + public static final String ANY = "ANY"; + public static final String TIME = "TIME"; public String name; - public String unit = "1"; + public String unit = ANY; + } + + public static class Input extends Parameter { public boolean variableLength = false; + public boolean optional = false; + public ArrayList variableLengthLabels; + } + + public static class Output extends Parameter { } public enum Type { @@ -44,16 +55,26 @@ public class Function implements Comparable{ VENSIM } - public Function(String name, ArrayList parameterList, Type type, String description){ + public Function( + String name, + ArrayList inputList, + ArrayList outputList, + Type type, + String description){ + this.name = new String(name); this.type = type; - String parameterListString = parameterListToString(parameterList); - if (parameterListString != null) - this.parameterList = new String(parameterListString); + if (inputList != null) + this.inputList = inputList; + else + this.inputList = new ArrayList(); + + if (outputList != null) + this.outputList = outputList; else - this.parameterList = new String(""); + this.outputList = new ArrayList(); if (description != null) this.description = new String(description); @@ -61,21 +82,42 @@ public class Function implements Comparable{ this.description = null; } - public static String parameterListToString(ArrayList parameterList) { + /** + * Convert list of Inputs to string + * @param inputList list of Inputs + * @return printable form of inputs (for function declaration) + */ + public static String inputListToString(ArrayList inputList) { String inputStr = null; - for (Parameter p : parameterList) { + for (Input p : inputList) { + String pName; + // Variable length parameter list + if (p.variableLength) { + pName = ""; + for (String label : p.variableLengthLabels) { + pName += label + ", "; + } + pName += "..."; + } else { + pName = p.name; + } + if (inputStr == null) - inputStr = new String(p.name); + inputStr = new String(pName); else - inputStr += ", " + p.name; + inputStr += ", " + pName; } return inputStr; } - public String getParameterList() { - return parameterList; + public ArrayList getInputList() { + return inputList; } - + + public ArrayList getOutputList() { + return outputList; + } + public String getName() { return name; } @@ -96,34 +138,40 @@ public class Function implements Comparable{ } /** - * Get Modelica function parameters + * Get Modelica function input parameters * @param graph * @param sr * @param r Resource of the Modelica function - * @return String in which the paramters are ", " delimited + * @return ArrayList of Inputs * @throws DatabaseException */ - public static ArrayList getFunctionInputs(ReadGraph graph, SysdynResource sr, Resource r) throws DatabaseException { + public static ArrayList getFunctionInputs(ReadGraph graph, SysdynResource sr, Resource r) throws DatabaseException { Resource inputs = graph.getPossibleObject(r, sr.SysdynModelicaFunction_inputs); - ArrayList inputParameters = new ArrayList(); + ArrayList inputParameters = new ArrayList(); if (inputs != null) { for (Resource input : ListUtils.toList(graph, inputs)) { - Parameter inputParameter = new Parameter(); + // Convert the Resource into Parameter; + Input inputParameter = new Input(); + inputParameter.name = NameUtils.getSafeName(graph, input); + inputParameter.optional = graph.getPossibleRelatedValue( + input, + sr.SysdynModelicaFunction_optional, + Bindings.BOOLEAN); + inputParameter.unit = graph.getPossibleRelatedValue( + input, + sr.SysdynModelicaFunction_unit, + Bindings.STRING); if (graph.isInstanceOf(input, sr.SysdynModelicaFunction_VariableLengthInput)) { - inputParameter.name = ""; inputParameter.variableLength = true; Resource shownLabels = graph.getPossibleObject( input, sr.SysdynModelicaFunction_VariableLengthInput_shownLabels); + inputParameter.variableLengthLabels = new ArrayList(); if (shownLabels != null) { for (Resource label : ListUtils.toList(graph, shownLabels)) { - inputParameter.name += NameUtils.getSafeName(graph, label); - inputParameter.name += ", "; + inputParameter.variableLengthLabels.add(NameUtils.getSafeName(graph, label)); } } - inputParameter.name += "..."; - } else { - inputParameter.name = NameUtils.getSafeName(graph, input); } inputParameters.add(inputParameter); @@ -131,6 +179,33 @@ public class Function implements Comparable{ } return inputParameters; } + + /** + * Get Modelica function outputs + * @param graph + * @param sr + * @param r Resource of the Modelica function + * @return ArrayList of Outputs + * @throws DatabaseException + */ + protected static ArrayList getFunctionOutputs(ReadGraph graph, + SysdynResource sr, Resource r) throws DatabaseException { + Resource outputs = graph.getPossibleObject(r, sr.SysdynModelicaFunction_outputs); + ArrayList outputParameters = new ArrayList(1); + if (outputs != null) { + for (Resource output : ListUtils.toList(graph, outputs)) { + // Convert the Resource into Parameter; + Output outputParameter = new Output(); + outputParameter.name = NameUtils.getSafeName(graph, output); + outputParameter.unit = graph.getPossibleRelatedValue( + output, + sr.SysdynModelicaFunction_unit, + Bindings.STRING); + outputParameters.add(outputParameter); + } + } + return outputParameters; + } public static String getFunctionDescription(ReadGraph graph, Resource r) throws DatabaseException { String descriptionStr = null; @@ -152,9 +227,10 @@ public class Function implements Comparable{ Resource functionLibrary = graph.getPossibleResource(functionTypeUri); for(Resource r : graph.syncRequest(new ObjectsWithType(functionLibrary, l0.ConsistsOf, sr.SysdynModelicaFunction))) { String name = NameUtils.getSafeName(graph, r); - ArrayList inputs = getFunctionInputs(graph, sr, r); + ArrayList inputs = getFunctionInputs(graph, sr, r); + ArrayList outputs = getFunctionOutputs(graph, sr, r); String description = getFunctionDescription(graph, r); - functions.add(new Function(name, inputs, functionType, description)); + functions.add(new Function(name, inputs, outputs, functionType, description)); } return functions; } @@ -238,7 +314,8 @@ public class Function implements Comparable{ // Create a Function object out of the Resource Function sharedFunction = new Function(fullName, - Function.getFunctionInputs(graph, sr, function), + Function.getFunctionInputs(graph, sr, function), + Function.getFunctionOutputs(graph, sr, function), Type.SHARED, Function.getFunctionDescription(graph, function)); sharedFunctions.add(sharedFunction); @@ -254,7 +331,7 @@ public class Function implements Comparable{ return functions; } - /** + /** * Get all user defined Modelica functions. * @param variable of which model is in question * @return ArrayList containing all user defined functions. @@ -290,6 +367,7 @@ public class Function implements Comparable{ // Create a Function object out of the Resource Function userFunction = new Function(fullName, Function.getFunctionInputs(graph, sr, function), + Function.getFunctionOutputs(graph, sr, function), Type.USER_DEFINED, Function.getFunctionDescription(graph, function)); userFunctions.add(userFunction);