#region Disclaimer / License // Copyright (C) 2010, Jackie Ng // http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@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 OSGeo.MapGuide.ObjectModels.MapDefinition; using OSGeo.MapGuide.ObjectModels.LayerDefinition; using OSGeo.MapGuide.MaestroAPI.Serialization; using OSGeo.MapGuide.MaestroAPI.Resource; namespace OSGeo.MapGuide.MaestroAPI.Mapping { /// /// Describes a FDO property /// public class PropertyInfo { /// /// Initializes a new instance of the class. /// /// The name. /// The type. public PropertyInfo(string name, Type type) { this.Name = name; this.Type = type; } /// /// Gets or sets the name. /// /// The name. public string Name { get; set; } /// /// Gets or sets the type. /// /// The type. public Type Type { get; set; } } /// /// Represents a runtime map layer /// public class RuntimeMapLayer : MapObservable { //From MgLayerType internal const int kBaseMap = 2; internal const int kDynamic = 1; const double InfinityScale = double.MaxValue; internal RuntimeMap Parent { get; private set; } internal RuntimeMapLayer(RuntimeMap parent) { _scaleRanges = new double[] { 0.0, InfinityScale }; this.Type = kDynamic; this.IdentityProperties = new PropertyInfo[0]; this.ObjectId = Guid.NewGuid().ToString(); this.Parent = parent; this.Group = string.Empty; } internal RuntimeMapLayer(RuntimeMap parent, ILayerDefinition ldf) : this(parent) { Check.NotNull(ldf, "ldf"); this.LayerDefinitionID = ldf.ResourceID; this.ExpandInLegend = false; this.Name = ResourceIdentifier.GetName(ldf.ResourceID); this.Selectable = true; this.ShowInLegend = true; this.Visible = true; _disableChangeTracking = false; } internal RuntimeMapLayer(RuntimeMap parent, IMapLayer source, ILayerDefinition ldf) : this(parent, (IBaseMapLayer)source, ldf) { _disableChangeTracking = true; this.Group = source.Group; this.Visible = source.Visible; _disableChangeTracking = false; } internal RuntimeMapLayer(RuntimeMap parent, IBaseMapLayer source, ILayerDefinition ldf) : this(parent, ldf) { Check.NotNull(source, "source"); Check.NotNull(ldf, "ldf"); Check.Precondition(source.ResourceId == ldf.ResourceID, "source.ResourceId == ldf.ResourceID"); _disableChangeTracking = true; this.LayerDefinitionID = source.ResourceId; this.ExpandInLegend = source.ExpandInLegend; this.Name = source.Name; this.Selectable = source.Selectable; this.ShowInLegend = source.ShowInLegend; this.LegendLabel = source.LegendLabel; this.NeedsRefresh = false; this.DisplayOrder = 0; switch (ldf.SubLayer.LayerType) { case LayerType.Drawing: { } break; case LayerType.Raster: { IRasterLayerDefinition rdf = (IRasterLayerDefinition)ldf.SubLayer; this.FeatureSourceID = rdf.ResourceId; this.GeometryPropertyName = rdf.Geometry; this.QualifiedClassName = rdf.FeatureName; if (rdf.GridScaleRangeCount > 0) { _scaleRanges = new double[rdf.GridScaleRangeCount * 2]; int i = 0; foreach (var gsr in rdf.GridScaleRange) { _scaleRanges[i * 2] = gsr.MinScale.HasValue ? gsr.MinScale.Value : 0; _scaleRanges[i * 2 + 1] = gsr.MaxScale.HasValue ? gsr.MaxScale.Value : InfinityScale; i++; } } } break; case LayerType.Vector: { IVectorLayerDefinition vld = (IVectorLayerDefinition)ldf.SubLayer; this.FeatureSourceID = vld.ResourceId; this.GeometryPropertyName = vld.Geometry; this.QualifiedClassName = vld.FeatureName; this.Filter = vld.Filter; if (vld.HasVectorScaleRanges()) { int vsrCount = vld.GetScaleRangeCount(); _scaleRanges = new double[vsrCount * 2]; for (int i = 0; i < vsrCount; i++) { var vsr = vld.GetScaleRangeAt(i); _scaleRanges[i * 2] = vsr.MinScale.HasValue ? vsr.MinScale.Value : 0; _scaleRanges[i * 2 + 1] = vsr.MaxScale.HasValue ? vsr.MaxScale.Value : InfinityScale; } } this.HasTooltips = !string.IsNullOrEmpty(vld.ToolTip); //get identity property information } break; } _disableChangeTracking = false; } private bool _visible; /// /// Gets or sets a value indicating whether this is visible. /// /// true if visible; otherwise, false. public bool Visible { get { return _visible; } set { SetField(ref _visible, value, "Visible"); } } private string _group; /// /// Gets or sets the group. /// /// The group. public string Group { get { return _group; } set { SetField(ref _group, value, "Group"); } } /// /// Gets the layer definition ID. /// /// The layer definition ID. public string LayerDefinitionID { get; private set; } private bool _selectable; /// /// Gets or sets a value indicating whether this is selectable. /// /// true if selectable; otherwise, false. public bool Selectable { get { return _selectable; } set { SetField(ref _selectable, value, "Selectable"); } } private string _name; /// /// Gets or sets the name. /// /// The name. public string Name { get { return _name; } set { SetField(ref _name, value, "Name"); } } private bool _showInLegend; /// /// Gets or sets a value indicating whether [show in legend]. /// /// true if [show in legend]; otherwise, false. public bool ShowInLegend { get { return _showInLegend; } set { SetField(ref _showInLegend, value, "ShowInLegend"); } } private string _legendLabel; /// /// Gets or sets the legend label. /// /// The legend label. public string LegendLabel { get { return _legendLabel; } set { SetField(ref _legendLabel, value, "LegendLabel"); } } private bool _expandInLegend; /// /// Gets or sets a value indicating whether [expand in legend]. /// /// true if [expand in legend]; otherwise, false. public bool ExpandInLegend { get { return _expandInLegend; } set { SetField(ref _expandInLegend, value, "ExpandInLegend"); } } /// /// Gets or sets the feature source ID. /// /// The feature source ID. public string FeatureSourceID { get; internal set; } /// /// Gets or sets the name of the qualified class. /// /// The name of the qualified class. public string QualifiedClassName { get; internal set; } /// /// Gets the identity properties. /// /// The identity properties. public PropertyInfo[] IdentityProperties { get; private set; } /// /// Gets the object id. /// /// The object id. public string ObjectId { get; internal set; } /// /// Gets the name of the geometry property. /// /// The name of the geometry property. public string GeometryPropertyName { get; private set; } /// /// Gets the filter. /// /// The filter. public string Filter { get; internal set; } /// /// Gets the type /// public int Type { get; internal set; } /// /// Gets the display order /// public double DisplayOrder { get; internal set; } /// /// Gets whether this layer needs to be refreshed /// public bool NeedsRefresh { get; internal set; } /// /// Gets whether this layer has tooltips /// public bool HasTooltips { get; internal set; } /// /// Gets the schema name /// public string SchemaName { get { var tokens = this.QualifiedClassName.Split(':'); if (tokens.Length == 2) return tokens[0]; return string.Empty; } } private double[] _scaleRanges; /// /// Serializes this instance to a binary stream /// /// public void Serialize(MgBinarySerializer s) { s.Write(this.Group); if (s.SiteVersion <= SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1)) s.WriteClassId(19003); else s.WriteClassId(30501); s.WriteResourceIdentifier(this.LayerDefinitionID); if (s.SiteVersion < SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { s.Write(this.Name); s.Write(this.ObjectId); s.Write(this.Type); s.Write((byte)(this.Visible ? 1 : 0)); s.Write((byte)(this.Selectable ? 1 : 0)); s.Write((byte)(this.ShowInLegend ? 1 : 0)); s.Write((byte)(this.ExpandInLegend ? 1 : 0)); s.Write(this.LegendLabel); s.Write((byte)(this.NeedsRefresh ? 1 : 0)); s.Write(this.DisplayOrder); s.Write(_scaleRanges.Length); foreach (double d in _scaleRanges) s.Write(d); s.Write(this.FeatureSourceID); s.Write(this.QualifiedClassName); s.Write(this.GeometryPropertyName); s.Write(this.IdentityProperties.Length); foreach (var x in this.IdentityProperties) { s.Write((short)ConvertNetTypeToMgType(x.Type)); s.Write(x.Name); } } else { s.WriteStringInternal(this.Name); s.WriteStringInternal(this.ObjectId); s.WriteRaw(BitConverter.GetBytes(this.Type)); int flags = 0; flags |= this.Visible ? 1 : 0; flags |= this.Selectable ? 2 : 0; flags |= this.ShowInLegend ? 4 : 0; flags |= this.ExpandInLegend ? 8 : 0; flags |= this.NeedsRefresh ? 16 : 0; flags |= this.HasTooltips ? 32 : 0; s.WriteRaw(new byte[] { (byte)flags }); s.WriteStringInternal(this.LegendLabel); s.WriteRaw(BitConverter.GetBytes(this.DisplayOrder)); s.WriteRaw(BitConverter.GetBytes(_scaleRanges.Length)); foreach (double d in _scaleRanges) s.WriteRaw(BitConverter.GetBytes(d)); s.WriteStringInternal(this.FeatureSourceID); s.WriteStringInternal(this.QualifiedClassName); if (s.SiteVersion > SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS2_1)) s.WriteStringInternal(this.Filter); s.WriteStringInternal(this.SchemaName); s.WriteStringInternal(this.GeometryPropertyName); s.WriteRaw(BitConverter.GetBytes(this.IdentityProperties.Length)); foreach (var x in this.IdentityProperties) { s.WriteRaw(BitConverter.GetBytes((short)ConvertNetTypeToMgType(x.Type))); s.WriteStringInternal(x.Name); } } } /// /// Initializes this instance with the specified binary stream /// /// public void Deserialize(MgBinaryDeserializer d) { this.Group = d.ReadString(); int classid = d.ReadClassId(); if (d.SiteVersion <= SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1) && classid != 19003) throw new Exception("Resource Identifier expected, but got: " + classid.ToString()); if (d.SiteVersion > SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1) && classid != 30501) throw new Exception("Resource Identifier expected, but got: " + classid.ToString()); this.LayerDefinitionID = d.ReadResourceIdentifier(); if (d.SiteVersion < SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { this.Name = d.ReadString(); this.ObjectId = d.ReadString(); this.Type = d.ReadInt32(); this.Visible = d.ReadByte() > 0; this.Selectable = d.ReadByte() > 0; this.ShowInLegend = d.ReadByte() > 0; this.ExpandInLegend = d.ReadByte() > 0; this.LegendLabel = d.ReadString(); this.NeedsRefresh = d.ReadByte() > 0; this.DisplayOrder = d.ReadDouble(); var scaleRanges = new List(); int scales = d.ReadInt32(); while (scales-- > 0) scaleRanges.Add(d.ReadDouble()); _scaleRanges = scaleRanges.ToArray(); this.FeatureSourceID = d.ReadString(); this.QualifiedClassName = d.ReadString(); this.GeometryPropertyName = d.ReadString(); var ids = new List(); int idCount = d.ReadInt32(); while (idCount-- > 0) { short idType = d.ReadInt16(); string idName = d.ReadString(); ids.Add(new PropertyInfo(idName, ConvertMgTypeToNetType(idType))); } this.IdentityProperties = ids.ToArray(); } else { //AAARGH!!! Now they bypass their own header system .... this.Name = d.ReadInternalString(); this.ObjectId = d.ReadInternalString(); this.Type = BitConverter.ToInt32(d.ReadStreamRepeat(4), 0); int flags = d.ReadStreamRepeat(1)[0]; this.Visible = (flags & 1) > 0; this.Selectable = (flags & 2) > 0; this.ShowInLegend = (flags & 4) > 0; this.ExpandInLegend = (flags & 8) > 0; this.NeedsRefresh = (flags & 16) > 0; this.HasTooltips = (flags & 32) > 0; this.LegendLabel = d.ReadInternalString(); this.DisplayOrder = BitConverter.ToDouble(d.ReadStreamRepeat(8), 0); var scaleRanges = new List(); int scales = BitConverter.ToInt32(d.ReadStreamRepeat(4), 0); while (scales-- > 0) scaleRanges.Add(BitConverter.ToDouble(d.ReadStreamRepeat(8), 0)); _scaleRanges = scaleRanges.ToArray(); this.FeatureSourceID = d.ReadInternalString(); this.QualifiedClassName = d.ReadInternalString(); if (d.SiteVersion > SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS2_1)) this.Filter = d.ReadInternalString(); //this.SchemaName = d.ReadInternalString(); d.ReadInternalString(); this.GeometryPropertyName = d.ReadInternalString(); var ids = new List(); int idCount = BitConverter.ToInt32(d.ReadStreamRepeat(4), 0); while (idCount-- > 0) { short idType = BitConverter.ToInt16(d.ReadStreamRepeat(2), 0); string idName = d.ReadInternalString(); ids.Add(new PropertyInfo(idName, ConvertMgTypeToNetType(idType))); } this.IdentityProperties = ids.ToArray(); } } //from MgPropertyType const int Blob = 10; const int Boolean = 1; const int Byte = 2; const int Clob = 11; const int DateTime = 3; const int Double = 5; const int Feature = 12; const int Geometry = 13; const int Int16 = 6; const int Int32 = 7; const int Int64 = 8; const int Null = 0; const int Raster = 14; const int Single = 4; const int String = 9; private static short ConvertNetTypeToMgType(Type type) { if (type == typeof(short)) return Int16; else if (type == typeof(byte)) return Byte; else if (type == typeof(bool)) return Boolean; else if (type == typeof(int)) return Int32; else if (type == typeof(long)) return Int64; else if (type == typeof(float)) return Single; else if (type == typeof(double)) return Double; else if (type == Utility.GeometryType) return Geometry; else if (type == typeof(string)) return String; else if (type == typeof(DateTime)) return DateTime; else if (type == Utility.RasterType) return Raster; else if (type == typeof(byte[])) return Blob; throw new Exception("Failed to find type for: " + type.FullName.ToString()); } private static Type ConvertMgTypeToNetType(short idType) { switch (idType) { case Byte: return typeof(byte); case Int16: return typeof(short); case Int32: return typeof(int); case Int64: return typeof(long); case Single: return typeof(float); case Double: return typeof(double); case Boolean: return typeof(bool); case Geometry: return Utility.GeometryType; case String: return typeof(string); case DateTime: return typeof(DateTime); case Raster: return Utility.RasterType; case Blob: return typeof(byte[]); case Clob: return typeof(byte[]); default: throw new Exception("Failed to find type for: " + idType.ToString()); } } /// /// Raises the event /// /// protected override void OnPropertyChanged(string propertyName) { if (_disableChangeTracking) return; //register change items on map switch (propertyName) { case "Group": this.Parent.OnLayerParentChanged(this, this.ObjectId); break; case "Visible": this.Parent.OnLayerVisibilityChanged(this, this.Visible ? "1" : "0"); break; case "ShowInLegend": this.Parent.OnLayerDisplayInLegendChanged(this, this.ShowInLegend ? "1" : "0"); break; case "LegendLabel": this.Parent.OnLayerLegendLabelChanged(this, this.LegendLabel); break; case "LayerDefinitionID": this.Parent.OnLayerDefinitionChanged(this); break; case "Selectable": this.Parent.OnLayerSelectabilityChanged(this, this.Selectable ? "1" : "0"); break; } base.OnPropertyChanged(propertyName); } } }