#region Disclaimer / License // Copyright (C) 2009, Kenneth Skovhede // http://www.hexad.dk, opensource@hexad.dk // // 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; namespace OSGeo.MapGuide.MaestroAPI.RuntimeClasses { /// /// Implementation of the runtime map. This class is prone to breaking if the MapGuide server code changes. /// An implementation of RFC 21 can correct this problem. /// public class RuntimeMap : OSGeo.MapGuide.MaestroAPI.MapDefinition { protected string m_objid; protected const int MgBinaryVersion = 262144; //1; protected const int ClassId = 11500; //30500; protected double[] m_center = new double[2]; protected double m_scale; protected ResourceIdentifier m_resourceID; protected new RuntimeMapLayerCollection m_mapLayer; protected new RuntimeMapGroupCollection m_mapLayerGroup; protected MaestroAPI.Selection m_selection = null; Box2DType m_dataExtent = new Box2DType(); int m_displaydpi; int m_display_width; int m_display_height; double m_metersPerUnit; int m_layerRefreshMode; double[] m_finiteScales = new double[0]; ArrayList m_changeList = new ArrayList(); byte[] m_layersGroupBlob = new byte[0]; #if DEBUG public RuntimeMap(BinarySerializer.MgBinaryDeserializer ds, BinarySerializer.MgBinaryDeserializer ds2) : this() { Deserialize(ds); DeserializeLayerData(ds2); } #endif internal RuntimeMap() : base() { m_mapLayer = new RuntimeMapLayerCollection(); m_mapLayerGroup = new RuntimeMapGroupCollection(); } public RuntimeMap(OSGeo.MapGuide.MaestroAPI.MapDefinition map) : this() { if (map.CurrentConnection == null) throw new Exception("Map must have a connection for construction to work"); map.SortGroupList(); this.CurrentConnection = map.CurrentConnection; this.m_resourceID = map.ResourceId; base.m_resourceId = map.ResourceId; base.m_name = map.Name; this.m_objid = Guid.NewGuid().ToString(); this.m_center[0] = ((map.Extents.MaxX - map.Extents.MinX) / 2) + map.Extents.MinX; this.m_center[1] = ((map.Extents.MaxY - map.Extents.MinY) / 2) + map.Extents.MinY; base.m_extents = new Box2DType(); base.m_extents.MinX = map.Extents.MinX; base.m_extents.MaxX = map.Extents.MaxX; base.m_extents.MinY = map.Extents.MinY; base.m_extents.MaxY = map.Extents.MaxY; m_dataExtent.MinX = map.Extents.MinX; m_dataExtent.MinY = map.Extents.MinY; m_dataExtent.MaxX = map.Extents.MaxX; m_dataExtent.MaxY = map.Extents.MaxY; base.m_backgroundColor = map.BackgroundColor; base.m_coordinateSystem = map.CoordinateSystem; this.m_metersPerUnit = 1.0; //TODO: Create coordsys and get real Meters Per Unit from Coordsys if (this.m_mapLayer == null) this.m_mapLayer = new RuntimeMapLayerCollection(); int dispIndex = 0; foreach(OSGeo.MapGuide.MaestroAPI.MapLayerType layer in map.Layers) { if (layer.Parent == null) layer.Parent = map; RuntimeMapLayer rtl = new RuntimeMapLayer(layer); rtl.SetParent(this); rtl.DisplayOrder = (++dispIndex) * 1000; this.m_mapLayer.Add(rtl); } foreach(OSGeo.MapGuide.MaestroAPI.MapLayerGroupType group in map.LayerGroups) { if (group.Parent != null) group.Parent = map; RuntimeMapGroup rtg = new RuntimeMapGroup(group); this.m_mapLayerGroup.Add(rtg); } if (map.BaseMapDefinition != null && map.BaseMapDefinition.BaseMapLayerGroup != null) foreach (OSGeo.MapGuide.MaestroAPI.BaseMapLayerGroupCommonType group in map.BaseMapDefinition.BaseMapLayerGroup) { if (group.BaseMapLayer != null) foreach(BaseMapLayerType layer in group.BaseMapLayer) { if (layer.Parent == null) layer.Parent = map; RuntimeMapLayer rtl = new RuntimeMapLayer(layer, group.Name, true); rtl.Type = OSGeo.MapGuide.MgLayerType.BaseMap; rtl.SetParent(this); rtl.DisplayOrder = (++dispIndex) * 1000; this.m_mapLayer.Add(rtl); } RuntimeMapGroup rtg = new RuntimeMapGroup(group); this.m_mapLayerGroup.Add(rtg); } if (map.BaseMapDefinition != null && map.BaseMapDefinition.FiniteDisplayScale != null) { m_finiteScales = new double[map.BaseMapDefinition.FiniteDisplayScale.Count]; for(int i =0; i < map.BaseMapDefinition.FiniteDisplayScale.Count; i++) m_finiteScales[i] = map.BaseMapDefinition.FiniteDisplayScale[i]; } else m_finiteScales = new double[0]; /*if (this.Layers.Count > 0) { SortedList sl = new SortedList(); foreach(RuntimeMapLayer l in this.Layers) foreach(double d in l.Scaleranges) if (d > 0.0 && !sl.ContainsKey(d)) sl.Add(d, d); int i = 0; m_finiteScales = new double[sl.Count]; foreach(double d in sl.Keys) m_finiteScales[i++] = d; } else m_finiteScales = new double[] {0.0, RuntimeMapLayer.InfinityScale };*/ m_layerRefreshMode = 1; m_scale = 500; m_displaydpi = 96; m_display_width = 1024; m_display_height = 768; } public new RuntimeMapLayerCollection Layers { get { return m_mapLayer; } set { m_mapLayer = value; } } public new RuntimeMapGroupCollection LayerGroups { get { return m_mapLayerGroup; } set { m_mapLayerGroup = value; } } public bool HasLoadedSelectionXml { get { return m_selection != null; } } public MaestroAPI.Selection Selection { get { if (m_selection == null) m_selection = new OSGeo.MapGuide.MaestroAPI.Selection(this, m_serverConnection.GetSelectionXml(m_resourceID)); return m_selection; } } internal void Serialize(BinarySerializer.MgBinarySerializer s) { if (s.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { s.Write(MgBinaryVersion); s.WriteResourceIdentifier(m_resourceID); } s.Write(base.m_name); s.Write(m_objid); s.WriteResourceIdentifier(base.m_resourceId); s.Write(base.m_coordinateSystem); base.m_extents.Serialize(s); s.WriteCoordinates(m_center, 0); s.Write(m_scale); m_dataExtent.Serialize(s); s.Write(m_displaydpi); s.Write(m_display_width ); s.Write(m_display_height); s.Write(Utility.SerializeHTMLColor(base.m_backgroundColor, true)); s.Write(m_metersPerUnit); if (s.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) s.Write(m_layerRefreshMode); s.Write(m_finiteScales.Length); foreach(double d in m_finiteScales) s.Write(d); if (s.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { SerializeChangeMap(s); s.Write((int)0); } else { SerializeLayerData(s); SerializeChangeMap(s); } } internal void SerializeLayerData(BinarySerializer.MgBinarySerializer s) { if (m_mapLayerGroup == null) s.Write((int)0); else { s.Write((int)m_mapLayerGroup.Count); foreach(RuntimeMapGroup g in m_mapLayerGroup) g.Serialize(s); } if (m_mapLayer == null) s.Write((int)0); else { s.Write(m_mapLayer.Count); foreach(RuntimeMapLayer t in m_mapLayer) t.Serialize(s); } } protected void SerializeChangeMap(BinarySerializer.MgBinarySerializer s) { s.Write(m_changeList.Count); foreach(ChangeList cl in m_changeList) { s.Write(cl.IsLayer); s.Write(cl.ObjectId); s.Write(cl.Changes.Count); foreach(Change c in cl.Changes) { s.Write((int)c.Type); s.Write(c.Params); } } } internal void Deserialize(BinarySerializer.MgBinaryDeserializer d) { if (d.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { if (d.ReadInt32() != MgBinaryVersion) throw new Exception("Invalid map version"); m_resourceID = d.ReadResourceIdentifier(); } base.m_name = d.ReadString(); m_objid = d.ReadString(); base.m_resourceId = d.ReadResourceIdentifier(); base.m_coordinateSystem = d.ReadString(); base.m_extents = new Box2DType(); base.m_extents.Deserialize(d); m_center = d.ReadCoordinates(); m_scale = d.ReadDouble(); m_dataExtent.Deserialize(d); m_displaydpi = d.ReadInt32(); m_display_width = d.ReadInt32(); m_display_height = d.ReadInt32(); base.m_backgroundColor = Utility.ParseHTMLColor(d.ReadString()); m_metersPerUnit = d.ReadDouble(); if (d.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) m_layerRefreshMode = d.ReadInt32(); ArrayList finiteScales = new ArrayList(); int finiteScaleCount = d.ReadInt32(); while(finiteScaleCount-- > 0) finiteScales.Add(d.ReadDouble()); m_finiteScales = (double[])finiteScales.ToArray(typeof(double)); m_changeList = new ArrayList(); if (d.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { m_changeList = DeserializeChangeMap(d); int mapLayerCount = d.ReadInt32(); if (mapLayerCount != 0) throw new Exception("On new versions, there should be no layer data in map"); } else { //ri.LayerGroupBlob = d.ReadStreamRepeat(d.ReadInt32()); DeserializeLayerData(d); m_changeList = DeserializeChangeMap(d); } } internal void DeserializeLayerData(BinarySerializer.MgBinaryDeserializer d) { //if (d.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { int groupCount = d.ReadInt32(); m_mapLayerGroup = new RuntimeMapGroupCollection(); for(int i = 0; i < groupCount; i++) { RuntimeMapGroup g = new RuntimeMapGroup(); g.Deserialize(d); m_mapLayerGroup.Add(g); } } int mapLayerCount = d.ReadInt32(); m_mapLayer = new RuntimeMapLayerCollection(); while (mapLayerCount-- > 0) { RuntimeMapLayer t = new RuntimeMapLayer(); t.Deserialize(d); m_mapLayer.Add(t); } } protected ArrayList DeserializeChangeMap(BinarySerializer.MgBinaryDeserializer d) { int changeListCount = d.ReadInt32(); ArrayList l = new ArrayList(); while(changeListCount-- > 0) { bool isLayer = d.ReadByte() > 0; string objid = d.ReadString(); ChangeList c = new ChangeList(objid, isLayer); int changeCount = d.ReadInt32(); while(changeCount-- > 0) { //Split up to avoid dependency on argument evaluation order int ctype = d.ReadInt32(); c.Changes.Add(new Change((Change.ChangeType)ctype, d.ReadString())); } l.Add(c); } return l; } public string ObjectID { get { return m_objid; } set { m_objid = value; } } public double[] Center { get { return m_center; } set { m_center = value; } } public double Scale { get { return m_scale; } set { m_scale = value; } } public Box2DType DataExtent { get { return m_dataExtent; } set { m_dataExtent = value; } } public int DisplayDPI { get { return m_displaydpi; } set { m_displaydpi = value; } } public int DisplayWidth { get { return m_display_width; } set { m_display_width = value; } } public int DisplayHeight { get { return m_display_height; } set { m_display_height = value; } } public double MetersPerUnit { get { return m_metersPerUnit; } set { m_metersPerUnit = value; } } public int LayerRefreshMode { get { return m_layerRefreshMode; } set { m_layerRefreshMode = value; } } public double[] FiniteScales { get { return m_finiteScales; } set { m_finiteScales = value; } } public ArrayList ChangeList { get { return m_changeList; } set { m_changeList = value; } } public byte[] LayerGroupBlob { get { return m_layersGroupBlob; } set { m_layersGroupBlob = value; } } public ResourceIdentifier ResourceID { get { return m_resourceID; } set { m_resourceID = value; } } /// /// Gets or sets the connection used in various operations performed on this object /// [System.Xml.Serialization.XmlIgnore()] public new ServerConnectionI CurrentConnection { get { return m_serverConnection; } set { m_serverConnection = value; foreach(RuntimeMapLayer layer in this.Layers) layer.SetParent(this); foreach(RuntimeMapGroup group in this.LayerGroups) group.SetParent(this); } } public System.IO.Stream RenderToStream(double x, double y, double scale, int width, int height, int dpi, string format, bool clip) { return m_serverConnection.RenderRuntimeMap(m_resourceID, x, y, scale, width, height, dpi, format, clip); } public System.IO.Stream RenderToStream(double x1, double y1, double x2, double y2, int width, int height, int dpi, string format, bool clip) { return m_serverConnection.RenderRuntimeMap(m_resourceID, x1, y1, x2, y2, width, height, dpi, format, clip); } public System.Drawing.Bitmap Render(double x, double y, double scale, int width, int height, int dpi, string format, bool clip) { using (System.IO.Stream s = m_serverConnection.RenderRuntimeMap(m_resourceID, x, y, scale, width, height, dpi, format, clip)) return new System.Drawing.Bitmap(s); } public System.Drawing.Bitmap Render(double x1, double y1, double x2, double y2, int width, int height, int dpi, string format, bool clip) { using (System.IO.Stream s = m_serverConnection.RenderRuntimeMap(m_resourceID, x1, y1, x2, y2, width, height, dpi, format, clip)) return new System.Drawing.Bitmap(s); } } public class RuntimeMapGroup : BaseMapLayerType { private int m_type; private bool m_visible; private string m_parentGroup; protected string m_objectid; public new RuntimeMap Parent { get { return m_parent; } } internal void SetParent(RuntimeMap parent) { m_parent = parent; } protected new RuntimeMap m_parent = null; public RuntimeMapGroup() : base() { m_type = MgLayerGroupType.Normal; m_objectid = Guid.NewGuid().ToString(); } public RuntimeMapGroup(BaseMapLayerGroupCommonType group) : this() { base.ExpandInLegend = group.ExpandInLegend; base.LegendLabel = group.LegendLabel; base.Name = group.Name; base.ShowInLegend = group.ShowInLegend; m_visible = group.Visible; m_parentGroup = ""; m_objectid = Guid.NewGuid().ToString(); m_type = MgLayerGroupType.BaseMap; } public RuntimeMapGroup(MapLayerGroupType group) : this() { base.ExpandInLegend = group.ExpandInLegend; base.LegendLabel = group.LegendLabel; base.Name = group.Name; base.ShowInLegend = group.ShowInLegend; m_visible = group.Visible; m_parentGroup = group.Group; m_objectid = Guid.NewGuid().ToString(); } internal void Deserialize(BinarySerializer.MgBinaryDeserializer d) { m_parentGroup = d.ReadString(); int objid = d.ReadClassId(); if (d.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { if (objid != 12001) throw new Exception("Group must have object id 12001, but had: " + objid); } else if (objid != 19001) throw new Exception("Group must have object id 19001, but had: " + objid); base.m_name = d.ReadString(); m_objectid = d.ReadString(); m_type = d.ReadInt32(); m_visible = d.ReadBool(); base.m_showInLegend = d.ReadBool(); base.m_expandInLegend = d.ReadBool(); base.m_legendLabel = d.ReadString(); } internal void Serialize(BinarySerializer.MgBinarySerializer s) { s.Write(m_parentGroup); if (s.SiteVersion >= SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) s.WriteClassId(12001); else s.WriteClassId(19001); s.Write(base.m_name); s.Write(m_objectid); s.Write(m_type); s.Write(m_visible); s.Write(base.m_showInLegend); s.Write(base.m_expandInLegend); s.Write(base.m_legendLabel); } public string ParentGroup { get { return m_parentGroup; } set { m_parentGroup = value; } } public int Type { get { return m_type; } set { m_type = value; } } public bool Visible { get { return m_visible; } set { m_visible = value; } } public string ObjectID { get { return m_objectid; } set { m_objectid = value; } } /// /// Gets the full path of the group /// /// The string used to separate the individual levels /// The parent mapdefinition, use null for the current parent /// public string GetFullPath(string separator, RuntimeMap parent) { if (parent == null) parent = m_parent; if (parent == null) throw new Exception("Cannot determine full path on group that is not attached to a map"); if (m_parentGroup == null || m_parentGroup.Length == 0) return m_name; else { RuntimeMapGroup mlg = null; if (parent.LayerGroups != null) foreach(RuntimeMapGroup g in parent.LayerGroups) if (g.Name == m_parentGroup) { mlg = g; break; } if (mlg == null) throw new Exception("Failed to locate group named: " + m_parentGroup); return mlg.GetFullPath(separator, parent) + separator + m_name; } } /// /// Returns a list of layers present in the current group. This method does NOT run in O(n). /// public RuntimeMapLayerCollection Layers { get { if (m_parent == null) return null; string s = this.GetFullPath(ReservedChar.PATH_SEPARATOR, m_parent); RuntimeMapLayerCollection layers = new RuntimeMapLayerCollection(); foreach(RuntimeMapLayer ml in m_parent.Layers) if (ml.GetFullPath(ReservedChar.PATH_SEPARATOR, m_parent).StartsWith(s)) layers.Add(ml); return layers; } } } public class RuntimeMapLayer : MapLayerType { protected double[] m_scaleRanges; protected int m_type; protected List> m_ids; protected bool m_needRefresh; protected double m_displayOrder; protected string m_featureSourceId; protected string m_featureName; protected string m_geometry; protected string m_guid; //V 1.2 Runtime extensions protected bool m_hasTooltips = false; protected string m_schemaName = ""; //V2.2 Runtime extensions protected string m_filter; public new RuntimeMap Parent { get { return m_parent; } } internal void SetParent(RuntimeMap parent) { m_parent = parent; } protected new RuntimeMap m_parent = null; public const double InfinityScale = 1000000000000.0; public RuntimeMapLayer(RuntimeMap parent) : this() { this.m_parent = parent; } public RuntimeMapLayer() : base() { m_scaleRanges = new double[] {0.0, InfinityScale}; m_type = OSGeo.MapGuide.MgLayerType.Dynamic; m_ids = new List>(); m_schemaName = ""; m_featureName = ""; m_featureSourceId = ""; m_geometry = ""; m_guid = System.Guid.NewGuid().ToString(); } public RuntimeMapLayer(OSGeo.MapGuide.MaestroAPI.BaseMapLayerType layer, string group, bool visible) : this() { base.m_resourceId = layer.ResourceId; base.m_expandInLegend = layer.ExpandInLegend; base.m_group = group; base.m_legendLabel = layer.LegendLabel; base.m_name = layer.Name; base.m_selectable = layer.Selectable; base.m_showInLegend = layer.ShowInLegend; base.m_visible = visible; OSGeo.MapGuide.MaestroAPI.LayerDefinition ldef = layer.Parent.CurrentConnection.GetLayerDefinition(layer.ResourceId); if (ldef.Item as OSGeo.MapGuide.MaestroAPI.VectorLayerDefinitionType != null) { OSGeo.MapGuide.MaestroAPI.VectorLayerDefinitionType vld = (OSGeo.MapGuide.MaestroAPI.VectorLayerDefinitionType)ldef.Item; this.m_needRefresh = false; this.m_displayOrder = 0; this.m_featureSourceId = vld.ResourceId; this.m_featureName = vld.FeatureName; this.m_schemaName = vld.FeatureName.IndexOf(":") > 0 ? vld.FeatureName.Substring(0, vld.FeatureName.IndexOf(":")) : ""; this.m_geometry = vld.Geometry; if (vld.VectorScaleRange != null) { m_scaleRanges = new double[vld.VectorScaleRange.Count * 2]; for (int i = 0; i < vld.VectorScaleRange.Count; i++) { m_scaleRanges[i * 2] = vld.VectorScaleRange[i].MinScaleSpecified ? vld.VectorScaleRange[i].MinScale : 0; m_scaleRanges[i * 2 + 1] = vld.VectorScaleRange[i].MaxScaleSpecified ? vld.VectorScaleRange[i].MaxScale : InfinityScale; } } m_hasTooltips = (vld.ToolTip != null && vld.ToolTip.Trim().Length > 0) || (vld.Url != null && vld.Url.Trim().Length > 0); if (base.m_selectable && base.m_visible) try { FindResourceIDs(layer.Parent.CurrentConnection); } catch { } } else if (ldef.Item as OSGeo.MapGuide.MaestroAPI.GridLayerDefinitionType != null) { OSGeo.MapGuide.MaestroAPI.GridLayerDefinitionType gld = (OSGeo.MapGuide.MaestroAPI.GridLayerDefinitionType)ldef.Item; this.m_needRefresh = false; this.m_displayOrder = 0; this.m_featureSourceId = gld.ResourceId; this.m_featureName = gld.FeatureName; this.m_geometry = gld.Geometry; if (gld.GridScaleRange != null) { m_scaleRanges = new double[gld.GridScaleRange.Count * 2]; for (int i = 0; i < gld.GridScaleRange.Count; i++) { m_scaleRanges[i * 2] = gld.GridScaleRange[i].MinScaleSpecified ? gld.GridScaleRange[i].MinScale : 0; m_scaleRanges[i * 2 + 1] = gld.GridScaleRange[i].MaxScaleSpecified ? gld.GridScaleRange[i].MaxScale : InfinityScale; } } } else if (ldef.Item as OSGeo.MapGuide.MaestroAPI.DrawingLayerDefinitionType != null) { OSGeo.MapGuide.MaestroAPI.DrawingLayerDefinitionType dld = (OSGeo.MapGuide.MaestroAPI.DrawingLayerDefinitionType)ldef.Item; this.m_needRefresh = false; this.m_displayOrder = 0; throw new Exception("Drawing layers are not support in runtime map creation"); } else { throw new Exception("Layer " + ldef.ResourceId + " had an invalid or unknown type"); } if (m_ids == null) m_ids = new List>(); } public RuntimeMapLayer(OSGeo.MapGuide.MaestroAPI.MapLayerType layer) : this(layer, layer.Group, layer.Visible) { } /// /// Reads the primary key information from the layers featuresource /// private void FindResourceIDs(ServerConnectionI con) { OSGeo.MapGuide.MaestroAPI.FeatureSource fs = con.GetFeatureSource(m_featureSourceId); //TODO: Should not be hardcoded, but it is the fastest way! if (fs.Provider.StartsWith("OSGeo.Gdal") || fs.Provider.StartsWith("OSGeo.WMS") || fs.Provider.StartsWith("Autodesk.Raster")) { if (m_ids == null) m_ids = new List>(); return; } string[] ids = fs.GetIdentityProperties(m_featureName); OSGeo.MapGuide.MaestroAPI.FeatureSourceDescription.FeatureSourceSchema scm = con.GetFeatureSourceSchema(m_featureSourceId, m_featureName); if (scm != null) { m_ids = new List>(); foreach(string id in ids) foreach(OSGeo.MapGuide.MaestroAPI.FeatureSetColumn fsc in scm.Columns) if (fsc.Name == id) { m_ids.Add(new KeyValuePair (id, fsc.Type)); break; } } } /// /// Reads the primary key information from the layers featuresource /// private void FindResourceIDs() { if (this.Parent == null) throw new Exception("Cannot reload ID's because the layers parent is not set"); FindResourceIDs(this.Parent.CurrentConnection); } internal void Deserialize(BinarySerializer.MgBinaryDeserializer d) { m_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()); m_resourceId = d.ReadResourceIdentifier(); if (d.SiteVersion < SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { m_name = d.ReadString(); m_guid = d.ReadString(); m_type = d.ReadInt32(); m_visible = d.ReadByte() > 0; m_selectable = d.ReadByte() > 0; m_showInLegend = d.ReadByte() > 0; m_expandInLegend = d.ReadByte() > 0; m_legendLabel = d.ReadString(); m_needRefresh = d.ReadByte() > 0; m_displayOrder = d.ReadDouble(); ArrayList scaleRanges = new ArrayList(); int scales = d.ReadInt32(); while(scales-- > 0) scaleRanges.Add(d.ReadDouble()); m_scaleRanges = (double[])scaleRanges.ToArray(typeof(double)); m_featureSourceId = d.ReadString(); m_featureName = d.ReadString(); m_geometry = d.ReadString(); List> ids = new List>(); int idCount = d.ReadInt32(); while(idCount-- > 0) { short idType = d.ReadInt16(); string idName = d.ReadString(); ids.Add(new KeyValuePair(idName, Utility.ConvertMgTypeToNetType(idType))); } m_ids = ids; } else { //AAARGH!!! Now they bypass their own header system .... m_name = d.ReadInternalString(); m_guid = d.ReadInternalString(); m_type = BitConverter.ToInt32(d.ReadStreamRepeat(4), 0); int flags = d.ReadStreamRepeat(1)[0]; m_visible = (flags & 1) > 0; m_selectable = (flags & 2) > 0; m_showInLegend = (flags & 4) > 0; m_expandInLegend = (flags & 8) > 0; m_needRefresh = (flags & 16) > 0; m_hasTooltips = (flags & 32) > 0; m_legendLabel = d.ReadInternalString(); m_displayOrder = BitConverter.ToDouble(d.ReadStreamRepeat(8), 0); ArrayList scaleRanges = new ArrayList(); int scales = BitConverter.ToInt32(d.ReadStreamRepeat(4), 0); while(scales-- > 0) scaleRanges.Add(BitConverter.ToDouble(d.ReadStreamRepeat(8), 0)); m_scaleRanges = (double[])scaleRanges.ToArray(typeof(double)); m_featureSourceId = d.ReadInternalString(); m_featureName = d.ReadInternalString(); if (d.SiteVersion > SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS2_1)) m_filter = d.ReadInternalString(); m_schemaName = d.ReadInternalString(); m_geometry = d.ReadInternalString(); List> 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 KeyValuePair(idName, Utility.ConvertMgTypeToNetType(idType))); } m_ids = ids; } } internal void Serialize(BinarySerializer.MgBinarySerializer s) { s.Write(m_group); if (s.SiteVersion <= SiteVersions.GetVersion(KnownSiteVersions.MapGuideEP1_1)) s.WriteClassId(19003); else s.WriteClassId(30501); s.WriteResourceIdentifier(m_resourceId); if (s.SiteVersion < SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS1_2)) { s.Write(m_name); s.Write(m_guid); s.Write(m_type); s.Write((byte)(m_visible ? 1 : 0)); s.Write((byte)(m_selectable ? 1 : 0)); s.Write((byte)(m_showInLegend ? 1 : 0)); s.Write((byte)(m_expandInLegend ? 1 : 0)); s.Write(m_legendLabel); s.Write((byte)(m_needRefresh ? 1 : 0)); s.Write(m_displayOrder); s.Write(m_scaleRanges.Length); foreach(double d in m_scaleRanges) s.Write(d); s.Write(m_featureSourceId); s.Write(m_featureName); s.Write(m_geometry); s.Write(m_ids.Count); foreach(KeyValuePair x in m_ids) { s.Write((short)Utility.ConvertNetTypeToMgType(x.Value)); s.Write(x.Key); } } else { s.WriteStringInternal(m_name); s.WriteStringInternal(m_guid); s.WriteRaw(BitConverter.GetBytes(m_type)); int flags = 0; flags |= m_visible ? 1 : 0; flags |= m_selectable ? 2 : 0; flags |= m_showInLegend ? 4 : 0; flags |= m_expandInLegend ? 8 : 0; flags |= m_needRefresh ? 16 : 0; flags |= m_hasTooltips ? 32 : 0; s.WriteRaw(new byte[] {(byte)flags}); s.WriteStringInternal(m_legendLabel); s.WriteRaw(BitConverter.GetBytes(m_displayOrder)); s.WriteRaw(BitConverter.GetBytes(m_scaleRanges.Length)); foreach(double d in m_scaleRanges) s.WriteRaw(BitConverter.GetBytes(d)); s.WriteStringInternal(m_featureSourceId); s.WriteStringInternal(m_featureName); if (s.SiteVersion > SiteVersions.GetVersion(KnownSiteVersions.MapGuideOS2_1)) s.WriteStringInternal(m_filter); s.WriteStringInternal(m_schemaName); s.WriteStringInternal(m_geometry); s.WriteRaw(BitConverter.GetBytes(m_ids.Count)); foreach(KeyValuePair x in m_ids) { s.WriteRaw(BitConverter.GetBytes((short)Utility.ConvertNetTypeToMgType(x.Value))); s.WriteStringInternal(x.Key); } } } public double DisplayOrder { get { return m_displayOrder; } set { m_displayOrder = value; } } public bool NeedRefresh { get { return m_needRefresh; } set { m_needRefresh = value; } } public string FeatureSourceID { get { return m_featureSourceId;} set { m_featureSourceId = value; } } public string FeatureName { get { return m_featureName; } set { m_featureName = value; } } public string Filter { get { return m_filter; } set { m_filter = value; } } public string Geometry { get { return m_geometry; } set { m_geometry = value; } } public string Guid { get { return m_guid; } set { m_guid = value; } } public FeatureSetReader Query() { return Query(null, null, null); } public FeatureSetReader Query(string filter) { return Query(filter, null, null); } public FeatureSetReader Query(string filter, string[] columns) { return Query(filter, columns, null); } public FeatureSetReader Query(string filter, string[] columns, System.Collections.Specialized.NameValueCollection computedProperties) { //TODO: This is SLOW, and also breaks the OGR provider :( /* //Merge in the layer filter OSGeo.MapGuide.MaestroAPI.LayerDefinition ldef = m_parent.CurrentConnection.GetLayerDefinition(this.ResourceId); if (ldef.Item.GetType() == typeof(OSGeo.MapGuide.MaestroAPI.VectorLayerDefinitionType)) { string f = ((OSGeo.MapGuide.MaestroAPI.VectorLayerDefinitionType)ldef.Item).Filter; if (f != null && f.Trim().Length != 0) filter = "(" + filter + ") AND (" + f + ")"; } */ return m_parent.CurrentConnection.QueryFeatureSource(this.FeatureSourceID, this.FeatureName, filter, columns, computedProperties); } /// /// Gets the full path of the layer /// /// The string used to separate the individual levels /// The parent mapdefinition, use null for the current parent /// public string GetFullPath(string separator, RuntimeMap parent) { if (parent == null) parent = m_parent; if (parent == null) throw new Exception("Cannot determine full path on group that is not attached to a map"); if (m_group == null || m_group.Length == 0) return m_name; else { RuntimeMapGroup mlg = null; if (parent.LayerGroups != null) foreach(RuntimeMapGroup g in parent.LayerGroups) if (g.Name == m_group) { mlg = g; break; } if (mlg == null) throw new Exception("Failed to locate layer named: " + m_group); return mlg.GetFullPath(separator, parent) + separator + m_name; } } public string SchemaName { get { return m_schemaName; } set { m_schemaName = value; } } public bool HasTooltips { get { return m_hasTooltips; } set { m_hasTooltips = value; } } public override bool Selectable { get { return m_selectable; } set { if (m_visible && value && (m_ids == null || m_ids.Count == 0)) FindResourceIDs(); m_selectable = value; } } public override bool Visible { get { return m_visible; } set { if (m_selectable && value && (m_ids == null || m_ids.Count == 0)) FindResourceIDs(); m_visible = value; } } public double[] Scaleranges { get { return m_scaleRanges; } set { m_scaleRanges = value; } } public int Type { get { return m_type; } set { m_type = value; } } /// /// Returns the list of columns that comprise the primary key for the layer /// public IList> IDs { get { if (m_ids == null || m_ids.Count == 0) FindResourceIDs(); return new System.Collections.ObjectModel.ReadOnlyCollection>(m_ids); } } } public class RuntimeMapLayerCollection : System.Collections.CollectionBase { /// /// Gets or sets the index of a layer, given the layer name. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// /// The name of the layer /// The index of the layer, or -1 if no such layer could be found public int IndexOf(string name) { int rml = -1; for(int i = 0; i < this.Count; i++) if (this[i].Name == name) return i; else if (rml == -1 && this[i].Name.ToLower() == name.ToLower()) rml = i; return rml; } /// /// Gets a value indicating if the layer exists in the map. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// /// The name of the layer /// True if the layer was found, false otherwise public bool Contains(string name) { return IndexOf(name) != -1; } /// /// Gets or sets a layer based on the layers name. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// public RuntimeMapLayer this[string name] { get { int ix = IndexOf(name); if (ix == -1) throw new IndexOutOfRangeException("The layer named: " + name + " was not found in the map"); else return this[ix]; } set { int ix = IndexOf(name); if (ix == -1) throw new IndexOutOfRangeException("The layer named: " + name + " was not found"); else this[ix] = value; } } public RuntimeMapLayer this[int idx] { get { return ((RuntimeMapLayer)(base.InnerList[idx])); } set { base.InnerList[idx] = value; } } public int Add(RuntimeMapLayer value) { return base.InnerList.Add(value); } public void Insert(int index, RuntimeMapLayer layer) { base.InnerList.Insert(index, layer); } public RuntimeClasses.RuntimeMapLayer FindByGuid(string guid) { foreach (RuntimeMapLayer l in base.InnerList) if (l.Guid == guid) return l; return null; } } public class RuntimeMapGroupCollection : System.Collections.CollectionBase { /// /// Gets or sets the index of a layer, given the layer name. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// /// The name of the layer /// The index of the layer, or -1 if no such layer could be found public int IndexOf(string name) { int rml = -1; for(int i = 0; i < this.Count; i++) if (this[i].Name == name) return i; else if (rml == -1 && this[i].Name.ToLower() == name.ToLower()) rml = i; return rml; } /// /// Gets a value indicating if the layer exists in the map. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// /// The name of the layer /// True if the layer was found, false otherwise public bool Contains(string name) { return IndexOf(name) != -1; } /// /// Gets or sets a layer based on the layers name. /// Is case sensitive but will search case insensitive if no layer matches with case sensitive. /// public RuntimeMapGroup this[string name] { get { int ix = IndexOf(name); if (ix == -1) throw new IndexOutOfRangeException("The group named: " + name + " was not found in the map"); else return this[ix]; } set { int ix = IndexOf(name); if (ix == -1) throw new IndexOutOfRangeException("The group named: " + name + " was not found"); else this[ix] = value; } } public RuntimeMapGroup this[int idx] { get { return ((RuntimeMapGroup)(base.InnerList[idx])); } set { base.InnerList[idx] = value; } } public int Add(RuntimeMapGroup value) { return base.InnerList.Add(value); } public void Insert(int index, RuntimeMapGroup layer) { base.InnerList.Insert(index, layer); } } }