[mapguide-commits] r8505 - in trunk/Tools/Maestro: . Maestro OSGeo.MapGuide.MaestroAPI.Expressions OSGeo.MapGuide.MaestroAPI.Expressions/Properties OSGeo.MapGuide.MaestroAPI.Tests Properties

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sun Jan 18 08:16:50 PST 2015


Author: jng
Date: 2015-01-18 08:16:50 -0800 (Sun, 18 Jan 2015)
New Revision: 8505

Added:
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoBinaryExpression.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoDataValue.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpression.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpressionGrammar.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilter.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilterGrammar.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFunction.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoGeometryValue.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoIdentifier.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoLiteralValue.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParameter.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParseException.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoTerminalNames.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoUnaryExpression.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoValueExpression.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/OSGeo.MapGuide.MaestroAPI.Expressions.csproj
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/Properties/
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/Properties/AssemblyInfo.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/packages.config
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/ExpressionTests.cs
Modified:
   trunk/Tools/Maestro/Maestro/Maestro_All.sln
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/OSGeo.MapGuide.MaestroAPI.Tests.csproj
   trunk/Tools/Maestro/Properties/GlobalAssemblyInfo.cs
Log:
#2525: Add library to provide support for parsing FDO expression and filter strings. This initial implementations supports parsing of FDO expressions.

Modified: trunk/Tools/Maestro/Maestro/Maestro_All.sln
===================================================================
--- trunk/Tools/Maestro/Maestro/Maestro_All.sln	2015-01-18 13:11:04 UTC (rev 8504)
+++ trunk/Tools/Maestro/Maestro/Maestro_All.sln	2015-01-18 16:16:50 UTC (rev 8505)
@@ -120,6 +120,8 @@
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSGeo.MapGuide.ObjectModels.Tests", "..\OSGeo.MapGuide.ObjectModel.Tests\OSGeo.MapGuide.ObjectModels.Tests.csproj", "{D32BE7DB-D0C3-4805-A057-18312370C57E}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OSGeo.MapGuide.MaestroAPI.Expressions", "..\OSGeo.MapGuide.MaestroAPI.Expressions\OSGeo.MapGuide.MaestroAPI.Expressions.csproj", "{DA2CC031-200B-4F99-A0A9-2E95374BE78F}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -262,6 +264,10 @@
 		{D32BE7DB-D0C3-4805-A057-18312370C57E}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{D32BE7DB-D0C3-4805-A057-18312370C57E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{D32BE7DB-D0C3-4805-A057-18312370C57E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DA2CC031-200B-4F99-A0A9-2E95374BE78F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DA2CC031-200B-4F99-A0A9-2E95374BE78F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DA2CC031-200B-4F99-A0A9-2E95374BE78F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DA2CC031-200B-4F99-A0A9-2E95374BE78F}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -299,5 +305,6 @@
 		{48C5EB23-45AE-4C4C-8FAB-635428AE8CA1} = {0DA73D0B-B89E-464B-AD24-CD370242F641}
 		{28224492-7383-46BD-AE64-2DA35243175C} = {7507E52A-413B-4E0D-A1FF-7D293E462C1B}
 		{D32BE7DB-D0C3-4805-A057-18312370C57E} = {7507E52A-413B-4E0D-A1FF-7D293E462C1B}
+		{DA2CC031-200B-4F99-A0A9-2E95374BE78F} = {0DA73D0B-B89E-464B-AD24-CD370242F641}
 	EndGlobalSection
 EndGlobal


Property changes on: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions
___________________________________________________________________
Added: svn:ignore
   + bin
obj


Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoBinaryExpression.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoBinaryExpression.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoBinaryExpression.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,131 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public enum BinaryOperator
+    {
+        Add,
+        Subtract,
+        Multiply,
+        Divide
+    }
+
+    public class FdoBinaryExpression : FdoExpression
+    {
+        public FdoExpression Left { get; private set; }
+
+        public BinaryOperator Operator { get; private set; }
+
+        public FdoExpression Right { get; private set; }
+
+        public FdoBinaryExpression(ParseTreeNode node)
+        {
+            this.Left = FdoExpression.ParseNode(node.ChildNodes[0]);
+            //HACK: Workaround bug in parser or grammar specification where (a - b) produces a: Expression, b: Expression
+            if (node.ChildNodes.Count == 2)
+            {
+                var expr = FdoExpression.ParseNode(node.ChildNodes[1]);
+                this.Operator = BinaryOperator.Subtract;
+                this.Right = expr;
+                /*
+                if (expr is FdoUnaryExpression)
+                {
+                    this.Operator = BinaryOperator.Subtract;
+                    this.Right = ((FdoUnaryExpression)expr).Expression;
+                }
+                else if (expr is FdoDataValue)
+                {
+                    var dt = ((FdoDataValue)expr).DataType;
+                    switch (dt)
+                    {
+                        case DataType.Double:
+                            {
+                                FdoDoubleValue dbl = (FdoDoubleValue)expr;
+                                if (dbl.Value < 0.0)
+                                {
+                                    this.Operator = BinaryOperator.Subtract;
+                                    this.Right = dbl.Negate();
+                                }
+                                else
+                                {
+                                    this.Operator = BinaryOperator.Add;
+                                    this.Right = expr;
+                                }
+                            }
+                            break;
+                        case DataType.Int32:
+                            {
+                                FdoInt32Value iv = (FdoInt32Value)expr;
+                                if (iv.Value < 0)
+                                {
+                                    this.Operator = BinaryOperator.Subtract;
+                                    this.Right = iv.Negate();
+                                }
+                                else
+                                {
+                                    this.Operator = BinaryOperator.Add;
+                                    this.Right = expr;
+                                }
+                            }
+                            break;
+                        default:
+                            throw new FdoParseException("Could not parse as Binary Expression");
+                    }
+                }
+                else
+                {
+                    throw new FdoParseException("Could not parse as Binary Expression");
+                }
+                 */
+            }
+            else
+            {
+                var opStr = node.ChildNodes[1].Token.ValueString;
+                switch (opStr)
+                {
+                    case "+":
+                        this.Operator = BinaryOperator.Add;
+                        break;
+                    case "-":
+                        this.Operator = BinaryOperator.Subtract;
+                        break;
+                    case "/":
+                        this.Operator = BinaryOperator.Divide;
+                        break;
+                    case "*":
+                        this.Operator = BinaryOperator.Multiply;
+                        break;
+                    default:
+                        throw new FdoParseException("Unknown binary operator: " + opStr);
+                }
+                this.Right = FdoExpression.ParseNode(node.ChildNodes[2]);
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoDataValue.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoDataValue.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoDataValue.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,182 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public enum DataType
+    {
+        Boolean,
+        DateTime,
+        Double,
+        Int32,
+        String
+    }
+
+    public abstract class FdoDataValue : FdoLiteralValue
+    {
+        public DataType DataType { get; protected set; }
+
+        protected FdoDataValue()
+        {
+            this.LiteralValueType = LiteralValueType.Data;
+        }
+
+        internal static FdoDataValue ParseDataNode(ParseTreeNode node)
+        {
+            if (node.Term.Name == FdoTerminalNames.DataValue)
+            {
+                return ParseDataNode(node.ChildNodes[0]);
+            }
+            else
+            {
+                switch (node.Term.Name)
+                {
+                    case FdoTerminalNames.Boolean:
+                        return new FdoBooleanValue(node);
+                    case FdoTerminalNames.String:
+                        return new FdoStringValue(node);
+                    case FdoTerminalNames.Integer:
+                        return new FdoInt32Value(node);
+                    case FdoTerminalNames.Double:
+                        return new FdoDoubleValue(node);
+                    case FdoTerminalNames.DateTime:
+                        return new FdoDateTimeValue(node);
+                    default:
+                        throw new FdoParseException("Unknown terminal: " + node.Term.Name);
+                }
+            }
+        }
+    }
+
+    public class FdoStringValue : FdoDataValue
+    {
+        public string Value { get; private set; }
+
+        internal FdoStringValue(ParseTreeNode node)
+        {
+            this.DataType = Expressions.DataType.String;
+            this.Value = node.Token.ValueString;
+        }
+    }
+
+    public class FdoInt32Value : FdoDataValue
+    {
+        public int Value { get; private set; }
+
+        internal FdoInt32Value(ParseTreeNode node)
+        {
+            this.DataType = Expressions.DataType.Int32;
+            this.Value = Convert.ToInt32(node.Token.ValueString);
+        }
+
+        private FdoInt32Value(int value)
+        {
+            this.Value = value;
+        }
+
+        internal FdoInt32Value Negate()
+        {
+            return new FdoInt32Value(-this.Value);
+        }
+    }
+
+    public class FdoDoubleValue : FdoDataValue
+    {
+        public double Value { get; private set; }
+
+        internal FdoDoubleValue(ParseTreeNode node)
+        {
+            this.DataType = Expressions.DataType.Double;
+            this.Value = Convert.ToDouble(node.Token.ValueString);
+        }
+
+        private FdoDoubleValue(double value)
+        {
+            this.Value = value;
+        }
+
+        internal FdoDoubleValue Negate()
+        {
+            return new FdoDoubleValue(-this.Value);
+        }
+    }
+
+    public class FdoDateTimeValue : FdoDataValue
+    {
+        public DateTime? DateTime { get; private set; }
+
+        public TimeSpan? Time { get; private set; }
+
+        internal FdoDateTimeValue(ParseTreeNode node)
+        {
+            this.DataType = Expressions.DataType.DateTime;
+            string keyword = node.ChildNodes[0].Token.ValueString;
+            string value = node.ChildNodes[1].Token.ValueString;
+            switch (keyword)
+            {
+                case "DATE":
+                    {
+                        string[] tokens = value.Split('-');
+                        if (tokens.Length != 3)
+                            throw new FdoParseException("Value is not a valid FDO date string: " + value);
+                        this.DateTime = new DateTime(Convert.ToInt32(tokens[0]), Convert.ToInt32(tokens[1]), Convert.ToInt32(tokens[2]));
+                    }
+                    break;
+                case "TIME":
+                    {
+                        string [] tokens = value.Split(':', '.');
+                        if (tokens.Length != 3 && tokens.Length != 4)
+                            throw new FdoParseException("Value is not a valid FDO time string: " + value);
+                        var ts = new TimeSpan(0, Convert.ToInt32(tokens[0]), Convert.ToInt32(tokens[1]), Convert.ToInt32(tokens[2]), (tokens.Length == 4) ? Convert.ToInt32(tokens[3]) : 0);
+                        this.Time = ts;
+                    }
+                    break;
+                case "TIMESTAMP":
+                    {
+                        string[] tokens = value.Split('-', '.', ':', ' ');
+                        if (tokens.Length != 6 && tokens.Length != 7)
+                            throw new FdoParseException("Value is not a valid FDO timestamp string: " + value);
+                        this.DateTime = new DateTime(Convert.ToInt32(tokens[0]), Convert.ToInt32(tokens[1]), Convert.ToInt32(tokens[2]), Convert.ToInt32(tokens[3]), Convert.ToInt32(tokens[4]), Convert.ToInt32(tokens[5]), (tokens.Length == 7) ? Convert.ToInt32(tokens[6]) : 0);
+                    }
+                    break;
+                default:
+                    throw new FdoParseException("Unknown keyword: " + keyword);
+            }
+        } 
+    }
+
+    public class FdoBooleanValue : FdoDataValue
+    {
+        public bool Value { get; private set; }
+
+        internal FdoBooleanValue(ParseTreeNode node)
+        {
+            this.Value = Convert.ToBoolean(node.ChildNodes[0].Token.ValueString);
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpression.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpression.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpression.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,74 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public abstract class FdoExpression
+    {
+        public static FdoExpression Parse(string str)
+        {
+            Parser p = new Parser(new FdoExpressionGrammar());
+            var tree = p.Parse(str);
+            if (tree.Root.Term.Name == FdoTerminalNames.Expression)
+            {
+                var child = tree.Root.ChildNodes[0];
+                return ParseNode(child);
+            }
+            else
+            {
+                throw new FdoParseException();
+            }
+        }
+
+        protected static FdoExpression ParseNode(ParseTreeNode child)
+        {
+            if (child.Term.Name == FdoTerminalNames.Expression)
+            {
+                return ParseNode(child.ChildNodes[0]);
+            }
+            else
+            {
+                switch (child.Term.Name)
+                {
+                    case FdoTerminalNames.UnaryExpression:
+                        return new FdoUnaryExpression(child);
+                    case FdoTerminalNames.BinaryExpression:
+                        return new FdoBinaryExpression(child);
+                    case FdoTerminalNames.Function:
+                        return new FdoFunction(child);
+                    case FdoTerminalNames.Identifier:
+                        return new FdoIdentifier(child);
+                    case FdoTerminalNames.ValueExpression:
+                        return FdoValueExpression.ParseValueNode(child);
+                    default:
+                        throw new FdoParseException("Unknown terminal: " + child.Term.Name);
+                }
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpressionGrammar.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpressionGrammar.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoExpressionGrammar.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,141 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    [Language("FDO Expression", "1.0", "FDO Expression Grammar")]
+    public class FdoExpressionGrammar : Grammar
+    {
+        public FdoExpressionGrammar()
+            : base(false)
+        {
+            //1. Terminals
+            IdentifierTerminal Identifier = new IdentifierTerminal(FdoTerminalNames.Identifier);
+            StringLiteral QuotedIdentifier = new StringLiteral(FdoTerminalNames.Identifier, "\"");
+            StringLiteral String = new StringLiteral(FdoTerminalNames.String, "\'");
+            NumberLiteral Integer = new NumberLiteral(FdoTerminalNames.Integer, NumberOptions.IntOnly | NumberOptions.AllowSign);
+            NumberLiteral Double = new NumberLiteral(FdoTerminalNames.Double);
+
+            //2. Non-Terminals
+            NonTerminal Expression = new NonTerminal(FdoTerminalNames.Expression);
+            NonTerminal UnaryExpression = new NonTerminal(FdoTerminalNames.UnaryExpression);
+            NonTerminal BinaryExpression = new NonTerminal(FdoTerminalNames.BinaryExpression);
+            NonTerminal ValueExpression = new NonTerminal(FdoTerminalNames.ValueExpression);
+            NonTerminal Function = new NonTerminal(FdoTerminalNames.Function);
+
+            NonTerminal DataValue = new NonTerminal(FdoTerminalNames.DataValue);
+            NonTerminal LiteralValue = new NonTerminal(FdoTerminalNames.LiteralValue);
+            NonTerminal Parameter = new NonTerminal(FdoTerminalNames.Parameter);
+            NonTerminal ExpressionCollection = new NonTerminal(FdoTerminalNames.ExpressionCollection);
+            NonTerminal GeometryValue = new NonTerminal(FdoTerminalNames.GeometryValue);
+
+            NonTerminal Boolean = new NonTerminal(FdoTerminalNames.Boolean);
+            NonTerminal DateTime = new NonTerminal(FdoTerminalNames.DateTime);
+
+            //3. BNF Rules
+            Expression.Rule = 
+                "(" + Expression + ")" | 
+                UnaryExpression | 
+                BinaryExpression | 
+                Function | 
+                Identifier | 
+                QuotedIdentifier |
+                ValueExpression;
+            BinaryExpression.Rule =
+                Expression + "+" + Expression |
+                Expression + "-" + Expression |
+                Expression + "*" + Expression |
+                Expression + "/" + Expression;
+            DataValue.Rule = 
+                DateTime | 
+                Double | 
+                Integer | 
+                String | 
+                //Blob | 
+                //Clob | 
+                Boolean |
+                "NULL";
+            Boolean.Rule = 
+                ToTerm("TRUE") | 
+                ToTerm("FALSE");
+            DateTime.Rule = 
+                "DATE" + String |
+                "TIME" + String |
+                "TIMESTAMP" + String;
+            Function.Rule =
+                Identifier + "(" + ExpressionCollection + ")" |
+                Identifier + "()";
+            ExpressionCollection.Rule = Expression | ExpressionCollection + "," + Expression;
+            GeometryValue.Rule = ToTerm("GEOMFROMTEXT") + "(" + String + ")";
+            ValueExpression.Rule = LiteralValue | Parameter;
+            LiteralValue.Rule = GeometryValue | DataValue;
+            Parameter.Rule = Parameter | ":" + Identifier;
+            UnaryExpression.Rule = "-" + Expression;
+
+            this.Root = Expression;
+
+            // 4. Set operators precedence
+            RegisterOperators(1, "+", "-");
+            RegisterOperators(2, "*", "/");
+            this.MarkPunctuation("(", ")", ",", ":", "-");
+            /*
+             <Expression> ::= '(' Expression ')'
+                | <UnaryExpression>
+                | <BinaryExpression>
+                | <Function>
+                | <Identifier>
+                | <ValueExpression>
+             <BinaryExpression> ::=
+                <Expression> '+' <Expression>
+                | <Expression> '-' <Expression>
+                | <Expression> '*' <Expression>
+                | <Expression> '/' <Expression>
+             <DataValue> ::=
+                TRUE
+                | FALSE
+                | DATETIME
+                | DOUBLE
+                | INTEGER
+                | STRING
+                | BLOB
+                | CLOB
+                | NULL
+             <Function> ::= <Identifier> '(' <ExpressionCollection> ')'
+             <ExpressionCollection> ::=
+                | <Expression>
+                | <ExpressionCollection> ',' <Expression>
+             <GeometryValue> ::= GEOMFROMTEXT '(' STRING ')'
+             <Identifier> ::= IDENTIFIER
+             <ValueExpression> ::= <LiteralValue> | <Parameter>;
+             <LiteralValue> ::= <GeometryValue> | <DataValue>
+             <Parameter> ::= PARAMETER | ':'STRING
+             <UnaryExpression> ::= '-' <Expression>
+             
+             */
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilter.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilter.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilter.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,33 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoFilter
+    {
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilterGrammar.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilterGrammar.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFilterGrammar.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,216 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    [Language("FDO Filter", "1.0", "FDO Filter Grammar")]
+    public class FdoFilterGrammar : Grammar
+    {
+        public FdoFilterGrammar()
+            : base(false)
+        {
+            NonTerminal Filter = new NonTerminal(FdoTerminalNames.Filter);
+            NonTerminal LogicalOperator = new NonTerminal(FdoTerminalNames.LogicalOperator);
+            NonTerminal BinaryLogicalOperator = new NonTerminal(FdoTerminalNames.BinaryLogicalOperator);
+            NonTerminal UnaryLogicalOperator = new NonTerminal(FdoTerminalNames.UnaryLogicalOperator);
+            NonTerminal BinaryLogicalOperations = new NonTerminal(FdoTerminalNames.BinaryLogicalOperations);
+
+            NonTerminal InCondition = new NonTerminal(FdoTerminalNames.InCondition);
+            NonTerminal SearchCondition = new NonTerminal(FdoTerminalNames.SearchCondition);
+            NonTerminal ComparisonCondition = new NonTerminal(FdoTerminalNames.ComparisonCondition);
+            NonTerminal GeometricCondition = new NonTerminal(FdoTerminalNames.GeometricCondition);
+            NonTerminal NullCondition = new NonTerminal(FdoTerminalNames.NullCondition);
+            NonTerminal DistanceCondition = new NonTerminal(FdoTerminalNames.DistanceCondition);
+            NonTerminal SpatialCondition = new NonTerminal(FdoTerminalNames.SpatialCondition);
+
+            NonTerminal ValueExpressionCollection = new NonTerminal(FdoTerminalNames.ValueExpressionCollection);
+            NonTerminal ComparisonOperations = new NonTerminal(FdoTerminalNames.ComparisonOperations);
+            NonTerminal DistanceOperations = new NonTerminal(FdoTerminalNames.DistanceOperations);
+            NonTerminal Distance = new NonTerminal(FdoTerminalNames.Distance);
+            NonTerminal SpatialOperations = new NonTerminal(FdoTerminalNames.SpatialOperations);
+
+            //FDO Expression terminals and literals
+            IdentifierTerminal Identifier = new IdentifierTerminal(FdoTerminalNames.Identifier);
+            StringLiteral QuotedIdentifier = new StringLiteral(FdoTerminalNames.Identifier, "\"");
+            StringLiteral String = new StringLiteral(FdoTerminalNames.String, "\'");
+            NumberLiteral Integer = new NumberLiteral(FdoTerminalNames.Integer, NumberOptions.IntOnly);
+            NumberLiteral Double = new NumberLiteral(FdoTerminalNames.Double);
+
+            //FDO Expression non-terminals
+            NonTerminal Expression = new NonTerminal(FdoTerminalNames.Expression);
+            NonTerminal UnaryExpression = new NonTerminal(FdoTerminalNames.UnaryExpression);
+            NonTerminal BinaryExpression = new NonTerminal(FdoTerminalNames.BinaryExpression);
+            NonTerminal ValueExpression = new NonTerminal(FdoTerminalNames.ValueExpression);
+            NonTerminal Function = new NonTerminal(FdoTerminalNames.Function);
+            NonTerminal DataValue = new NonTerminal(FdoTerminalNames.DataValue);
+            NonTerminal LiteralValue = new NonTerminal(FdoTerminalNames.LiteralValue);
+            NonTerminal Parameter = new NonTerminal(FdoTerminalNames.Parameter);
+            NonTerminal ExpressionCollection = new NonTerminal(FdoTerminalNames.ExpressionCollection);
+            NonTerminal GeometryValue = new NonTerminal(FdoTerminalNames.GeometryValue);
+            NonTerminal Boolean = new NonTerminal(FdoTerminalNames.Boolean);
+            NonTerminal DateTime = new NonTerminal(FdoTerminalNames.DateTime);
+
+            //Filter BNF
+            Filter.Rule =
+                "(" + Filter + ")" |
+                LogicalOperator |
+                SearchCondition;
+            LogicalOperator.Rule =
+                BinaryLogicalOperator |
+                UnaryLogicalOperator;
+            BinaryLogicalOperator.Rule = Filter + BinaryLogicalOperations + Filter;
+            SearchCondition.Rule =
+                InCondition |
+                ComparisonCondition |
+                GeometricCondition |
+                NullCondition;
+            InCondition.Rule = Identifier + ToTerm("IN") + "(" + ValueExpressionCollection + ")";
+            ValueExpressionCollection.Rule =
+                ValueExpression |
+                ValueExpressionCollection + "," + ValueExpression;
+            ComparisonCondition.Rule = Expression + ComparisonOperations + Expression;
+            GeometricCondition.Rule =
+                DistanceCondition |
+                SpatialCondition;
+            DistanceCondition.Rule = Identifier + DistanceOperations + Expression + Distance;
+            NullCondition.Rule = Identifier + "NULL";
+            SpatialCondition.Rule = Identifier + SpatialOperations + Expression;
+            UnaryLogicalOperator.Rule = "NOT" + Filter;
+            BinaryLogicalOperations.Rule =
+                ToTerm("AND") |
+                ToTerm("OR");
+            ComparisonOperations.Rule =
+                ToTerm("=") |
+                ToTerm("<>") |
+                ToTerm(">") |
+                ToTerm(">=") |
+                ToTerm("<") |
+                ToTerm("<=") |
+                ToTerm("LIKE");
+            DistanceOperations.Rule =
+                ToTerm("BEYOND") |
+                ToTerm("WITHINDISTANCE");
+            Distance.Rule =
+                Double |
+                Integer;
+            SpatialOperations.Rule =
+                ToTerm("CONTAINS") |
+                ToTerm("CROSSES") |
+                ToTerm("DISJOINT") |
+                ToTerm("EQUALS") |
+                ToTerm("INTERSECTS") |
+                ToTerm("OVERLAPS") |
+                ToTerm("TOUCHES") |
+                ToTerm("WITHIN") |
+                ToTerm("COVEREDBY") |
+                ToTerm("INSIDE");
+
+            //FDO Expression BNF
+            Expression.Rule =
+                "(" + Expression + ")" |
+                UnaryExpression |
+                BinaryExpression |
+                Function |
+                Identifier |
+                QuotedIdentifier |
+                ValueExpression;
+            BinaryExpression.Rule =
+                Expression + "+" + Expression |
+                Expression + "-" + Expression |
+                Expression + "*" + Expression |
+                Expression + "/" + Expression;
+            DataValue.Rule =
+                DateTime |
+                Double |
+                Integer |
+                String |
+                //Blob | 
+                //Clob | 
+                "NULL" |
+                "TRUE" |
+                "FALSE";
+            DateTime.Rule =
+                "DATE" + String |
+                "TIME" + String |
+                "TIMESTAMP" + String;
+            Function.Rule = Identifier + "(" + ExpressionCollection + ")";
+            ExpressionCollection.Rule = Expression | ExpressionCollection + "," + Expression;
+            GeometryValue.Rule = ToTerm("GEOMFROMTEXT") + "(" + String + ")";
+            ValueExpression.Rule = LiteralValue | Parameter;
+            LiteralValue.Rule = GeometryValue | DataValue;
+            Parameter.Rule = Parameter | ":" + Identifier;
+            UnaryExpression.Rule = "-" + Expression;
+            /*
+                <Filter> ::= '(' Filter ')'
+                | <LogicalOperator>
+                | <SearchCondition>
+                <LogicalOperator> ::= <BinaryLogicalOperator>
+                | <UnaryLogicalOperator>
+                <BinaryLogicalOperator> ::= <Filter> <BinaryLogicalOperations> <Filter>
+                <SearchCondition> ::= <InCondition>
+                | <ComparisonCondition>
+                | <GeometricCondition>
+                | <NullCondition>
+                <InCondition> ::= <Identifier> IN '(' ValueExpressionCollection
+                ')'
+                <ValueExpressionCollection> ::= <ValueExpression>
+                | <ValueExpressionCollection> ',' <ValueExpression>
+                <ComparisonCondition> ::= <Expression> <ComparisonOperations> <Expression>
+                <GeometricCondition> ::= <DistanceCondition>
+                | <SpatialCondition>
+                <DistanceCondition> ::= <Identifier> <DistanceOperations> <Expression> <distance>
+                <NullCondition> ::= <Identifier> NULL
+                <SpatialCondition> ::= <Identifier> <SpatialOperations> <Expression>
+                <UnaryLogicalOperator> ::= NOT <Filter>
+                <BinaryLogicalOperations> ::= AND | OR
+                <ComparisionOperations> ::=
+                = // EqualTo (EQ)
+                <> // NotEqualTo (NE)
+                > // GreaterThan (GT)
+                >= // GreaterThanOrEqualTo (GE)
+                < // LessThan (LT)
+                <= // LessThanOrEqualTo (LE)
+                LIKE // Like
+                <DistanceOperations> ::= BEYOND | WITHINDISTANCE
+                <distance> ::= DOUBLE | INTEGER
+                <SpatialOperations> ::= CONTAINS | CROSSES | DISJOINT
+                | EQUALS | INTERSECTS | OVERLAPS | TOUCHES | WITHIN | COVEREDBY |
+                INSIDE
+             */
+            this.Root = Filter;
+            
+            
+            RegisterOperators(1, "-", "NOT");
+            RegisterOperators(2, "*", "/");
+            RegisterOperators(3, "+", "-");
+            RegisterOperators(4, "=", "<>", ">", ">=", "<", "<=");
+            RegisterOperators(5, "AND");
+            RegisterOperators(6, "OR");
+            this.MarkPunctuation("(", ")", ",", ":", "-");
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFunction.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFunction.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoFunction.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,64 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoFunction : FdoExpression
+    {
+        public string Name { get; private set; }
+
+        public List<FdoExpression> Arguments { get; private set; }
+
+        internal FdoFunction(ParseTreeNode node)
+        {
+            this.Name = node.ChildNodes[0].Token.Text;
+            this.Arguments = new List<FdoExpression>();
+            ProcessArguments(node.ChildNodes[1]);
+        }
+
+        private void ProcessNodeList(ParseTreeNodeList list)
+        {
+            foreach (ParseTreeNode child in list)
+            {
+                if (child.Term.Name == FdoTerminalNames.ExpressionCollection)
+                {
+                    ProcessNodeList(child.ChildNodes);
+                }
+                else
+                {
+                    this.Arguments.Add(FdoExpression.ParseNode(child));
+                }
+            }
+        }
+
+        private void ProcessArguments(ParseTreeNode node)
+        {
+            ProcessNodeList(node.ChildNodes);
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoGeometryValue.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoGeometryValue.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoGeometryValue.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,41 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoGeometryValue : FdoLiteralValue
+    {
+        public string GeometryWkt { get; private set; }
+
+        internal FdoGeometryValue(ParseTreeNode node)
+        {
+            this.LiteralValueType = LiteralValueType.Geometry;
+            this.GeometryWkt = node.ChildNodes[1].Token.ValueString;
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoIdentifier.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoIdentifier.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoIdentifier.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,40 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoIdentifier : FdoExpression
+    {
+        public string Name { get; private set; }
+
+        internal FdoIdentifier(ParseTreeNode node)
+        {
+            this.Name = node.Token.ValueString;
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoLiteralValue.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoLiteralValue.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoLiteralValue.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,61 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public enum LiteralValueType
+    {
+        Data,
+        Geometry
+    }
+
+    public abstract class FdoLiteralValue : FdoValueExpression
+    {
+        public LiteralValueType LiteralValueType { get; protected set; }
+
+        internal static FdoLiteralValue ParseLiteralNode(ParseTreeNode node)
+        {
+            if (node.Term.Name == FdoTerminalNames.LiteralValue)
+            {
+                return ParseLiteralNode(node.ChildNodes[0]);
+            }
+            else
+            {
+                switch (node.Term.Name)
+                {
+                    case FdoTerminalNames.DataValue:
+                        return FdoDataValue.ParseDataNode(node);
+                    case FdoTerminalNames.GeometryValue:
+                        return new FdoGeometryValue(node);
+                    default:
+                        throw new FdoParseException("Unknown terminal: " + node.Term.Name);
+                }
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParameter.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParameter.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParameter.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,40 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoParameter : FdoValueExpression
+    {
+        public string Name { get; private set; }
+
+        internal FdoParameter(ParseTreeNode node)
+        {
+            this.Name = node.ChildNodes[0].Token.ValueString;
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParseException.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParseException.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoParseException.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,41 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    [Serializable]
+    public class FdoParseException : Exception
+    {
+        public FdoParseException() { }
+        public FdoParseException(string message) : base(message) { }
+        public FdoParseException(string message, Exception inner) : base(message, inner) { }
+        protected FdoParseException(
+          System.Runtime.Serialization.SerializationInfo info,
+          System.Runtime.Serialization.StreamingContext context)
+            : base(info, context) { }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoTerminalNames.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoTerminalNames.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoTerminalNames.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,71 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    internal class FdoTerminalNames
+    {
+        public const string Identifier = "Identifier";
+        public const string String = "String";
+        public const string Integer = "Integer";
+        public const string Double = "Double";
+
+        public const string Expression = "Expression";
+        public const string UnaryExpression = "UnaryExpression";
+        public const string BinaryExpression = "BinaryExpression";
+        public const string ValueExpression = "ValueExpression";
+        public const string Function = "Function";
+
+        public const string DataValue = "DataValue";
+        public const string LiteralValue = "LiteralValue";
+        public const string Parameter = "Parameter";
+        public const string ExpressionCollection = "ExpressionCollection";
+        public const string GeometryValue = "GeometryValue";
+
+        public const string Boolean = "Boolean";
+        public const string DateTime = "DateTime";
+
+        public const string Filter = "Filter";
+        public const string LogicalOperator = "LogicalOperator";
+        public const string BinaryLogicalOperator = "BinaryLogicalOperator";
+        public const string UnaryLogicalOperator = "UnaryLogicalOperator";
+        public const string BinaryLogicalOperations = "BinaryLogicalOperations";
+        public const string InCondition = "InCondition";
+        public const string SearchCondition = "SearchCondition";
+        public const string ComparisonCondition = "ComparisonCondition";
+        public const string GeometricCondition = "GeometricCondition";
+        public const string NullCondition = "NullCondition";
+        public const string DistanceCondition = "DistanceCondition";
+        public const string SpatialCondition = "SpatialCondition";
+
+        public const string ValueExpressionCollection = "ValueExpressionCollection";
+        public const string ComparisonOperations = "ComparisonOperations";
+        public const string DistanceOperations = "DistanceOperations";
+        public const string Distance = "Distance";
+        public const string SpatialOperations = "SpatialOperations";
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoUnaryExpression.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoUnaryExpression.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoUnaryExpression.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,40 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public class FdoUnaryExpression : FdoExpression
+    {
+        public FdoExpression Expression { get; private set; }
+
+        internal FdoUnaryExpression(ParseTreeNode node)
+        {
+            this.Expression = FdoExpression.ParseNode(node.ChildNodes[0]);
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoValueExpression.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoValueExpression.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/FdoValueExpression.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,53 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using Irony.Parsing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.MaestroAPI.Expressions
+{
+    public abstract class FdoValueExpression : FdoExpression
+    {
+        internal static FdoValueExpression ParseValueNode(ParseTreeNode node)
+        {
+            if (node.Term.Name == FdoTerminalNames.ValueExpression)
+            {
+                return ParseValueNode(node.ChildNodes[0]);
+            }
+            else
+            {
+                switch (node.Term.Name)
+                {
+                    case FdoTerminalNames.LiteralValue:
+                        return FdoLiteralValue.ParseLiteralNode(node);
+                    case FdoTerminalNames.Parameter:
+                        return new FdoParameter(node);
+                    default:
+                        throw new FdoParseException("Unknown terminal: " + node.Term.Name);
+                }
+            }
+        }
+    }
+}

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/OSGeo.MapGuide.MaestroAPI.Expressions.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/OSGeo.MapGuide.MaestroAPI.Expressions.csproj	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/OSGeo.MapGuide.MaestroAPI.Expressions.csproj	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{DA2CC031-200B-4F99-A0A9-2E95374BE78F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>OSGeo.MapGuide.MaestroAPI.Expressions</RootNamespace>
+    <AssemblyName>OSGeo.MapGuide.MaestroAPI.Expressions</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\Maestro\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Irony">
+      <HintPath>..\Maestro\packages\Irony.0.9.0\lib\net45\Irony.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\GlobalAssemblyInfo.cs">
+      <Link>GlobalAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="..\Properties\SignedAssemblyInfo.cs">
+      <Link>SignedAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="FdoBinaryExpression.cs" />
+    <Compile Include="FdoDataValue.cs" />
+    <Compile Include="FdoExpression.cs" />
+    <Compile Include="FdoExpressionGrammar.cs" />
+    <Compile Include="FdoFilterGrammar.cs" />
+    <Compile Include="FdoFilter.cs" />
+    <Compile Include="FdoFunction.cs" />
+    <Compile Include="FdoGeometryValue.cs" />
+    <Compile Include="FdoIdentifier.cs" />
+    <Compile Include="FdoLiteralValue.cs" />
+    <Compile Include="FdoParameter.cs" />
+    <Compile Include="FdoParseException.cs" />
+    <Compile Include="FdoTerminalNames.cs" />
+    <Compile Include="FdoUnaryExpression.cs" />
+    <Compile Include="FdoValueExpression.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/Properties/AssemblyInfo.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/Properties/AssemblyInfo.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OSGeo.MapGuide.MaestroAPI.Expressions")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyProduct("OSGeo.MapGuide.MaestroAPI.Expressions")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("610096bc-a9fa-4ec1-a043-060e8e128d75")]

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/packages.config
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/packages.config	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Expressions/packages.config	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Irony" version="0.9.0" targetFramework="net451" />
+</packages>
\ No newline at end of file

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/ExpressionTests.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/ExpressionTests.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/ExpressionTests.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -0,0 +1,159 @@
+#region Disclaimer / License
+
+// Copyright (C) 2015, Jackie Ng
+// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie at gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#endregion Disclaimer / License
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OSGeo.MapGuide.MaestroAPI.Expressions;
+
+namespace OSGeo.MapGuide.MaestroAPI.Tests
+{
+    [TestFixture]
+    public class ExpressionTests
+    {
+        [Test]
+        public void TestExpressionParse()
+        {
+            FdoExpression expr = null;
+
+            expr = FdoExpression.Parse("RNAME");
+            Assert.IsInstanceOf<FdoIdentifier>(expr);
+            Assert.AreEqual("RNAME", ((FdoIdentifier)expr).Name);
+
+            expr = FdoExpression.Parse("TRUE");
+            Assert.IsInstanceOf<FdoBooleanValue>(expr);
+
+            expr = FdoExpression.Parse("FALSE");
+            Assert.IsInstanceOf<FdoBooleanValue>(expr);
+            
+            expr = FdoExpression.Parse(":Foo");
+            Assert.IsInstanceOf<FdoParameter>(expr);
+            Assert.AreEqual("Foo", ((FdoParameter)expr).Name);
+            
+            expr = FdoExpression.Parse(":Foo_bar");
+            Assert.AreEqual("Foo_bar", ((FdoParameter)expr).Name);
+            Assert.IsInstanceOf<FdoParameter>(expr);
+
+            expr = FdoExpression.Parse("1");
+            Assert.IsInstanceOf<FdoInt32Value>(expr);
+            Assert.AreEqual(1, ((FdoInt32Value)expr).Value);
+
+            expr = FdoExpression.Parse("-1");
+            Assert.IsInstanceOf<FdoInt32Value>(expr);
+            Assert.AreEqual(-1, ((FdoInt32Value)expr).Value);
+            
+            expr = FdoExpression.Parse("1 + 2.2");
+            Assert.IsInstanceOf<FdoBinaryExpression>(expr);
+            Assert.IsInstanceOf<FdoInt32Value>(((FdoBinaryExpression)expr).Left);
+            Assert.AreEqual(BinaryOperator.Add, ((FdoBinaryExpression)expr).Operator);
+            Assert.IsInstanceOf<FdoDoubleValue>(((FdoBinaryExpression)expr).Right);
+
+            expr = FdoExpression.Parse("1 * 2.2");
+            Assert.IsInstanceOf<FdoBinaryExpression>(expr);
+            Assert.IsInstanceOf<FdoInt32Value>(((FdoBinaryExpression)expr).Left);
+            Assert.AreEqual(BinaryOperator.Multiply, ((FdoBinaryExpression)expr).Operator);
+            Assert.IsInstanceOf<FdoDoubleValue>(((FdoBinaryExpression)expr).Right);
+
+            expr = FdoExpression.Parse("1 / 2.2");
+            Assert.IsInstanceOf<FdoBinaryExpression>(expr);
+            Assert.IsInstanceOf<FdoInt32Value>(((FdoBinaryExpression)expr).Left);
+            Assert.AreEqual(BinaryOperator.Divide, ((FdoBinaryExpression)expr).Operator);
+            Assert.IsInstanceOf<FdoDoubleValue>(((FdoBinaryExpression)expr).Right);
+
+            expr = FdoExpression.Parse("1 - 2.2");
+            Assert.IsInstanceOf<FdoBinaryExpression>(expr);
+            Assert.IsInstanceOf<FdoInt32Value>(((FdoBinaryExpression)expr).Left);
+            Assert.AreEqual(BinaryOperator.Subtract, ((FdoBinaryExpression)expr).Operator);
+            Assert.IsInstanceOf<FdoDoubleValue>(((FdoBinaryExpression)expr).Right);
+
+            expr = FdoExpression.Parse("GeomFromText('POINT (1 1)')");
+            Assert.IsInstanceOf<FdoGeometryValue>(expr);
+            Assert.AreEqual("POINT (1 1)", ((FdoGeometryValue)expr).GeometryWkt);
+
+            expr = FdoExpression.Parse("DATE '1971-12-24'");
+            Assert.IsInstanceOf<FdoDateTimeValue>(expr);
+            Assert.True(((FdoDateTimeValue)expr).DateTime.HasValue);
+            Assert.False(((FdoDateTimeValue)expr).Time.HasValue);
+            Assert.AreEqual(1971, ((FdoDateTimeValue)expr).DateTime.Value.Year);
+            Assert.AreEqual(12, ((FdoDateTimeValue)expr).DateTime.Value.Month);
+            Assert.AreEqual(24, ((FdoDateTimeValue)expr).DateTime.Value.Day);
+
+            expr = FdoExpression.Parse("TIME '11:23:43'");
+            Assert.IsInstanceOf<FdoDateTimeValue>(expr);
+            Assert.False(((FdoDateTimeValue)expr).DateTime.HasValue);
+            Assert.True(((FdoDateTimeValue)expr).Time.HasValue);
+            Assert.AreEqual(11, ((FdoDateTimeValue)expr).Time.Value.Hours);
+            Assert.AreEqual(23, ((FdoDateTimeValue)expr).Time.Value.Minutes);
+            Assert.AreEqual(43, ((FdoDateTimeValue)expr).Time.Value.Seconds);
+
+            expr = FdoExpression.Parse("TIME '11:23:43.123'");
+            Assert.IsInstanceOf<FdoDateTimeValue>(expr);
+            Assert.False(((FdoDateTimeValue)expr).DateTime.HasValue);
+            Assert.True(((FdoDateTimeValue)expr).Time.HasValue);
+            Assert.AreEqual(11, ((FdoDateTimeValue)expr).Time.Value.Hours);
+            Assert.AreEqual(23, ((FdoDateTimeValue)expr).Time.Value.Minutes);
+            Assert.AreEqual(43, ((FdoDateTimeValue)expr).Time.Value.Seconds);
+            Assert.AreEqual(123, ((FdoDateTimeValue)expr).Time.Value.Milliseconds);
+            
+            expr = FdoExpression.Parse("TIMESTAMP '2003-10-23 11:00:02'");
+            Assert.IsInstanceOf<FdoDateTimeValue>(expr);
+            Assert.True(((FdoDateTimeValue)expr).DateTime.HasValue);
+            Assert.False(((FdoDateTimeValue)expr).Time.HasValue);
+            Assert.AreEqual(2003, ((FdoDateTimeValue)expr).DateTime.Value.Year);
+            Assert.AreEqual(10, ((FdoDateTimeValue)expr).DateTime.Value.Month);
+            Assert.AreEqual(23, ((FdoDateTimeValue)expr).DateTime.Value.Day);
+            Assert.AreEqual(11, ((FdoDateTimeValue)expr).DateTime.Value.Hour);
+            Assert.AreEqual(00, ((FdoDateTimeValue)expr).DateTime.Value.Minute);
+            Assert.AreEqual(02, ((FdoDateTimeValue)expr).DateTime.Value.Second);
+
+            expr = FdoExpression.Parse("TIMESTAMP '2003-10-23 11:00:02.123'");
+            Assert.IsInstanceOf<FdoDateTimeValue>(expr);
+            Assert.True(((FdoDateTimeValue)expr).DateTime.HasValue);
+            Assert.False(((FdoDateTimeValue)expr).Time.HasValue);
+            Assert.AreEqual(2003, ((FdoDateTimeValue)expr).DateTime.Value.Year);
+            Assert.AreEqual(10, ((FdoDateTimeValue)expr).DateTime.Value.Month);
+            Assert.AreEqual(23, ((FdoDateTimeValue)expr).DateTime.Value.Day);
+            Assert.AreEqual(11, ((FdoDateTimeValue)expr).DateTime.Value.Hour);
+            Assert.AreEqual(00, ((FdoDateTimeValue)expr).DateTime.Value.Minute);
+            Assert.AreEqual(02, ((FdoDateTimeValue)expr).DateTime.Value.Second);
+            Assert.AreEqual(123, ((FdoDateTimeValue)expr).DateTime.Value.Millisecond);
+
+            expr = FdoExpression.Parse("CurrentDate()");
+            Assert.IsInstanceOf<FdoFunction>(expr);
+            Assert.AreEqual("CurrentDate", ((FdoFunction)expr).Name);
+            Assert.AreEqual(0, ((FdoFunction)expr).Arguments.Count);
+
+            expr = FdoExpression.Parse("Concat(RNAME, ' ', RBILAD)");
+            Assert.IsInstanceOf<FdoFunction>(expr);
+            Assert.AreEqual("Concat", ((FdoFunction)expr).Name);
+            Assert.AreEqual(3, ((FdoFunction)expr).Arguments.Count);
+            Assert.IsInstanceOf<FdoIdentifier>(((FdoFunction)expr).Arguments[0]);
+            Assert.IsInstanceOf<FdoStringValue>(((FdoFunction)expr).Arguments[1]);
+            Assert.IsInstanceOf<FdoIdentifier>(((FdoFunction)expr).Arguments[2]);
+
+            expr = FdoExpression.Parse("-UnixTime()");
+            Assert.IsInstanceOf<FdoUnaryExpression>(expr);
+        }
+    }
+}

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/OSGeo.MapGuide.MaestroAPI.Tests.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/OSGeo.MapGuide.MaestroAPI.Tests.csproj	2015-01-18 13:11:04 UTC (rev 8504)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Tests/OSGeo.MapGuide.MaestroAPI.Tests.csproj	2015-01-18 16:16:50 UTC (rev 8505)
@@ -61,6 +61,7 @@
     <Compile Include="ConfigurationDocumentTests.cs" />
     <Compile Include="CrossConnection\ResourceMigratorTests.cs" />
     <Compile Include="CrossConnection\ResourceRebaserTests.cs" />
+    <Compile Include="ExpressionTests.cs" />
     <Compile Include="FeatureReaderTests.cs" />
     <Compile Include="Mapping\RuntimeMapTests.cs" />
     <Compile Include="MiscTests.cs" />
@@ -80,6 +81,10 @@
     <Compile Include="ValidationTests.cs" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI.Expressions\OSGeo.MapGuide.MaestroAPI.Expressions.csproj">
+      <Project>{da2cc031-200b-4f99-a0a9-2e95374be78f}</Project>
+      <Name>OSGeo.MapGuide.MaestroAPI.Expressions</Name>
+    </ProjectReference>
     <ProjectReference Include="..\OSGeo.MapGuide.MaestroAPI.Http\OSGeo.MapGuide.MaestroAPI.Http.csproj">
       <Project>{6ef1e775-444b-4e5f-87fb-d687c43a68d7}</Project>
       <Name>OSGeo.MapGuide.MaestroAPI.Http</Name>

Modified: trunk/Tools/Maestro/Properties/GlobalAssemblyInfo.cs
===================================================================
--- trunk/Tools/Maestro/Properties/GlobalAssemblyInfo.cs	2015-01-18 13:11:04 UTC (rev 8504)
+++ trunk/Tools/Maestro/Properties/GlobalAssemblyInfo.cs	2015-01-18 16:16:50 UTC (rev 8505)
@@ -24,7 +24,7 @@
 
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("Open Source Geospatial Foundation")]
-[assembly: AssemblyCopyright("Copyright (c) 2014, Jackie Ng")]
+[assembly: AssemblyCopyright("Copyright (c) 2015, Jackie Ng")]
 
 // Version information for an assembly consists of the following four values:
 //



More information about the mapguide-commits mailing list