//----------------------------------------------------------------------- // // Copyright (c) 2012 Deltares. All rights reserved. // // B. Faassen // barry.faassen@deltares.nl // 1-8-2012 // n.a. //----------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Xml.Serialization; using Deltares.Standard; using Deltares.Standard.Attributes; using Deltares.Standard.EventPublisher; using Deltares.Standard.IO.Xml; using Deltares.Standard.Specifications; using GeoAPI.Geometries; using NetTopologySuite.Geometries; using Validator = Deltares.Standard.Specifications.Validator; using XmlSerializer = Deltares.Standard.IO.Xml.XmlSerializer; namespace Deltares.Dam.Data.Sensors { /// /// This class represents a sensor or monitoring point used in dikes. /// This entity is created for Dam Live /// [Serializable] public class Sensor : IName, IVisibleEnabled { #region Business Rules /// /// Specication to test if the value of the candidate is valid /// internal class ContiansAtLeastOneItem : PredicateSpecification> { public ContiansAtLeastOneItem() : base(x => x.Any()) { Description = "The sensor should contain at least one PL Line mapping."; } } #endregion private readonly IGeometry geometry; private double relativeLocation; private readonly HashSet plLineTypes; private int id; public Sensor() { plLineTypes = new HashSet(); ID = -1; geometry = new Point(0,0,0); } public Sensor(Point point) : this() { if (point == null) throw new ArgumentNullException("point"); this.geometry = point; } public Sensor(double x, double y, double z) : this(new Point(x, y, z)) { } /// /// Gets or sets the ID. /// /// /// The ID should be unique. /// [PropertyOrder(1,1)] public int ID { get { return id; } set { id = value; DataEventPublisher.AfterChange(this, s => s.ID); } } /// /// Gets or sets the name of this sensor. /// /// /// The name string value should not be empty and unique. /// [Specification(typeof(NotEmptySpecification))] [PropertyOrder(1, 2)] public string Name { get; set; } /// /// Gets or sets the depth. /// /// /// The depth. /// [PropertyOrder(1, 5)] [Format("F3")] public double Depth { get { return ZRd; } set { DataEventPublisher.BeforeChange(this, s => s.Depth); ZRd = value; DataEventPublisher.AfterChange(this, s => s.Depth); } } /// /// Gets or sets the relative location along the profile. /// /// /// The relative location in meter. /// [PropertyOrder(1, 4)] [Format("F3")] public double RelativeLocation { get { return relativeLocation; } set { DataEventPublisher.BeforeChange(this, s => s.RelativeLocation); relativeLocation = value; RelativeLocationSpecified = true; DataEventPublisher.AfterChange(this, s => s.RelativeLocation); } } /// /// Gets or sets the X rd. /// /// /// The X rd. /// [Browsable(false)] public double XRd { get { return geometry.Coordinate.X; } set { geometry.Coordinate.X = value; } } /// /// Gets or sets the Y rd. /// /// /// The Y rd. /// [Browsable(false)] public double YRd { get { return geometry.Coordinate.Y; } set { geometry.Coordinate.Y = value; } } /// /// Gets or sets the Z rd. Same as Depth?? /// /// /// The Z rd. /// [Browsable(false)] public double ZRd { get { return geometry.Coordinate.Z; } set { geometry.Coordinate.Z = value; } } /// /// Gets a value indicating whether the relative location is specified. /// /// /// true if the relative location is specified; otherwise, false. /// [Browsable(false)] public bool RelativeLocationSpecified { get; private set; } private SensorType type; /// /// Gets or sets the type of this sensor. /// /// /// The type. Default value is PiezoMetricHead. /// [PropertyOrder(1, 7)] public SensorType Type { get { return type; } set { type = value; } } /// /// Gets or sets the PL line array. Used for serialization only. /// /// /// The PL line array. /// [XmlElement("PLLineMappings")] [Specification(typeof(NotNullSpecification))] [Specification(typeof(ContiansAtLeastOneItem))] [Browsable(false)] public PLLineType[] PLLineMappings { get { return plLineTypes.ToArray(); } set { ClearPLLines(); foreach (var lineType in value) { Add(lineType); } } } [XmlIgnore] [PropertyOrder(1, 6)] public string PLLineMappingsAsString { get { string res = ""; foreach (var plLineType in plLineTypes) { switch (plLineType) { case PLLineType.PL1: res = res + "1; "; break; case PLLineType.PL2: res = res + "2; "; break; case PLLineType.PL3: res = res + "3; "; break; case PLLineType.PL4: res = res + "4; "; break; } } return res; } set { ClearPLLines(); var locPlLineTypes = ParseStringToPlLineTypes(value); foreach (var plLineType in locPlLineTypes) { switch (plLineType) { case 1: plLineTypes.Add(PLLineType.PL1); break; case 2: plLineTypes.Add(PLLineType.PL2); break; case 3: plLineTypes.Add(PLLineType.PL3); break; case 4: plLineTypes.Add(PLLineType.PL4); break; } } } } private List ParseStringToPlLineTypes(string value) { value = value.Trim(); var ids = new List(); var idsarr = value.Split(new Char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in idsarr) { try { var val = Int32.Parse(s); ids.Add(val); } catch (Exception) { // surpress errors, just do not use value } } return ids; } /// /// Adds the specified PL line. /// /// The PL line. public void Add(PLLineType plLine) { plLineTypes.Add(plLine); } /// /// Removes the specified PL line. /// /// The PL line. public void Remove(PLLineType plLine) { plLineTypes.Remove(plLine); } /// /// Clears the PL lines list. /// public void ClearPLLines() { plLineTypes.Clear(); } /// /// Serializes this instance to a xml string. /// /// A xml string internal string Serialize() { var xmlSerializer = new XmlSerializer(); return xmlSerializer.SerializeToString(this); } /// /// Deserializes the specified XML. /// /// The XML to deserialize. /// A sensor instance internal static Sensor Deserialize(string xml) { var xmlDeserializer = new XmlDeserializer(); return (Sensor)xmlDeserializer.XmlDeserializeFromString(xml, typeof(Sensor)); } /// /// Determines whether this instance is valid. /// /// /// true if this instance is valid; otherwise, false. /// public bool IsValid() { return !Validator.Validate(this).Any(); } /// /// Determines whether this instance is transient (associated with a correct ID in the context of the repository). /// /// /// true if this instance is transient; otherwise, false. /// public bool IsTransient() { return ID < 0; } public override string ToString() { var name = string.IsNullOrWhiteSpace(Name) ? "name_not_set" : Name; return string.Format("[ID: {0}, Name: {1}, Depth: {2}, Type: {3}, RelativeLocation: {4}]", ID, name, Depth, Type, RelativeLocation); } public bool IsVisible(string property) { switch (property) { case "XRd": return false; case "YRd": return false; case "ZRd": return false; default: return true; } } public bool IsEnabled(string property) { return true; } } }