Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilLayer2DReader.cs
===================================================================
diff -u -rd2b5b334c49948fa49297a1d24c13bc98aa6ee1e -r0047bcf51f94a295f3e4854f9b93594ad01a9e70
--- Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilLayer2DReader.cs (.../SoilLayer2DReader.cs) (revision d2b5b334c49948fa49297a1d24c13bc98aa6ee1e)
+++ Ringtoets/Piping/src/Ringtoets.Piping.IO/SoilProfile/SoilLayer2DReader.cs (.../SoilLayer2DReader.cs) (revision 0047bcf51f94a295f3e4854f9b93594ad01a9e70)
@@ -1,8 +1,12 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Xml;
+using System.Xml.Linq;
+using System.Xml.Schema;
+using System.Xml.XPath;
using Ringtoets.Piping.Data;
using Ringtoets.Piping.IO.Builders;
using Ringtoets.Piping.IO.Properties;
@@ -23,212 +27,171 @@
private const string xElementName = "X";
private const string zElementName = "Z";
- private readonly XmlTextReader xmlTextReader;
+ private readonly XmlSchemaSet schema;
///
- /// Constructs a new , which uses the as the source of the
+ /// Constructs an instance of .
+ ///
+ /// Thrown when the XML-schema
+ /// could not be loaded.
+ internal SoilLayer2DReader()
+ {
+ schema = LoadXmlSchema();
+ }
+
+ ///
+ /// Reads a new using the as the source of the
/// geometry for a .
///
- /// An array of which contains the information of a
- /// in an XML document.
- /// Thrown when is null.
- internal SoilLayer2DReader(byte[] geometry)
+ /// An of which contains the information
+ /// of a in an XML document.
+ /// A new with information taken from the XML document.
+ /// Thrown when is null.
+ /// Thrown when:
+ ///
+ /// - is not valid XML.
+ /// - does not validate to the schema.
+ ///
+ ///
+ internal SoilLayer2D Read(byte[] geometry)
{
+ if (geometry == null)
+ {
+ throw new ArgumentNullException("geometry", Resources.SoilLayer2DReader_Geometry_is_null);
+ }
try
{
- xmlTextReader = new XmlTextReader(new MemoryStream(geometry));
+ return Read(XDocument.Load(new MemoryStream(geometry)));
}
- catch (ArgumentNullException e)
+ catch (XmlException e)
{
throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml, e);
}
}
///
- /// Reads the XML document and from this obtains the required information and constructs a based
- /// on this information.
+ /// Reads a new using the as the source of the
+ /// geometry for a .
///
+ /// An which contains the information of a
+ /// in an XML document.
/// A new with information taken from the XML document.
+ /// Thrown when is null.
/// Thrown when:
///
- /// - Reading from the XML document of the failed.
- /// - The segments do not form a loop for either the inner or outer loop.
+ /// - is not valid XML.
+ /// - does not validate to the schema.
///
///
- internal SoilLayer2D Read()
+ internal SoilLayer2D Read(XDocument geometry)
{
+ ValidateToSchema(geometry);
+
+ return ParseLayer(geometry);
+ }
+
+ private SoilLayer2D ParseLayer(XDocument geometry)
+ {
var pipingSoilLayer = new SoilLayer2D();
- try
+ var xmlOuterLoop = geometry.XPathSelectElement(string.Format("//{0}", outerLoopElementName));
+ var xmlInnerLoops = geometry.XPathSelectElements(string.Format("//{0}", innerLoopElementName));
+
+ if (xmlOuterLoop != null)
{
- while (xmlTextReader.Read())
- {
- List outerLoop;
- List innerLoop;
- if (TryParseLoop(outerLoopElementName, out outerLoop))
- {
- pipingSoilLayer.OuterLoop = outerLoop;
- }
- if (TryParseLoop(innerLoopElementName, out innerLoop))
- {
- pipingSoilLayer.AddInnerLoop(innerLoop);
- }
- }
+ pipingSoilLayer.OuterLoop = ParseGeometryLoop(xmlOuterLoop);
}
- catch (XmlException e)
+ foreach (XElement loop in xmlInnerLoops)
{
- throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml, e);
+ pipingSoilLayer.AddInnerLoop(ParseGeometryLoop(loop));
}
- catch (ArgumentException e)
- {
- throw new SoilLayer2DConversionException(e.Message, e);
- }
-
return pipingSoilLayer;
}
///
- /// Tries to parse the element with the given , which the reader should be currently pointing at, as a loop.
+ /// Adds the validation schema for the geometry to the .
///
- /// The name of the element which the reader should be currently pointing at.
- /// The result of parsing the element as a loop. null if the current element's name does not match .
- /// True if the reader currently points to an element with name . False otherwise.
- /// Thrown when not both HeadPoint and EndPoint are defined in
- /// the GeometryCurve XML element.
- private bool TryParseLoop(string elementName, out List loop)
+ /// The to add the validation schema to.
+ /// Thrown when:
+ ///
+ /// - The validation schema could not be correctly loaded.
+ /// - The validation failed.
+ ///
+ ///
+ private void ValidateToSchema(XDocument document)
{
- loop = null;
-
- if (IsElementWithName(elementName))
+ try
{
- loop = new List();
-
- if (!IsEmptyElement())
- {
- while (xmlTextReader.Read() && !IsEndElementWithName(elementName))
- {
- Segment2D segment;
- if (TryParseSegment(out segment))
- {
- loop.Add(segment);
- }
- }
- }
- return true;
+ document.Validate(schema, null);
}
- return false;
+ catch (InvalidOperationException e)
+ {
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml, e);
+ }
+ catch (XmlSchemaValidationException e)
+ {
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml, e);
+ }
}
- ///
- /// Tries to parse a GeometryCurve XML element to a .
- ///
- /// The segment reference in which to put the parsed .
- /// true if a segment could be parsed. false otherwise.
- /// Thrown when not both HeadPoint and EndPoint are defined in
- /// the GeometryCurve XML element.
- private bool TryParseSegment(out Segment2D segment)
+ private XmlSchemaSet LoadXmlSchema()
{
- segment = null;
- if (IsElementWithName(geometryCurveElementName) || IsElementWithName(endPointElementName))
+ var schemaFile = GetType().Assembly.GetManifestResourceStream("Ringtoets.Piping.IO.SoilProfile.XmlGeometrySchema.xsd");
+ if (schemaFile == null)
{
- var points = new Point2D[2];
- var index = 0;
- while (xmlTextReader.Read() && !IsEndElementWithName(geometryCurveElementName))
- {
- Point2D point;
- if (TryParsePoint(out point))
- {
- points[index] = point;
- index++;
- }
- }
- try
- {
- segment = new Segment2D(points[0], points[1]);
- return true;
- }
- catch (ArgumentNullException e)
- {
- throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml, e);
- }
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Schema_file_could_not_be_loaded);
}
- return false;
+ try
+ {
+ var xmlSchema = new XmlSchemaSet();
+ xmlSchema.Add(XmlSchema.Read(schemaFile, null));
+ return xmlSchema;
+ }
+ catch (XmlSchemaException e)
+ {
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Schema_file_could_not_be_loaded, e);
+ }
}
- ///
- /// Finds out whether the element which the reader is currently pointing at is empty.
- ///
- /// True if the element is empty. False otherwise.
- private bool IsEmptyElement()
+ private IEnumerable ParseGeometryLoop(XElement loop)
{
- return xmlTextReader.IsEmptyElement;
+ var loops = new Collection();
+ var curves = loop.XPathSelectElements(string.Format("//{0}", geometryCurveElementName));
+
+ foreach (XElement curve in curves)
+ {
+ loops.Add(ParseGeometryCurve(curve));
+ }
+ return loops;
}
- ///
- /// Tries to parse the element which the reader is currently pointing at as a point.
- ///
- /// The result of parsing the element as a point. null if current element is not a head or end point.
- /// True if the reader currently points to an element with name or . False otherwise.
- private bool TryParsePoint(out Point2D point)
+ private Segment2D ParseGeometryCurve(XElement curve)
{
- point = null;
-
- if (IsElementWithName(headPointElementName) || IsElementWithName(endPointElementName))
+ var headDefinition = curve.Element(headPointElementName);
+ var endDefinition = curve.Element(endPointElementName);
+ if (headDefinition != null && endDefinition != null)
{
- var pointValues = ReadChildValues();
- point = new Point2D
- {
- X = double.Parse(pointValues[xElementName], CultureInfo.InvariantCulture),
- Y = double.Parse(pointValues[zElementName], CultureInfo.InvariantCulture)
- };
- return true;
+ return new Segment2D(
+ ParsePoint(headDefinition),
+ ParsePoint(endDefinition)
+ );
}
- return false;
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml);
}
- ///
- /// Reads the name and values for the children of the current element and puts them in a name indexed dictionary.
- ///
- /// A . For each entry, key is equal to child element name and value is equal to the value of the child element's text node.
- private Dictionary ReadChildValues()
+ private Point2D ParsePoint(XElement point)
{
- string elementName = xmlTextReader.Name;
- var nodeSibblings = new Dictionary();
-
- while (xmlTextReader.Read() && !IsEndElementWithName(elementName))
+ var x = point.Element(xElementName);
+ var y = point.Element(zElementName);
+ if (x != null && y != null)
{
- if (xmlTextReader.NodeType == XmlNodeType.Element)
+ return new Point2D
{
- nodeSibblings[xmlTextReader.Name] = xmlTextReader.ReadString();
- }
+ X = double.Parse(x.Value, CultureInfo.InvariantCulture),
+ Y = double.Parse(y.Value, CultureInfo.InvariantCulture)
+ };
}
-
- return nodeSibblings;
+ throw new SoilLayer2DConversionException(Resources.SoilLayer2DReader_Geometry_contains_no_valid_xml);
}
-
- ///
- /// Checks whether the element the reader is currently pointing at is of type and has a name equal to .
- ///
- /// The name which the element should have.
- /// True if the current element has type and its name is equal to .
- private bool IsElementWithName(string name)
- {
- var isElement = xmlTextReader.NodeType == XmlNodeType.Element;
- var isPoint = xmlTextReader.Name == name;
-
- return isElement && isPoint;
- }
- ///
- /// Checks whether the element the reader is currently pointing at is of type and has a name equal to .
- ///
- /// The name which the end element should have.
- /// True if the current element has type and its name is equal to .
- private bool IsEndElementWithName(string name)
- {
- var isElement = xmlTextReader.NodeType == XmlNodeType.EndElement;
- var isPoint = xmlTextReader.Name == name;
-
- return isElement && isPoint;
- }
}
}
\ No newline at end of file