[mapguide-commits] r6453 - in trunk/Tools/Maestro: MaestroAPITests OSGeo.MapGuide.MaestroAPI OSGeo.MapGuide.MaestroAPI/Internal OSGeo.MapGuide.MaestroAPI.Http OSGeo.MapGuide.MaestroAPI.Native OSGeo.MapGuide.MaestroAPI.Native/Commands

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jan 24 11:38:25 EST 2012


Author: jng
Date: 2012-01-24 08:38:24 -0800 (Tue, 24 Jan 2012)
New Revision: 6453

Added:
   trunk/Tools/Maestro/MaestroAPITests/MiscTests.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Internal/
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Internal/FixedWKTReader.cs
Modified:
   trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj
   trunk/Tools/Maestro/MaestroAPITests/TestControl.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlReaderBase.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlRecord.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/Commands/FeatureCommandsImpl.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeDataReader.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeature.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeatureReader.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeRecord.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeSqlReader.cs
   trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
Log:
#1928: Introduce a new FixedWKTReader.cs which is a copypasta of the original NTS WKTReader, with a small fix to gracefully handle 3D geometry WKT strings. Update all code that uses the NTS WKTReader to use our FixedWKTReader. Added a unit test to test against some sample 3D WKT strings.

Modified: trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/MaestroAPITests/MaestroAPITests.csproj	2012-01-24 16:38:24 UTC (rev 6453)
@@ -78,6 +78,7 @@
     <Compile Include="HttpSiteTests.cs" />
     <Compile Include="LocalNativeFeatureTests.cs" />
     <Compile Include="LocalNativePerformanceTests.cs" />
+    <Compile Include="MiscTests.cs" />
     <Compile Include="ObjectTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\Resources.Designer.cs">

Added: trunk/Tools/Maestro/MaestroAPITests/MiscTests.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/MiscTests.cs	                        (rev 0)
+++ trunk/Tools/Maestro/MaestroAPITests/MiscTests.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -0,0 +1,42 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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
+using System;
+using System.Collections.Generic;
+using System.Text;
+using NUnit.Framework;
+using OSGeo.MapGuide.MaestroAPI.Internal;
+
+namespace MaestroAPITests
+{
+    [TestFixture(Ignore = TestControl.IgnoreMiscTests)]
+    public class MiscTests
+    {
+        [Test]
+        public void TestParse3dWkt()
+        {
+            var wkt1 = "LINESTRING XYZ (218941.59990888927 173858.42946731683 0, 218931.73921854934 173868.56834443274 0)";
+            var wkt2 = "POINT XYZ (1 2 3)";
+
+            var reader = new FixedWKTReader();
+            reader.Read(wkt1);
+            reader.Read(wkt2);
+        }
+    }
+}

Modified: trunk/Tools/Maestro/MaestroAPITests/TestControl.cs
===================================================================
--- trunk/Tools/Maestro/MaestroAPITests/TestControl.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/MaestroAPITests/TestControl.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -44,6 +44,7 @@
         public const bool IgnoreSchemaTests = false;
         public const bool IgnoreSerializationTests = false;
         public const bool IgnoreValidationTests = false;
+        public const bool IgnoreMiscTests = false;
     }
 
     public class LocalNativeConnectionUtil

Added: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Internal/FixedWKTReader.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Internal/FixedWKTReader.cs	                        (rev 0)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/Internal/FixedWKTReader.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -0,0 +1,586 @@
+#region Disclaimer / License
+// Copyright (C) 2012, 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
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using GeoAPI.Geometries;
+using GisSharpBlog.NetTopologySuite.Geometries;
+using GisSharpBlog.NetTopologySuite.Utilities;
+using RTools_NTS.Util;
+using GisSharpBlog.NetTopologySuite.IO;
+
+namespace OSGeo.MapGuide.MaestroAPI.Internal
+{
+    /// <summary>  
+    /// A fixed version of WKTReader that can parse 3D geometry WKT
+    /// </summary>
+    public class FixedWKTReader
+    {
+        private IGeometryFactory geometryFactory;
+        private IPrecisionModel precisionModel;
+        int index;
+
+        bool hasXY = true;
+        bool hasZ = false;
+        bool hasM = false;
+
+        /// <summary> 
+        /// Creates a <c>WKTReader</c> that creates objects using a basic GeometryFactory.
+        /// </summary>
+        public FixedWKTReader() : this(GeometryFactory.Default) { }
+
+        /// <summary>  
+        /// Creates a <c>WKTReader</c> that creates objects using the given
+        /// <c>GeometryFactory</c>.
+        /// </summary>
+        /// <param name="geometryFactory">The factory used to create <c>Geometry</c>s.</param>
+        public FixedWKTReader(IGeometryFactory geometryFactory)
+        {
+            this.geometryFactory = geometryFactory;
+            precisionModel = geometryFactory.PrecisionModel;
+        }
+
+        /// <summary>
+        /// Converts a Well-known Text representation to a <c>Geometry</c>.
+        /// </summary>
+        /// <param name="wellKnownText">
+        /// one or more Geometry Tagged Text strings (see the OpenGIS
+        /// Simple Features Specification) separated by whitespace.
+        /// </param>
+        /// <returns>
+        /// A <c>Geometry</c> specified by <c>wellKnownText</c>
+        /// </returns>
+        public IGeometry Read(string wellKnownText)
+        {
+            using (StringReader reader = new StringReader(wellKnownText))
+            {
+                return Read(reader);
+            }
+        }
+
+        /// <summary>  
+        /// Converts a Well-known Text representation to a <c>Geometry</c>.
+        /// </summary>
+        /// <param name="reader"> 
+        /// A Reader which will return a "Geometry Tagged Text"
+        /// string (see the OpenGIS Simple Features Specification).
+        /// </param>
+        /// <returns>A <c>Geometry</c> read from <c>reader</c>.
+        /// </returns>
+        public IGeometry Read(TextReader reader)
+        {
+            StreamTokenizer tokenizer = new StreamTokenizer(reader);
+            List<Token> tokens = new List<Token>();
+            tokenizer.Tokenize(tokens);     // Read directly all tokens
+            index = 0;                      // Reset pointer to start of tokens
+
+            hasXY = true;
+            hasZ = false;
+            hasM = false;
+            try
+            {
+                return ReadGeometryTaggedText(tokens);
+            }
+            catch (IOException e)
+            {
+                throw new ParseException(e.ToString());
+            }
+        }
+
+        /// <summary>
+        /// Returns the next array of <c>Coordinate</c>s in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next element returned by the stream should be "(" (the
+        /// beginning of "(x1 y1, x2 y2, ..., xn yn)") or "EMPTY".
+        /// </param>
+        /// <param name="skipExtraParenthesis">
+        /// if set to <c>true</c> skip extra parenthesis around coordinates.
+        /// </param>
+        /// <returns>
+        /// The next array of <c>Coordinate</c>s in the
+        /// stream, or an empty array if "EMPTY" is the next element returned by
+        /// the stream.
+        /// </returns>
+        private ICoordinate[] GetCoordinates(IList tokens, Boolean skipExtraParenthesis)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return new ICoordinate[] { };
+            List<ICoordinate> coordinates = new List<ICoordinate>();
+            coordinates.Add(GetPreciseCoordinate(tokens, skipExtraParenthesis));
+            nextToken = GetNextCloserOrComma(tokens);
+            while (nextToken.Equals(","))
+            {
+                coordinates.Add(GetPreciseCoordinate(tokens, skipExtraParenthesis));
+                nextToken = GetNextCloserOrComma(tokens);
+            }
+            return coordinates.ToArray();
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="tokens"></param>
+        /// <param name="skipExtraParenthesis"></param>
+        /// <returns></returns>
+        private ICoordinate GetPreciseCoordinate(IList tokens, Boolean skipExtraParenthesis)
+        {
+            ICoordinate coord = new Coordinate();
+            Boolean extraParenthesisFound = false;
+            if (skipExtraParenthesis)
+            {
+                extraParenthesisFound = IsStringValueNext(tokens, "(");
+                if (extraParenthesisFound)
+                {
+                    index++;
+                }
+            }
+            coord.X = GetNextNumber(tokens);
+            coord.Y = GetNextNumber(tokens);
+            if (IsNumberNext(tokens))
+                coord.Z = GetNextNumber(tokens);
+
+            if (skipExtraParenthesis &&
+                extraParenthesisFound &&
+                IsStringValueNext(tokens, ")"))
+            {
+                index++;
+            }
+
+            precisionModel.MakePrecise(coord);
+            return coord;
+        }
+
+        private Boolean IsStringValueNext(IList tokens, String stringValue)
+        {
+            Token token = tokens[index] as Token;
+            return token.StringValue == stringValue;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="tokens"></param>
+        /// <returns></returns>
+        private bool IsNumberNext(IList tokens)
+        {
+            Token token = tokens[index] as Token;
+            return token is FloatToken || token is IntToken;
+        }
+
+        /// <summary>
+        /// Returns the next number in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next token must be a number.
+        /// </param>
+        /// <returns>The next number in the stream.</returns>
+        private double GetNextNumber(IList tokens)
+        {
+            Token token = tokens[index++] as Token;
+
+            if (token == null)
+                throw new ArgumentNullException("tokens", "Token list contains a null value");
+            else if (token is EofToken)
+                throw new ParseException("Expected number but encountered end of stream");
+            else if (token is EolToken)
+                throw new ParseException("Expected number but encountered end of line");
+            else if (token is FloatToken || token is IntToken)
+                return (double)token.ConvertToType(typeof(double));
+            else if (token is WordToken)
+                throw new ParseException("Expected number but encountered word: " + token.StringValue);
+            else if (token.StringValue == "(")
+                throw new ParseException("Expected number but encountered '('");
+            else if (token.StringValue == ")")
+                throw new ParseException("Expected number but encountered ')'");
+            else if (token.StringValue == ",")
+                throw new ParseException("Expected number but encountered ','");
+            else
+            {
+                Assert.ShouldNeverReachHere();
+                return double.NaN;
+            }
+        }
+
+        /// <summary>
+        /// Returns the next "EMPTY" or "(" in the stream as uppercase text.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next token must be "EMPTY" or "(".
+        /// </param>
+        /// <returns>
+        /// The next "EMPTY" or "(" in the stream as uppercase text.</returns>
+        private string GetNextEmptyOrOpener(IList tokens)
+        {
+            //The next word may be the dimension specifier. In such a case, read the
+            //next word after that.
+            string nextWord = GetNextWord(tokens);
+            if (nextWord.Equals("XYZ"))
+            {
+                hasZ = true;
+                nextWord = GetNextWord(tokens);
+            }
+            else if (nextWord.Equals("XYM"))
+            {
+                hasM = true;
+                nextWord = GetNextWord(tokens);
+            }
+            else if (nextWord.Equals("ZM"))
+            {
+                hasXY = false; 
+                hasZ = true; 
+                hasM = true;
+                nextWord = GetNextWord(tokens);
+            }
+            if (nextWord.Equals("EMPTY") || nextWord.Equals("("))
+                return nextWord;
+            throw new ParseException("Expected 'EMPTY' or '(' but encountered '" + nextWord + "'");
+        }
+
+        /// <summary>
+        /// Returns the next ")" or "," in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next token must be ")" or ",".
+        /// </param>
+        /// <returns>
+        /// The next ")" or "," in the stream.</returns>
+        private string GetNextCloserOrComma(IList tokens)
+        {
+            string nextWord = GetNextWord(tokens);
+            if (nextWord.Equals(",") || nextWord.Equals(")"))
+                return nextWord;
+
+            throw new ParseException("Expected ')' or ',' but encountered '" + nextWord
+                + "'");
+        }
+
+        /// <summary>
+        /// Returns the next ")" in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next token must be ")".
+        /// </param>
+        /// <returns>
+        /// The next ")" in the stream.</returns>
+        private string GetNextCloser(IList tokens)
+        {
+            string nextWord = GetNextWord(tokens);
+            if (nextWord.Equals(")"))
+                return nextWord;
+            throw new ParseException("Expected ')' but encountered '" + nextWord + "'");
+        }
+
+        /// <summary>
+        /// Returns the next word in the stream as uppercase text.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next token must be a word.
+        /// </param>
+        /// <returns>The next word in the stream as uppercase text.</returns>
+        private string GetNextWord(IList tokens)
+        {
+            Token token = tokens[index++] as Token;
+
+            if (token is EofToken)
+                throw new ParseException("Expected number but encountered end of stream");
+            else if (token is EolToken)
+                throw new ParseException("Expected number but encountered end of line");
+            else if (token is FloatToken || token is IntToken)
+                throw new ParseException("Expected word but encountered number: " + token.StringValue);
+            else if (token is WordToken)
+                return token.StringValue.ToUpper();
+            else if (token.StringValue == "(")
+                return "(";
+            else if (token.StringValue == ")")
+                return ")";
+            else if (token.StringValue == ",")
+                return ",";
+            else
+            {
+                Assert.ShouldNeverReachHere();
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Creates a <c>Geometry</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;Geometry Tagged Text.
+        /// </param>
+        /// <returns>A <c>Geometry</c> specified by the next token
+        /// in the stream.</returns>
+        private IGeometry ReadGeometryTaggedText(IList tokens)
+        {
+            /*
+             * A new different implementation by Marc Jacquin:
+             * this code manages also SRID values.
+             */
+            IGeometry returned = null;
+            string sridValue = null;
+            string type = tokens[0].ToString();
+
+            if (type == "SRID")
+            {
+                sridValue = tokens[2].ToString();
+                // tokens.RemoveRange(0, 4);
+                tokens.RemoveAt(0);
+                tokens.RemoveAt(0);
+                tokens.RemoveAt(0);
+                tokens.RemoveAt(0);
+            }
+            else type = GetNextWord(tokens);
+            if (type.Equals("POINT"))
+                returned = ReadPointText(tokens);
+            else if (type.Equals("LINESTRING"))
+                returned = ReadLineStringText(tokens);
+            else if (type.Equals("LINEARRING"))
+                returned = ReadLinearRingText(tokens);
+            else if (type.Equals("POLYGON"))
+                returned = ReadPolygonText(tokens);
+            else if (type.Equals("MULTIPOINT"))
+                returned = ReadMultiPointText(tokens);
+            else if (type.Equals("MULTILINESTRING"))
+                returned = ReadMultiLineStringText(tokens);
+            else if (type.Equals("MULTIPOLYGON"))
+                returned = ReadMultiPolygonText(tokens);
+            else if (type.Equals("GEOMETRYCOLLECTION"))
+                returned = ReadGeometryCollectionText(tokens);
+            else throw new ParseException("Unknown type: " + type);
+
+            if (returned == null)
+                throw new NullReferenceException("Error reading geometry");
+
+            if (sridValue != null)
+                returned.SRID = Convert.ToInt32(sridValue);
+
+            return returned;
+        }
+
+        /// <summary>
+        /// Creates a <c>Point</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;Point Text.
+        /// </param>
+        /// <returns>A <c>Point</c> specified by the next token in
+        /// the stream.</returns>
+        private IPoint ReadPointText(IList tokens)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return geometryFactory.CreatePoint((ICoordinate)null);
+            IPoint point = geometryFactory.CreatePoint(GetPreciseCoordinate(tokens, false));
+            GetNextCloser(tokens);
+            return point;
+        }
+
+        /// <summary>
+        /// Creates a <c>LineString</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;LineString Text.
+        /// </param>
+        /// <returns>
+        /// A <c>LineString</c> specified by the next
+        /// token in the stream.</returns>
+        private ILineString ReadLineStringText(IList tokens)
+        {
+            return geometryFactory.CreateLineString(GetCoordinates(tokens, false));
+        }
+
+        /// <summary>
+        /// Creates a <c>LinearRing</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;LineString Text.
+        /// </param>
+        /// <returns>A <c>LinearRing</c> specified by the next
+        /// token in the stream.</returns>
+        private ILinearRing ReadLinearRingText(IList tokens)
+        {
+            return geometryFactory.CreateLinearRing(GetCoordinates(tokens, false));
+        }
+
+        /// <summary>
+        /// Creates a <c>MultiPoint</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;MultiPoint Text.
+        /// </param>
+        /// <returns>
+        /// A <c>MultiPoint</c> specified by the next
+        /// token in the stream.</returns>
+        private IMultiPoint ReadMultiPointText(IList tokens)
+        {
+            return geometryFactory.CreateMultiPoint(ToPoints(GetCoordinates(tokens, true)));
+        }
+
+        /// <summary> 
+        /// Creates an array of <c>Point</c>s having the given <c>Coordinate</c>s.
+        /// </summary>
+        /// <param name="coordinates">
+        /// The <c>Coordinate</c>s with which to create the <c>Point</c>s
+        /// </param>
+        /// <returns>
+        /// <c>Point</c>s created using this <c>WKTReader</c>
+        /// s <c>GeometryFactory</c>.
+        /// </returns>
+        private IPoint[] ToPoints(ICoordinate[] coordinates)
+        {
+            List<IPoint> points = new List<IPoint>();
+            for (int i = 0; i < coordinates.Length; i++)
+                points.Add(geometryFactory.CreatePoint(coordinates[i]));
+            return points.ToArray();
+        }
+
+        /// <summary>  
+        /// Creates a <c>Polygon</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a Polygon Text.
+        /// </param>
+        /// <returns>
+        /// A <c>Polygon</c> specified by the next token
+        /// in the stream.        
+        /// </returns>
+        private IPolygon ReadPolygonText(IList tokens)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return geometryFactory.CreatePolygon(
+                    geometryFactory.CreateLinearRing(new ICoordinate[] { }), new ILinearRing[] { });
+
+            List<ILinearRing> holes = new List<ILinearRing>();
+            ILinearRing shell = ReadLinearRingText(tokens);
+            nextToken = GetNextCloserOrComma(tokens);
+            while (nextToken.Equals(","))
+            {
+                ILinearRing hole = ReadLinearRingText(tokens);
+                holes.Add(hole);
+                nextToken = GetNextCloserOrComma(tokens);
+            }
+            return geometryFactory.CreatePolygon(shell, holes.ToArray());
+        }
+
+        /// <summary>
+        /// Creates a <c>MultiLineString</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a MultiLineString Text.
+        /// </param>
+        /// <returns>
+        /// A <c>MultiLineString</c> specified by the
+        /// next token in the stream.</returns>
+        private IMultiLineString ReadMultiLineStringText(IList tokens)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return geometryFactory.CreateMultiLineString(new ILineString[] { });
+
+            List<ILineString> lineStrings = new List<ILineString>();
+            ILineString lineString = ReadLineStringText(tokens);
+            lineStrings.Add(lineString);
+            nextToken = GetNextCloserOrComma(tokens);
+            while (nextToken.Equals(","))
+            {
+                lineString = ReadLineStringText(tokens);
+                lineStrings.Add(lineString);
+                nextToken = GetNextCloserOrComma(tokens);
+            }
+            return geometryFactory.CreateMultiLineString(lineStrings.ToArray());
+        }
+
+        /// <summary>  
+        /// Creates a <c>MultiPolygon</c> using the next token in the stream.
+        /// </summary>
+        /// <param name="tokens">Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a MultiPolygon Text.
+        /// </param>
+        /// <returns>
+        /// A <c>MultiPolygon</c> specified by the next
+        /// token in the stream, or if if the coordinates used to create the
+        /// <c>Polygon</c> shells and holes do not form closed linestrings.</returns>
+        private IMultiPolygon ReadMultiPolygonText(IList tokens)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return geometryFactory.CreateMultiPolygon(new IPolygon[] { });
+
+            List<IPolygon> polygons = new List<IPolygon>();
+            IPolygon polygon = ReadPolygonText(tokens);
+            polygons.Add(polygon);
+            nextToken = GetNextCloserOrComma(tokens);
+            while (nextToken.Equals(","))
+            {
+                polygon = ReadPolygonText(tokens);
+                polygons.Add(polygon);
+                nextToken = GetNextCloserOrComma(tokens);
+            }
+            return geometryFactory.CreateMultiPolygon(polygons.ToArray());
+        }
+
+        /// <summary>
+        /// Creates a <c>GeometryCollection</c> using the next token in the
+        /// stream.
+        /// </summary>
+        /// <param name="tokens">
+        /// Tokenizer over a stream of text in Well-known Text
+        /// format. The next tokens must form a &lt;GeometryCollection Text.
+        /// </param>
+        /// <returns>
+        /// A <c>GeometryCollection</c> specified by the
+        /// next token in the stream.</returns>
+        private IGeometryCollection ReadGeometryCollectionText(IList tokens)
+        {
+            string nextToken = GetNextEmptyOrOpener(tokens);
+            if (nextToken.Equals("EMPTY"))
+                return geometryFactory.CreateGeometryCollection(new IGeometry[] { });
+
+            List<IGeometry> geometries = new List<IGeometry>();
+            IGeometry geometry = ReadGeometryTaggedText(tokens);
+            geometries.Add(geometry);
+            nextToken = GetNextCloserOrComma(tokens);
+            while (nextToken.Equals(","))
+            {
+                geometry = ReadGeometryTaggedText(tokens);
+                geometries.Add(geometry);
+                nextToken = GetNextCloserOrComma(tokens);
+            }
+            return geometryFactory.CreateGeometryCollection(geometries.ToArray());
+        }
+    }
+}
\ No newline at end of file

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI/OSGeo.MapGuide.MaestroAPI.csproj	2012-01-24 16:38:24 UTC (rev 6453)
@@ -221,6 +221,7 @@
     <Compile Include="Feature\PropertyValue.cs" />
     <Compile Include="Feature\ReaderBase.cs" />
     <Compile Include="Feature\RecordBase.cs" />
+    <Compile Include="Internal\FixedWKTReader.cs" />
     <Compile Include="IO\NsDoc.cs" />
     <Compile Include="Mapping\Collections.cs" />
     <Compile Include="Mapping\NsDoc.cs" />

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlReaderBase.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlReaderBase.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlReaderBase.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -25,6 +25,7 @@
 using System.Xml;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Http
 {
@@ -32,7 +33,7 @@
 
     public abstract class XmlReaderBase : ReaderBase
     {
-        protected WKTReader _wktReader;
+        protected FixedWKTReader _wktReader;
         protected XmlTextReader _reader;
 
         protected XmlProperty[] _properties;
@@ -63,7 +64,7 @@
         public XmlReaderBase(Stream source) 
         {
             _reader = new XmlTextReader(source);
-            _wktReader = new WKTReader();
+            _wktReader = new FixedWKTReader();
             _reader.WhitespaceHandling = WhitespaceHandling.Significant;
             _propertyMap = new Dictionary<string, XmlProperty>();
 

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlRecord.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlRecord.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Http/XmlRecord.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -24,6 +24,7 @@
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using System.Xml;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Http
 {
@@ -42,7 +43,7 @@
 
     public class XmlRecord : RecordBase
     {
-        public XmlRecord(XmlProperty[] properties, WKTReader wktReader, XmlNodeList propertyNodes, string nameElement, string valueElement)
+        public XmlRecord(XmlProperty[] properties, FixedWKTReader wktReader, XmlNodeList propertyNodes, string nameElement, string valueElement)
         {
             for (int i = 0; i < properties.Length; i++)
             {

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/Commands/FeatureCommandsImpl.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/Commands/FeatureCommandsImpl.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/Commands/FeatureCommandsImpl.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,6 +23,7 @@
 using OSGeo.MapGuide.MaestroAPI.Commands;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using OSGeo.MapGuide.MaestroAPI.Feature;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 #if LOCAL_API
 namespace OSGeo.MapGuide.MaestroAPI.Local.Commands
@@ -57,13 +58,13 @@
     {
         static MgAgfReaderWriter _agfRw;
         static MgWktReaderWriter _wktRw;
-        static GisSharpBlog.NetTopologySuite.IO.WKTReader _reader;
+        static FixedWKTReader _reader;
 
         static GeomConverter()
         {
             _agfRw = new MgAgfReaderWriter();
             _wktRw = new MgWktReaderWriter();
-            _reader = new GisSharpBlog.NetTopologySuite.IO.WKTReader();
+            _reader = new FixedWKTReader();
         }
 
         public static MgByteReader GetAgf(GeoAPI.Geometries.IGeometry geom)

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeDataReader.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeDataReader.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeDataReader.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,20 +23,21 @@
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
     public class LocalNativeDataReader : ReaderBase
     {
         private MgDataReader _reader;
-        private WKTReader _mgReader;
+        private FixedWKTReader _mgReader;
         private MgAgfReaderWriter _agfRw;
         private MgWktReaderWriter _wktRw;
 
         public LocalNativeDataReader(MgDataReader reader) 
         {
             _reader = reader;
-            _mgReader = new WKTReader();
+            _mgReader = new FixedWKTReader();
             _agfRw = new MgAgfReaderWriter();
             _wktRw = new MgWktReaderWriter();
         }

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeature.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeature.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeature.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,12 +23,13 @@
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
     public class LocalNativeFeature : FeatureBase
     {
-        public LocalNativeFeature(MgFeatureReader reader, WKTReader mgReader, MgAgfReaderWriter agfRw, MgWktReaderWriter wktRw)
+        public LocalNativeFeature(MgFeatureReader reader, FixedWKTReader mgReader, MgAgfReaderWriter agfRw, MgWktReaderWriter wktRw)
             : base(Utility.ConvertClassDefinition(reader.GetClassDefinition()))
         {
             for (int i = 0; i < reader.GetPropertyCount(); i++)

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeatureReader.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeatureReader.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeFeatureReader.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,20 +23,21 @@
 using OSGeo.MapGuide.MaestroAPI.Exceptions;
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
     public class LocalNativeFeatureReader : FeatureReaderBase
     {
         private MgFeatureReader _reader;
-        private WKTReader _mgReader;
+        private FixedWKTReader _mgReader;
         private MgAgfReaderWriter _agfRw;
         private MgWktReaderWriter _wktRw;
 
         public LocalNativeFeatureReader(MgFeatureReader reader) 
         {
             _reader = reader;
-            _mgReader = new WKTReader();
+            _mgReader = new FixedWKTReader();
             _agfRw = new MgAgfReaderWriter();
             _wktRw = new MgWktReaderWriter();
             base.ClassDefinition = Utility.ConvertClassDefinition(reader.GetClassDefinition());

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeRecord.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeRecord.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeRecord.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,12 +23,13 @@
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
     public class LocalNativeRecord : RecordBase
     {
-        public LocalNativeRecord(MgReader reader, WKTReader mgReader, MgAgfReaderWriter agfRw, MgWktReaderWriter wktRw)
+        public LocalNativeRecord(MgReader reader, FixedWKTReader mgReader, MgAgfReaderWriter agfRw, MgWktReaderWriter wktRw)
         {
             for (int i = 0; i < reader.GetPropertyCount(); i++)
             {

Modified: trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeSqlReader.cs
===================================================================
--- trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeSqlReader.cs	2012-01-24 13:34:05 UTC (rev 6452)
+++ trunk/Tools/Maestro/OSGeo.MapGuide.MaestroAPI.Native/LocalNativeSqlReader.cs	2012-01-24 16:38:24 UTC (rev 6453)
@@ -23,20 +23,21 @@
 using OSGeo.MapGuide.MaestroAPI.Feature;
 using OSGeo.MapGuide.MaestroAPI.Schema;
 using GisSharpBlog.NetTopologySuite.IO;
+using OSGeo.MapGuide.MaestroAPI.Internal;
 
 namespace OSGeo.MapGuide.MaestroAPI.Native
 {
     public class LocalNativeSqlReader : ReaderBase
     {
         private MgSqlDataReader _reader;
-        private WKTReader _mgReader;
+        private FixedWKTReader _mgReader;
         private MgAgfReaderWriter _agfRw;
         private MgWktReaderWriter _wktRw;
 
         public LocalNativeSqlReader(MgSqlDataReader reader) 
         {
             _reader = reader;
-            _mgReader = new WKTReader();
+            _mgReader = new FixedWKTReader();
             _agfRw = new MgAgfReaderWriter();
             _wktRw = new MgWktReaderWriter();
         }



More information about the mapguide-commits mailing list