// // mcs/class/System.Data/System.Data/XmlDiffLoader.cs // // Purpose: Loads XmlDiffGrams to DataSet // // class: XmlDiffLoader // assembly: System.Data.dll // namespace: System.Data // // Author: // Ville Palo // // (c)copyright 2003 Ville Palo // using System; using System.Data; using System.Xml; using System.Xml.XPath; using System.Collections; using System.Globalization; namespace System.Data { internal class XmlDiffLoader { #region Fields enum LoadType {CURRENT, BEFORE, ERROR}; private DataSet DSet; private Hashtable DiffGrRows = new Hashtable (); private Hashtable ErrorRows = new Hashtable (); #endregion // Fields #region ctors public XmlDiffLoader (DataSet DSet) { this.DSet = DSet; } #endregion //ctors #region Public methods public void Load (XmlReader Reader) { XmlDocument Document = BuildXmlDocument(Reader); XPathNavigator Navigator = Document.CreateNavigator (); bool origEnforceConstraint = DSet.EnforceConstraints; DSet.EnforceConstraints = false; LoadBefore (Navigator); LoadCurrent (Navigator); LoadErrors (Navigator); DSet.EnforceConstraints = origEnforceConstraint; } #endregion // Public methods #region Private methods private void LoadCurrent (XPathNavigator Navigator) { Navigator.MoveToRoot (); if (Navigator.MoveToFirstChild ()) { if (Navigator.Name == "diffgr:diffgram") { if (Navigator.MoveToFirstChild ()) { if (Navigator.MoveToFirstChild ()) { do { if (DSet.Tables.Contains (Navigator.LocalName)) LoadCurrentTable(Navigator); else throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + Navigator.LocalName + "' is missing in the destination dataset")); }while (Navigator.MoveToNext()); } } } } } private void LoadBefore (XPathNavigator Navigator) { Navigator.MoveToRoot (); if (!Navigator.MoveToFirstChild ()) return; // FIXME: exception if (Navigator.Name != "diffgr:diffgram") return; // FIXME: exception if (Navigator.MoveToFirstChild ()) { while (Navigator.Name != "diffgr:before") { if (!Navigator.MoveToNext ()) // there is no before return; } if (Navigator.MoveToFirstChild ()) { do { if (DSet.Tables.Contains (Navigator.LocalName)) LoadBeforeTable(Navigator); else throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + Navigator.LocalName + "' is missing in the destination dataset")); } while (Navigator.MoveToNext ()); } } } private void LoadErrors (XPathNavigator Navigator) { Navigator.MoveToRoot (); if (!Navigator.MoveToFirstChild ()) return; // FIXME: exception if (Navigator.Name != "diffgr:diffgram") return; // FIXME: exception if (Navigator.MoveToFirstChild ()) { while (Navigator.Name != "diffgr:errors") { if (!Navigator.MoveToNext ()) return; } if (Navigator.MoveToFirstChild ()) { DataRow Row = null; // find the row in 'current' section if (Navigator.MoveToFirstAttribute ()) { do { if (Navigator.Name == "diffgr:id") { if (ErrorRows.Contains (Navigator.Value)) Row = (DataRow)ErrorRows [Navigator.Value]; } } while (Navigator.MoveToNextAttribute ()); Navigator.MoveToParent (); } if (Navigator.MoveToFirstChild ()) { string Error = ""; do { if (Navigator.MoveToFirstAttribute ()) { do { if (Navigator.Name == "diffgr:Error") Error = Navigator.Value; } while (Navigator.MoveToNextAttribute ()); Navigator.MoveToParent (); } Row.SetColumnError (Navigator.LocalName, Error); } while (Navigator.MoveToNext ()); } } } } private void LoadColumns (DataTable Table, DataRow Row, XPathNavigator Navigator, bool NewRow, LoadType loadType) { if (Navigator.MoveToFirstChild ()) { do { if (Table.Columns.Contains (Navigator.LocalName)) Row [Navigator.LocalName] = Navigator.Value; else if (DSet.Tables.Contains (Navigator.LocalName)){ if (loadType == LoadType.BEFORE) LoadBeforeTable(Navigator); else if (loadType == LoadType.CURRENT) LoadCurrentTable(Navigator); } } while (Navigator.MoveToNext ()); if (NewRow) Table.Rows.Add (Row); } } private void LoadBeforeTable (XPathNavigator Navigator) { String id = null; DataTable Table = DSet.Tables [Navigator.LocalName]; DataRow Row = Table.NewRow (); if (Navigator.MoveToFirstAttribute ()) { do { if (Navigator.Name == "diffgr:id") id = Navigator.Value; } while (Navigator.MoveToNextAttribute ()); Navigator.MoveToParent (); } LoadColumns (Table, Row, Navigator, true, LoadType.BEFORE); DiffGrRows.Add (id, Row); // for later use Row.AcceptChanges (); } private void LoadCurrentTable (XPathNavigator Navigator) { DataTable Table = DSet.Tables [Navigator.LocalName]; DataRow Row = null; bool NewRow = false; bool HasErrors = false; string id = ""; if (Navigator.MoveToFirstAttribute ()) { do { // Find out was there same row in 'before' section if (Navigator.LocalName == "id") { id = Navigator.Value; if (DiffGrRows.Contains (id)) Row = (DataRow)DiffGrRows [id]; } else if (Navigator.LocalName == "hasErrors" && String.Compare (Navigator.Value, "true", true) == 0) HasErrors = true; } while (Navigator.MoveToNextAttribute ()); // back to business Navigator.MoveToParent (); } if (Row == null) { Row = Table.NewRow (); NewRow = true; } LoadColumns (Table, Row, Navigator, NewRow, LoadType.CURRENT); // back to business Navigator.MoveToParent(); if (HasErrors) // If row had errors add row to hashtable for later use ErrorRows.Add (id, Row); } private static XmlDocument BuildXmlDocument(XmlReader reader) { string endinglocalName = reader.LocalName; XmlDocument doc = new XmlDocument(); // create all contents with use of ReadNode() do { XmlNode n = doc.ReadNode (reader); if(n == null) break; doc.AppendChild (n); } while (reader.LocalName == endinglocalName); return doc; } #endregion // Private methods } }