#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.ComponentModel; using System.Drawing; using System.Data; using System.Windows.Forms; using System.Collections.Specialized; using OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC; using OSGeo.MapGuide.MaestroAPI; namespace OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC { /// /// Summary description for FeautreSourceEditorODBC. /// public class FeatureSourceEditorODBC : System.Windows.Forms.UserControl, IResourceEditorControl { /// /// Required designer variable. /// private System.ComponentModel.Container components = null; private EditorInterface m_editor; private OSGeo.MapGuide.MaestroAPI.FeatureSource m_feature; private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox ConnectionType; private System.Windows.Forms.Label label2; private ResourceEditors.FeatureSourceEditors.ODBC.DSN dsn; private ResourceEditors.FeatureSourceEditors.ODBC.Managed managed; private ResourceEditors.FeatureSourceEditors.ODBC.Unmanaged unmanaged; private ResourceEditors.FeatureSourceEditors.ODBC.Wizard wizard; private System.Windows.Forms.Panel CustomPanel; private System.Windows.Forms.TextBox ConnectionString; private ResourceEditors.FeatureSourceEditors.ODBC.Credentials credentials; private System.Windows.Forms.Button RefreshButton; private System.Windows.Forms.Button ConfigureButton; private bool m_isUpdating = false; public delegate void ConnectionStringUpdatedDelegate(string connectionString); private string m_wkt = null; System.Xml.XmlNode m_crsNode = null; /// /// The ODBC provider needs this stuff instead of the coordsys override :(. /// {0} is the name, {1} is the wkt, {2,3} and {4,5} is the bbox coordinates. /// private const string WKT_HEADER = "" + " {0}" + " {0}" + " " + " " + " " + " {2} {3}" + " {4} {5}" + " " + " " + " " + " " + " {0}" + " {1}" + " " + " " + " " + " geographic" + " " + ""; private const string XML_WKT_WRAPPER = "{0}"; private enum DisplayTypes : int { Managed, Unmanaged, DSN, Wizard, Custom } public class GeometryColumn { public string Name; public string XColumn; public string YColumn; public string ZColumn; } public FeatureSourceEditorODBC(EditorInterface editor, OSGeo.MapGuide.MaestroAPI.FeatureSource feature) : this() { m_editor = editor; m_feature = feature; dsn.SetItem(m_editor, m_feature); managed.SetItem(m_editor, m_feature); unmanaged.SetItem(m_editor, m_feature); wizard.SetItem(m_editor, m_feature); credentials.SetItem(m_editor, m_feature); foreach(Control c in CustomPanel.Controls) { c.Visible = false; c.Dock = DockStyle.Fill; } UpdateDisplay(); } public void UpdateDisplay() { try { m_isUpdating = true; dsn.UpdateDisplay(); managed.UpdateDisplay(); unmanaged.UpdateDisplay(); wizard.UpdateDisplay(); credentials.UpdateDisplay(); //This is spaghetti code, yum! if ((m_feature.Parameter["DataSourceName"] == null || m_feature.Parameter["DataSourceName"].Length == 0) && (m_feature.Parameter["ConnectionString"] == null || m_feature.Parameter["ConnectionString"].Length == 0)) ConnectionType.SelectedIndex = (int)DisplayTypes.Managed; else if (m_feature.Parameter["DataSourceName"] != null && m_feature.Parameter["DataSourceName"].Length != 0) ConnectionType.SelectedIndex = (int)DisplayTypes.DSN; else if (m_feature.Parameter["ConnectionString"].IndexOf("%MG_DATA_FILE_PATH%") > 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Managed; else if (m_feature.Parameter["ConnectionString"].IndexOf("%MG_DATA_PATH_ALIAS[") > 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Unmanaged; else { NameValueCollection nv = ConnectionStringManager.SplitConnectionString(m_feature.Parameter["ConnectionString"]); if (nv["Provider"] != null && nv["Provider"].Length != 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Wizard; else { NameValueCollection test = new NameValueCollection(); ConnectionStringManager.InsertDefaultValues(test, nv["Driver"]); if (test.Count > 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Wizard; else if (m_feature.Parameter["DataSourceName"] != null && m_feature.Parameter["DataSourceName"].IndexOf("Dbq=") >= 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Unmanaged; else if (m_feature.Parameter["ConnectionString"] != null && m_feature.Parameter["ConnectionString"].IndexOf("Dbq=") >= 0) ConnectionType.SelectedIndex = (int)DisplayTypes.Unmanaged; else ConnectionType.SelectedIndex = (int)DisplayTypes.Custom; } } if (m_feature.Parameter["ConnectionString"] == null || m_feature.Parameter["ConnectionString"].Length == 0) ConnectionString.Text = ""; else ConnectionString.Text = m_feature.Parameter["ConnectionString"]; m_crsNode = null; m_wkt = null; //The ODBC provider does not support this m_feature.SupplementalSpatialContextInfo = null; if (!string.IsNullOrEmpty(m_feature.ConfigurationDocument)) { try { System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.Load(m_editor.CurrentConnection.GetResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument)); System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(doc.NameTable); nm.AddNamespace("fdo", "http://fdo.osgeo.org/schemas"); nm.AddNamespace("gml", "http://www.opengis.net/gml"); nm.AddNamespace("xlink", "http://www.w3.org/1999/xlink"); m_crsNode = doc.SelectSingleNode("fdo:DataStore/gml:DerivedCRS", nm); if (m_crsNode != null) { System.Xml.XmlNode wktNode = m_crsNode.SelectSingleNode("gml:baseCRS/fdo:WKTCRS/fdo:WKT", nm); if (wktNode != null) m_wkt = wktNode.InnerText; } } catch (Exception ex) { string msg = NestedExceptionMessageProcessor.GetFullMessage(ex); m_editor.SetLastException(ex); MessageBox.Show(this, string.Format(OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Strings.FeatureSourceEditorODBC.CoordinateSystemError, msg), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } if (m_wkt != null) { m_feature.SupplementalSpatialContextInfo = new OSGeo.MapGuide.MaestroAPI.SpatialContextTypeCollection(); MaestroAPI.SpatialContextType cn = new OSGeo.MapGuide.MaestroAPI.SpatialContextType(); cn.CoordinateSystem = m_wkt; cn.Name = "Default"; m_feature.SupplementalSpatialContextInfo.Add(cn); } } finally { m_isUpdating = false; } } private FeatureSourceEditorODBC() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FeatureSourceEditorODBC)); this.label1 = new System.Windows.Forms.Label(); this.ConnectionType = new System.Windows.Forms.ComboBox(); this.CustomPanel = new System.Windows.Forms.Panel(); this.dsn = new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.DSN(); this.managed = new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Managed(); this.unmanaged = new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Unmanaged(); this.wizard = new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Wizard(); this.ConnectionString = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.credentials = new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Credentials(); this.RefreshButton = new System.Windows.Forms.Button(); this.ConfigureButton = new System.Windows.Forms.Button(); this.CustomPanel.SuspendLayout(); this.SuspendLayout(); // // label1 // resources.ApplyResources(this.label1, "label1"); this.label1.Name = "label1"; // // ConnectionType // resources.ApplyResources(this.ConnectionType, "ConnectionType"); this.ConnectionType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.ConnectionType.Items.AddRange(new object[] { resources.GetString("ConnectionType.Items"), resources.GetString("ConnectionType.Items1"), resources.GetString("ConnectionType.Items2"), resources.GetString("ConnectionType.Items3"), resources.GetString("ConnectionType.Items4")}); this.ConnectionType.Name = "ConnectionType"; this.ConnectionType.SelectedIndexChanged += new System.EventHandler(this.ConnectionType_SelectedIndexChanged); // // CustomPanel // resources.ApplyResources(this.CustomPanel, "CustomPanel"); this.CustomPanel.Controls.Add(this.dsn); this.CustomPanel.Controls.Add(this.managed); this.CustomPanel.Controls.Add(this.unmanaged); this.CustomPanel.Controls.Add(this.wizard); this.CustomPanel.Name = "CustomPanel"; // // dsn // resources.ApplyResources(this.dsn, "dsn"); this.dsn.Name = "dsn"; this.dsn.ConnectionStringUpdated += new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.FeatureSourceEditorODBC.ConnectionStringUpdatedDelegate(this.ConnectionStringUpdated); // // managed // resources.ApplyResources(this.managed, "managed"); this.managed.Name = "managed"; this.managed.ConnectionStringUpdated += new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.FeatureSourceEditorODBC.ConnectionStringUpdatedDelegate(this.ConnectionStringUpdated); // // unmanaged // resources.ApplyResources(this.unmanaged, "unmanaged"); this.unmanaged.Name = "unmanaged"; this.unmanaged.ConnectionStringUpdated += new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.FeatureSourceEditorODBC.ConnectionStringUpdatedDelegate(this.ConnectionStringUpdated); // // wizard // resources.ApplyResources(this.wizard, "wizard"); this.wizard.Name = "wizard"; this.wizard.ConnectionStringUpdated += new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.FeatureSourceEditorODBC.ConnectionStringUpdatedDelegate(this.ConnectionStringUpdated); // // ConnectionString // resources.ApplyResources(this.ConnectionString, "ConnectionString"); this.ConnectionString.Name = "ConnectionString"; this.ConnectionString.TextChanged += new System.EventHandler(this.ConnectionString_TextChanged); // // label2 // resources.ApplyResources(this.label2, "label2"); this.label2.Name = "label2"; // // credentials // resources.ApplyResources(this.credentials, "credentials"); this.credentials.Name = "credentials"; this.credentials.ConnectionStringUpdated += new OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.FeatureSourceEditorODBC.ConnectionStringUpdatedDelegate(this.ConnectionStringUpdated); // // RefreshButton // resources.ApplyResources(this.RefreshButton, "RefreshButton"); this.RefreshButton.Name = "RefreshButton"; this.RefreshButton.Click += new System.EventHandler(this.RefreshButton_Click); // // ConfigureButton // resources.ApplyResources(this.ConfigureButton, "ConfigureButton"); this.ConfigureButton.Name = "ConfigureButton"; this.ConfigureButton.Click += new System.EventHandler(this.ConfigureButton_Click); // // FeatureSourceEditorODBC // resources.ApplyResources(this, "$this"); this.Controls.Add(this.ConfigureButton); this.Controls.Add(this.RefreshButton); this.Controls.Add(this.credentials); this.Controls.Add(this.label2); this.Controls.Add(this.ConnectionString); this.Controls.Add(this.CustomPanel); this.Controls.Add(this.ConnectionType); this.Controls.Add(this.label1); this.Name = "FeatureSourceEditorODBC"; this.CustomPanel.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); } #endregion public object Resource { get { return m_feature; } set { m_feature = (OSGeo.MapGuide.MaestroAPI.FeatureSource)value; dsn.SetItem(m_editor, m_feature); managed.SetItem(m_editor, m_feature); unmanaged.SetItem(m_editor, m_feature); wizard.SetItem(m_editor, m_feature); credentials.SetItem(m_editor, m_feature); UpdateDisplay(); } } public string ResourceId { get { return m_feature.ResourceId; } set { m_feature.ResourceId = value; } } public bool Preview() { return false; } public bool Save(string savename) { if (m_feature.SupplementalSpatialContextInfo == null || m_feature.SupplementalSpatialContextInfo.Count == 0) { //Remove the CRSnode UpdateConfigWithCoordsys(null); } else { string wkt = m_feature.SupplementalSpatialContextInfo[0].CoordinateSystem; //m_feature.SupplementalSpatialContextInfo = null; string name = m_editor.CurrentConnection.CoordinateSystemCatalog.ConvertWktToCoordinateSystemCode(wkt); if (wkt != m_wkt) //TODO: Figure out how to get the coordsys extent UpdateConfigWithCoordsys(string.Format(System.Globalization.CultureInfo.InvariantCulture, WKT_HEADER, name, wkt, 0.0, 0.0, 0.0, 0.0)); } return false; } private void UpdateConfigWithCoordsys(string coordsysFragment) { if (!string.IsNullOrEmpty(m_feature.ConfigurationDocument)) { try { System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); doc.Load(m_editor.CurrentConnection.GetResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument)); System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(doc.NameTable); nm.AddNamespace("fdo", "http://fdo.osgeo.org/schemas"); nm.AddNamespace("gml", "http://www.opengis.net/gml"); nm.AddNamespace("xlink", "http://www.w3.org/1999/xlink"); System.Xml.XmlNode root = doc.SelectSingleNode("fdo:DataStore", nm); System.Xml.XmlNode crsNode = root.SelectSingleNode("gml:DerivedCRS", nm); if (crsNode != null) root.RemoveChild(crsNode); if (!string.IsNullOrEmpty(coordsysFragment)) { string tmpXml = string.Format(XML_WKT_WRAPPER, coordsysFragment); System.Xml.XmlDocument d2 = new System.Xml.XmlDocument(); d2.LoadXml(tmpXml); root.InsertBefore(doc.ImportNode(d2.FirstChild.FirstChild, true), root.FirstChild); } using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { doc.Save(ms); m_editor.CurrentConnection.SetResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument, OSGeo.MapGuide.MaestroAPI.ResourceDataType.Stream, ms); } } catch (Exception ex) { string msg = NestedExceptionMessageProcessor.GetFullMessage(ex); m_editor.SetLastException(ex); MessageBox.Show(this, string.Format(OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Strings.FeatureSourceEditorODBC.CoordinateSystemError, msg), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void ConnectionStringUpdated(string connectionString) { try { m_isUpdating = true; ConnectionString.Text = connectionString; m_editor.HasChanged(); } finally { m_isUpdating = false; } } private void ConnectionType_SelectedIndexChanged(object sender, System.EventArgs e) { Control sel = null; switch((DisplayTypes)ConnectionType.SelectedIndex) { case DisplayTypes.Managed: sel = managed; break; case DisplayTypes.Unmanaged: sel = unmanaged; break; case DisplayTypes.DSN: sel = dsn; break; case DisplayTypes.Wizard: sel = wizard; break; case DisplayTypes.Custom: break; } foreach(Control c in CustomPanel.Controls) c.Visible = c == sel; } private void ConnectionString_TextChanged(object sender, System.EventArgs e) { if (m_feature == null || m_isUpdating) return; m_feature.Parameter["ConnectionString"] = ConnectionString.Text; m_feature.Parameter["Datasource"] = ""; m_editor.HasChanged(); } private void RefreshButton_Click(object sender, System.EventArgs e) { if (m_feature == null || m_isUpdating) return; try { Hashtable geometry = new Hashtable(); Hashtable keys = new Hashtable(); //This is always a temp resource, so it is safe to update it if (m_feature.ConfigurationDocument != null && m_feature.ConfigurationDocument.Length != 0) { try { System.Xml.XmlDocument prev = new System.Xml.XmlDocument(); prev.Load(m_editor.CurrentConnection.GetResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument)); geometry = GeometryColumns(prev); keys = KeyColumns(prev); } catch { } try { m_editor.CurrentConnection.DeleteResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument); } catch { } } m_feature.ConfigurationDocument = null; m_editor.CurrentConnection.SaveResource(m_feature); UpdateConfigDocument(GetCleanConfig(geometry, keys)); } catch (Exception ex) { string msg = NestedExceptionMessageProcessor.GetFullMessage(ex); m_editor.SetLastException(ex); MessageBox.Show(this, string.Format(OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Strings.FeatureSourceEditorODBC.SchemaRefreshError, msg), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void UpdateConfigDocument(System.Xml.XmlDocument config) { using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { OSGeo.MapGuide.MaestroAPI.Utf8XmlWriter wr = new OSGeo.MapGuide.MaestroAPI.Utf8XmlWriter(ms); config.Save(wr); System.IO.MemoryStream ms2 = OSGeo.MapGuide.MaestroAPI.Utility.RemoveUTF8BOM(ms); m_editor.CurrentConnection.SetResourceData(m_feature.ResourceId, "config", OSGeo.MapGuide.MaestroAPI.ResourceDataType.Stream, ms2); if (ms2 != ms) (ms2 as IDisposable).Dispose(); } m_feature.ConfigurationDocument = "config"; m_editor.CurrentConnection.SaveResource(m_feature); m_editor.HasChanged(); } public Hashtable KeyColumns(System.Xml.XmlDocument doc) { Hashtable results = new Hashtable(); if (doc["fdo:DataStore"] != null && doc["fdo:DataStore"]["xs:schema"] != null ) foreach(System.Xml.XmlNode n in doc["fdo:DataStore"]["xs:schema"].ChildNodes) if (n.Name == "xs:element" && n.Attributes["name"] != null && n.FirstChild != null && n.FirstChild.Name == "xs:key") foreach(System.Xml.XmlNode nx in n.FirstChild.ChildNodes) if (nx.Name == "xs:field" && nx.Attributes["xpath"] != null) { results[n.Attributes["name"].Value] = nx.Attributes["xpath"].Value; break; } return results; } public Hashtable GeometryColumns(System.Xml.XmlDocument doc) { Hashtable results = new Hashtable(); if (doc["fdo:DataStore"] != null && doc["fdo:DataStore"]["SchemaMapping"] != null) foreach(System.Xml.XmlNode n in doc["fdo:DataStore"]["SchemaMapping"].ChildNodes) if (n.Name == "complexType" && n["Table"] != null && n["Table"].Attributes["name"] != null) { string tablename = n["Table"].Attributes["name"].Value; foreach(System.Xml.XmlNode c in n.ChildNodes) if (c.Name == "element" && c.Attributes["name"] != null && c.Attributes["xColumnName"] != null && c.Attributes["yColumnName"] != null) { GeometryColumn gc = new GeometryColumn(); gc.XColumn = c.Attributes["xColumnName"].Value; gc.YColumn = c.Attributes["yColumnName"].Value; if (c.Attributes["zColumnName"] != null) gc.ZColumn = c.Attributes["zColumnName"].Value; gc.Name = c.Attributes["name"].Value; if (!results.ContainsKey(tablename)) results.Add(tablename, new ArrayList()); results[tablename] = gc; } } return results; } private System.Xml.XmlDocument GetCleanConfig(Hashtable geometryColumns, Hashtable keyColumns) { System.IO.MemoryStream scm_ms = new System.IO.MemoryStream(); string backSet = m_feature.ConfigurationDocument; try { m_feature.ConfigurationDocument = null; m_editor.CurrentConnection.SaveResource(m_feature); //This is used to read the schema in raw xml NameValueCollection param = new NameValueCollection(); param.Add("OPERATION", "DESCRIBEFEATURESCHEMA"); param.Add("VERSION", "1.0.0"); param.Add("SESSION", m_editor.CurrentConnection.SessionID); param.Add("FORMAT", "text/xml"); param.Add("RESOURCEID", m_feature.ResourceId); OSGeo.MapGuide.MaestroAPI.Utility.CopyStream(((OSGeo.MapGuide.MaestroAPI.HttpServerConnection)m_editor.CurrentConnection).ExecuteOperation(param), scm_ms); } finally { m_feature.ConfigurationDocument = backSet; m_editor.CurrentConnection.SaveResource(m_feature); } System.Xml.XmlDocument schema = new System.Xml.XmlDocument(); scm_ms.Position = 0; schema.Load(scm_ms); if (schema.FirstChild.NodeType == System.Xml.XmlNodeType.XmlDeclaration) schema.RemoveChild(schema.FirstChild); if (schema.FirstChild.Attributes["targetNamespace"] == null) schema.FirstChild.Attributes.Append(schema.CreateAttribute("targetNamespace")); schema.FirstChild.Attributes["targetNamespace"].Value = "http://fdo.osgeo.org/schemas/feature/Default"; if (schema.FirstChild.Attributes["xmlns:Default"] == null) schema.FirstChild.Attributes.Append(schema.CreateAttribute("xmlns:Default")); schema.FirstChild.Attributes["xmlns:Default"].Value = "http://fdo.osgeo.org/schemas/feature/Default"; //Preserve the crs, if any if (m_crsNode != null) schema.FirstChild.AppendChild(schema.ImportNode(m_crsNode, true)); Hashtable approvedKeys = new Hashtable(); foreach(System.Xml.XmlNode n in schema.FirstChild.ChildNodes) if (n.Name == "xs:element" && n.Attributes["name"] != null && n.Attributes["type"] != null) n.Attributes["type"].Value = "Default:" + n.Attributes["name"].Value + "Type"; else if (n.Name == "xs:complexType" && n.Attributes["name"] != null && n.Attributes["name"].Value.EndsWith("Type")) { string tablename = n.Attributes["name"].Value.Substring(0, n.Attributes["name"].Value.Length - "Type".Length); if (geometryColumns.ContainsKey(tablename)) { n.Attributes.Append(n.OwnerDocument.CreateAttribute("fdo:hasGeometry")).Value = "true"; n.Attributes.Append(n.OwnerDocument.CreateAttribute("fdo:geometryName")).Value = ((GeometryColumn)geometryColumns[tablename]).Name; if (n.FirstChild != null && n.FirstChild.FirstChild != null & n.FirstChild.FirstChild.FirstChild != null) { //Extend the class type if needed if (n.FirstChild.Name == "xs:sequence") { string tmp = "" + n.InnerXml + ""; n.InnerXml = tmp; } System.Xml.XmlNode bas = n.FirstChild.FirstChild; if (bas.Name == "xs:extension" && bas.Attributes["base"] != null) bas.Attributes["base"].Value = "gml:AbstractFeatureType"; System.Xml.XmlNode seq = n.FirstChild.FirstChild.FirstChild; if (seq.Name == "xs:sequence") { System.Xml.XmlNode g = seq.AppendChild(seq.OwnerDocument.CreateElement("xs:element", "http://www.w3.org/2001/XMLSchema")); g.Attributes.Append(g.OwnerDocument.CreateAttribute("name")).Value = ((GeometryColumn)geometryColumns[tablename]).Name; g.Attributes.Append(g.OwnerDocument.CreateAttribute("type")).Value = "gml:AbstractGeometryType"; g.Attributes.Append(g.OwnerDocument.CreateAttribute("fdo:hasMeasure")).Value = "false"; g.Attributes.Append(g.OwnerDocument.CreateAttribute("fdo:hasElevation")).Value = "false"; //g.Attributes.Append(g.OwnerDocument.CreateAttribute("fdo:srsName")).Value = ""; g.Attributes.Append(g.OwnerDocument.CreateAttribute("fdo:geometricTypes")).Value = "point"; g.Attributes.Append(g.OwnerDocument.CreateAttribute("fdo:geometryTypes")).Value = "point multipoint"; } } } else n.Attributes.Append(n.OwnerDocument.CreateAttribute("fdo:hasGeometry")).Value = "false"; if (keyColumns.ContainsKey(tablename)) if (n.FirstChild != null && n.FirstChild.FirstChild != null & n.FirstChild.FirstChild.FirstChild != null) { //Extend the class type if needed if (n.FirstChild.Name == "xs:sequence") { string tmp = "" + n.InnerXml + ""; n.InnerXml = tmp; } string colName = (string)keyColumns[tablename]; System.Xml.XmlNode seq = n.FirstChild.FirstChild.FirstChild; if (seq.Name == "xs:sequence") foreach(System.Xml.XmlNode nx in seq.ChildNodes) if (nx.Name == "xs:element" && nx.Attributes["name"] != null && nx.Attributes["name"].Value == colName) { approvedKeys[tablename] = colName; break; } } } keyColumns = approvedKeys; Hashtable keySelectors = new Hashtable(); foreach (string s in keyColumns.Keys) keySelectors.Add(s, null); //Find tables with existing keys foreach (System.Xml.XmlNode n in schema.FirstChild.ChildNodes) if (n.Name == "xs:element" && n.Attributes["name"] != null && n.Attributes["type"] != null && keyColumns.ContainsKey(n.Attributes["name"].Value)) keySelectors[n.Attributes["name"].Value] = n; //Create selectors for non-existing keys foreach(string s in keySelectors.Keys) if (keySelectors[s] == null) { System.Xml.XmlNode selector = schema.FirstChild.AppendChild(schema.CreateElement("xs:element", "http://www.w3.org/2001/XMLSchema")); selector.Attributes.Append(selector.OwnerDocument.CreateAttribute("name")).Value = s; selector.Attributes.Append(selector.OwnerDocument.CreateAttribute("type")).Value = "Default:" + s + "Type"; selector.Attributes.Append(selector.OwnerDocument.CreateAttribute("abstract")).Value = "false"; selector.Attributes.Append(selector.OwnerDocument.CreateAttribute("substitutionGroup")).Value = "gml:_Feature"; System.Xml.XmlNode key = selector.AppendChild(selector.OwnerDocument.CreateElement("xs:key", "http://www.w3.org/2001/XMLSchema")); key.Attributes.Append(key.OwnerDocument.CreateAttribute("name")).Value = s + "Key"; System.Xml.XmlNode sl = key.AppendChild(selector.OwnerDocument.CreateElement("xs:selector", "http://www.w3.org/2001/XMLSchema")); sl.Attributes.Append(sl.OwnerDocument.CreateAttribute("xpath")).Value = ".//" + s; System.Xml.XmlNode f = key.AppendChild(selector.OwnerDocument.CreateElement("xs:field", "http://www.w3.org/2001/XMLSchema")); f.Attributes.Append(f.OwnerDocument.CreateAttribute("xpath")).Value = (string)keyColumns[s]; } foreach(System.Xml.XmlNode n in schema.FirstChild.ChildNodes) if (n.Name == "xs:element" && n.Attributes["name"] != null && keyColumns.ContainsKey(n.Attributes["name"].Value)) { ArrayList toRemove = new ArrayList(); if (n.FirstChild != null && n.FirstChild.Name == "xs:key") foreach(System.Xml.XmlNode nx in n.FirstChild.ChildNodes) if (nx.Name == "xs:field" && nx.Attributes["xpath"] != null) toRemove.Add(nx); foreach(System.Xml.XmlNode nx in toRemove) nx.ParentNode.RemoveChild(nx); System.Xml.XmlNode f = n.FirstChild.AppendChild(n.OwnerDocument.CreateElement("xs:field", "http://www.w3.org/2001/XMLSchema")); f.Attributes.Append(f.OwnerDocument.CreateAttribute("xpath")).Value = (string)keyColumns[n.Attributes["name"].Value]; } scm_ms.Position = 0; OSGeo.MapGuide.MaestroAPI.FeatureSourceDescription fsd = new OSGeo.MapGuide.MaestroAPI.FeatureSourceDescription(scm_ms); //Using a temp document to avoid all that namespace clutter that .Net uses System.Xml.XmlDocument temp = new System.Xml.XmlDocument(); temp.LoadXml(""); foreach(OSGeo.MapGuide.MaestroAPI.FeatureSourceDescription.FeatureSourceSchema scm in fsd.Schemas) { System.Xml.XmlNode type = temp.FirstChild.AppendChild(temp.CreateElement("complexType")); type.Attributes.Append(temp.CreateAttribute("name")).Value = scm.Name + "Type"; type.AppendChild(temp.CreateElement("Table")).Attributes.Append(temp.CreateAttribute("name")).Value = scm.Name; foreach(OSGeo.MapGuide.MaestroAPI.FeatureSetColumn fsc in scm.Columns) { System.Xml.XmlNode elm = type.AppendChild(temp.CreateElement("element")); elm.Attributes.Append(temp.CreateAttribute("name")).Value = fsc.Name; elm.AppendChild(temp.CreateElement("Column")).Attributes.Append(temp.CreateAttribute("name")).Value = fsc.Name; } if (geometryColumns.ContainsKey(scm.Name)) { GeometryColumn gc = (GeometryColumn)geometryColumns[scm.Name]; System.Xml.XmlNode elm = type.AppendChild(temp.CreateElement("element")); elm.Attributes.Append(temp.CreateAttribute("name")).Value = gc.Name; elm.Attributes.Append(temp.CreateAttribute("xColumnName")).Value = gc.XColumn; elm.Attributes.Append(temp.CreateAttribute("yColumnName")).Value = gc.YColumn; if(gc.ZColumn != null) elm.Attributes.Append(temp.CreateAttribute("zColumnName")).Value = gc.ZColumn; } } System.Xml.XmlDocument mapping = new System.Xml.XmlDocument(); string mappingRoot = ""; mappingRoot += temp.FirstChild.InnerXml; mappingRoot += ""; mapping.LoadXml(mappingRoot); System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(mapping.NameTable); nm.AddNamespace("xmlns:rdb", "http://fdordbms.osgeo.org/schemas"); nm.AddNamespace("", "http://fdoodbc.osgeo.org/schemas"); OSGeo.MapGuide.MaestroAPI.FeatureProviderRegistryFeatureProvider fpr = m_editor.CurrentConnection.GetFeatureProvider(m_feature.Provider); mapping.FirstChild.Attributes["provider"].Value = fpr.Name; System.Xml.XmlDocument config = new System.Xml.XmlDocument(); /*System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(config.NameTable); nm.AddNamespace("xmlns:xs", "http://www.w3.org/2001/XMLSchema"); nm.AddNamespace("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); nm.AddNamespace("xmlns:xlink", "http://www.w3.org/1999/xlink"); nm.AddNamespace("xmlns:gml", "http://www.opengis.net/gml"); nm.AddNamespace("xmlns:fdo", "http://fdo.osgeo.org/schemas"); nm.AddNamespace("xmlns:fds", "http://fdo.osgeo.org/schemas/fds");*/ string fdoRoot = ""; fdoRoot += schema.FirstChild.OuterXml; fdoRoot += mapping.InnerXml; fdoRoot += ""; config.LoadXml(fdoRoot); return config; } private void ConfigureButton_Click(object sender, System.EventArgs e) { GeometryColumnsEditor dlg = new GeometryColumnsEditor(); Hashtable geometry = new Hashtable(); Hashtable keys = new Hashtable(); //Make sure there is no autogeneration, as that hides the properties m_feature.Parameter["GenerateDefaultGeometryProperty"] = "false"; if (m_feature.ConfigurationDocument != null && m_feature.ConfigurationDocument.Length != 0) { try { System.Xml.XmlDocument prev = new System.Xml.XmlDocument(); prev.Load(m_editor.CurrentConnection.GetResourceData(m_feature.ResourceId, m_feature.ConfigurationDocument)); geometry = GeometryColumns(prev); keys = KeyColumns(prev); } catch(Exception ex) { string msg = NestedExceptionMessageProcessor.GetFullMessage(ex); m_editor.SetLastException(ex); MessageBox.Show(this, string.Format(OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Strings.FeatureSourceEditorODBC.ConfigurationReadError, msg), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } OSGeo.MapGuide.MaestroAPI.FeatureSourceDescription fsd = null; try { string backSet = m_feature.ConfigurationDocument; try { m_feature.ConfigurationDocument = null; m_editor.CurrentConnection.SaveResource(m_feature); fsd = m_editor.CurrentConnection.DescribeFeatureSource(m_feature.ResourceId); } finally { m_feature.ConfigurationDocument = backSet; m_editor.CurrentConnection.SaveResource(m_feature); } } catch(Exception ex) { string msg = NestedExceptionMessageProcessor.GetFullMessage(ex); m_editor.SetLastException(ex); MessageBox.Show(this, string.Format(OSGeo.MapGuide.Maestro.ResourceEditors.FeatureSourceEditors.ODBC.Strings.FeatureSourceEditorODBC.DatasourceLayoutReadError, msg), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } dlg.Setup(fsd, geometry, keys); if (dlg.ShowDialog(this) == DialogResult.OK) { UpdateConfigDocument(GetCleanConfig(dlg.GeometryColumns, dlg.KeyColumns)); } } public bool Profile() { return true; } public bool ValidateResource(bool recurse) { //Save as temp before validating, to include projection data Save(null); return true; } public bool SupportsPreview { get { return m_editor.CurrentConnection.SupportsResourcePreviews; } } public bool SupportsValidate { get { return true; } } public bool SupportsProfiling { get { return false; } } } }