2004-03-10 Umadevi S (sumadevi@novell.com)
[mono.git] / mcs / class / System.Data / System.Data / XmlDiffLoader.cs
index 76ed679defd1230bc212d93efebc3529023d3cf4..cef96b7d563d6fd40bd23df5f758c91ac4b109e9 100644 (file)
@@ -9,6 +9,7 @@
 //
 // Author:
 //     Ville Palo <vi64pa@koti.soon.fi>
+//     Lluis Sanchez Gual (lluis@ximian.com)
 //
 // (c)copyright 2003 Ville Palo
 //
@@ -25,8 +26,8 @@ namespace System.Data {
        {
 
                #region Fields
-               enum LoadType {CURRENT, BEFORE, ERROR};
                private DataSet DSet;
+               private DataTable table;
                private Hashtable DiffGrRows = new Hashtable ();
                private Hashtable ErrorRows = new Hashtable ();
 
@@ -39,225 +40,239 @@ namespace System.Data {
                        this.DSet = DSet;
                }
 
+               public XmlDiffLoader (DataTable table) 
+               {
+                       this.table = table;
+               }
+
                #endregion //ctors
 
                #region Public methods
 
-               public void Load (XmlReader Reader) 
+               public void Load (XmlReader reader) 
                {
-
-                       XmlDocument Document = XmlDataLoader.buildXmlDocument(Reader);
+                       bool origEnforceConstraint = false;
+                       if (DSet != null) {
+                               origEnforceConstraint = DSet.EnforceConstraints;
+                               DSet.EnforceConstraints = false;
+                       }
+                       
+                       reader.MoveToContent ();
+                       if (reader.IsEmptyElement) return;
+                       
+                       reader.ReadStartElement ("diffgram", XmlConstants.DiffgrNamespace);
+                       reader.MoveToContent ();
+                       
+                       while (reader.NodeType != XmlNodeType.EndElement)
+                       {
+                               if (reader.NodeType == XmlNodeType.Element)
+                               {
+                                       if (reader.LocalName == "before" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
+                                               LoadBefore (reader);
+                                       else if (reader.LocalName == "errors" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
+                                               LoadErrors (reader);
+                                       else
+                                               LoadCurrent (reader);
+                               }
+                               else
+                                       reader.Skip ();
+                       }
                        
-                       XPathNavigator Navigator = Document.CreateNavigator ();
-                       bool origEnforceConstraint = DSet.EnforceConstraints;
-                       DSet.EnforceConstraints = false;
-                       LoadBefore (Navigator);
-                       LoadCurrent (Navigator);
-                       LoadErrors (Navigator);
-                       DSet.EnforceConstraints = origEnforceConstraint;
+                       reader.ReadEndElement ();
+                       
+                       if (DSet != null)
+                               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 LoadCurrent (XmlReader reader) 
+               {
+                       if (reader.IsEmptyElement) return;
+                       
+                       reader.ReadStartElement ();             // Dataset root
+                       reader.MoveToContent ();
+
+                       while (reader.NodeType != XmlNodeType.EndElement)
+                       {
+                               if (reader.NodeType == XmlNodeType.Element)
+                               {
+                                       DataTable t = GetTable (reader.LocalName);
+                                       if (t != null)
+                                               LoadCurrentTable (t, reader);
+                                       else 
+                                               throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));      
                                }
+                               else
+                                       reader.Skip ();
                        }
+                       
+                       reader.ReadEndElement ();
                }
 
-               private void LoadBefore (XPathNavigator Navigator) 
+               private void LoadBefore (XmlReader reader) 
                {
-                       Navigator.MoveToRoot ();
-
-                       if (!Navigator.MoveToFirstChild ())
-                               return; // FIXME: exception
+                       if (reader.IsEmptyElement) return;
                        
-                       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 ());
+                       reader.ReadStartElement ();
+                       reader.MoveToContent ();
+
+                       while (reader.NodeType != XmlNodeType.EndElement)
+                       {
+                               if (reader.NodeType == XmlNodeType.Element)
+                               {
+                                       DataTable t = GetTable (reader.LocalName);
+                                       if (t != null)
+                                               LoadBeforeTable(t, reader);
+                                       else
+                                               throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));
                                }
+                               else
+                                       reader.Skip ();
                        }
+                       
+                       reader.ReadEndElement ();
                }                                
                                
                                           
-               private void LoadErrors (XPathNavigator Navigator) 
+               private void LoadErrors (XmlReader reader) 
                {
-                       Navigator.MoveToRoot ();
-
-                       if (!Navigator.MoveToFirstChild ())
-                               return; // FIXME: exception
+                       if (reader.IsEmptyElement) return;
                        
-                       if (Navigator.Name != "diffgr:diffgram")
-                               return; // FIXME: exception
-
-                       if (Navigator.MoveToFirstChild ()) {
-                               
-                               while (Navigator.Name != "diffgr:errors") {
-                                       if (!Navigator.MoveToNext ())
-                                               return;
-                               }
-
-                               if (Navigator.MoveToFirstChild ()) {
+                       reader.ReadStartElement ();
+                       reader.MoveToContent ();
 
+                       while (reader.NodeType != XmlNodeType.EndElement)
+                       {
+                               if (reader.NodeType == XmlNodeType.Element)
+                               {
                                        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 ());
+                                       
+                                       string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
+                                       
+                                       if (id != null)
+                                               Row = (DataRow) ErrorRows [id];
+               
+                                       if (reader.IsEmptyElement) continue;
+                                       reader.ReadStartElement ();
+                                       while (reader.NodeType != XmlNodeType.EndElement)
+                                       {
+                                               if (reader.NodeType == XmlNodeType.Element) {
+                                                       string error = reader.GetAttribute ("Error", XmlConstants.DiffgrNamespace);
+                                                       Row.SetColumnError (reader.LocalName, error);
+                                               }
+                                               reader.Read ();
                                        }
                                }
+                               else
+                                       reader.Skip ();
                        }
+                       reader.ReadEndElement ();
                }
 
-               private void LoadColumns (DataTable Table, DataRow Row, XPathNavigator Navigator, bool NewRow, LoadType loadType) 
+               private void LoadColumns (DataTable Table, DataRow Row, XmlReader reader, DataRowVersion 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 (reader.IsEmptyElement) return;
+                       
+                       reader.ReadStartElement ();
+                       reader.MoveToContent ();
+                       
+                       while (reader.NodeType != XmlNodeType.EndElement)
+                       {
+                               if (reader.NodeType != XmlNodeType.Element) { reader.Read (); continue; }
                                
-                               if (NewRow)
-                                       Table.Rows.Add (Row);
+                               if (Table.Columns.Contains (reader.LocalName)) 
+                               {
+                                       string colName = reader.LocalName;
+                                       object data = XmlDataLoader.StringToObject (Table.Columns[colName].DataType, reader.ReadString ());
+                                       
+                                       if (loadType == DataRowVersion.Current) Row [colName] = data;
+                                       else Row.SetOriginalValue (colName, data);
+                                       reader.Read ();
+                               }
+                               else 
+                               {
+                                       DataTable t = GetTable (reader.LocalName);
+                                       if (t != null) {
+                                               if (loadType == DataRowVersion.Original)
+                                                       LoadBeforeTable (t, reader);
+                                               else if (loadType == DataRowVersion.Current)
+                                                       LoadCurrentTable (t, reader);
+                                       }
+                               }
                        }
+                       
+                       reader.ReadEndElement ();
                }
 
-               private void LoadBeforeTable (XPathNavigator Navigator) 
+               private void LoadBeforeTable (DataTable Table, XmlReader reader) 
                {
-                               
-                       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 ();
+                       string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
+                       string rowOrder = reader.GetAttribute ("rowOrder", XmlConstants.MsdataNamespace);
+                       DataRow Row = (DataRow) DiffGrRows [id];
+                       
+                       if (Row == null)
+                       {
+                               // Deleted row
+                               Row = Table.NewRow ();
+                               LoadColumns (Table, Row, reader, DataRowVersion.Current);
+                               Table.Rows.InsertAt (Row, int.Parse (rowOrder));
+                               Row.AcceptChanges ();
+                               Row.Delete ();
+                       }
+                       else
+                       {
+                               LoadColumns (Table, Row, reader, DataRowVersion.Original);
                        }
-                                                                                                               
-                       LoadColumns (Table, Row, Navigator, true, LoadType.BEFORE);
-                       DiffGrRows.Add (id, Row); // for later use
-                       Row.AcceptChanges ();
                }
 
-               private void LoadCurrentTable (XPathNavigator Navigator) 
+               private void LoadCurrentTable (DataTable Table, XmlReader reader) 
                {
-                       
-                       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 ();
-                       }
+                       DataRowState state;
+                       DataRow Row = Table.NewRow ();
 
-                       if (Row == null) {
-                               Row = Table.NewRow ();
-                               NewRow = true;
+                       string id = reader.GetAttribute  ("id", XmlConstants.DiffgrNamespace);
+                       string error = reader.GetAttribute ("hasErrors");
+                       string changes = reader.GetAttribute ("hasChanges", XmlConstants.DiffgrNamespace);
+                       
+                       if (changes != null)
+                       {
+                               if (string.Compare (changes, "modified", true) == 0) {
+                                       DiffGrRows.Add (id, Row); // for later use
+                                       state = DataRowState.Modified;
+                               }
+                               else if (string.Compare (changes, "inserted", true) == 0) {
+                                       state = DataRowState.Added;
+                               }
+                               else
+                                       throw new InvalidOperationException ("Invalid row change state");
                        }
-                                                                                                                               
-                       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
+                       else
+                               state = DataRowState.Unchanged;
+                       
+                       // If row had errors add row to hashtable for later use
+                       if (error != null && string.Compare (error, "true", true) == 0)
                                ErrorRows.Add (id, Row);
                
+                       LoadColumns (Table, Row, reader, DataRowVersion.Current);
+                       Table.Rows.Add (Row);
+                       
+                       if (state != DataRowState.Added)
+                               Row.AcceptChanges ();
+               }
+
+               DataTable GetTable (string name)
+               {
+                       if (DSet != null) 
+                               return DSet.Tables [name];
+                       else if (name == table.TableName) 
+                               return table;
+                       else
+                               return null;
                }