]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Unit validation for Sysdyn functions: determination of function output unit based...
authormiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 29 Jan 2014 10:04:48 +0000 (10:04 +0000)
committermiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Wed, 29 Jan 2014 10:04:48 +0000 (10:04 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28722 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ontology/graph.tg
org.simantics.sysdyn.ontology/graph/ModelicaFunctions.pgraph
org.simantics.sysdyn.ontology/graph/VensimFunctions.pgraph
org.simantics.sysdyn.ontology/src/org/simantics/sysdyn/SysdynResource.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/ShortcutTabWidget.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/properties/widgets/expressions/CompletionProcessor.java
org.simantics.sysdyn/META-INF/MANIFEST.MF
org.simantics.sysdyn/src/org/simantics/sysdyn/unitParser/nodes/FunctionCall.java
org.simantics.sysdyn/src/org/simantics/sysdyn/utils/Function.java

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