2 // mcs/class/System.Data/System.Data/XmlDiffLoader.cs
4 // Purpose: Loads XmlDiffGrams to DataSet
6 // class: XmlDiffLoader
7 // assembly: System.Data.dll
8 // namespace: System.Data
11 // Ville Palo <vi64pa@koti.soon.fi>
12 // Lluis Sanchez Gual (lluis@ximian.com)
14 // (c)copyright 2003 Ville Palo
18 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
20 // Permission is hereby granted, free of charge, to any person obtaining
21 // a copy of this software and associated documentation files (the
22 // "Software"), to deal in the Software without restriction, including
23 // without limitation the rights to use, copy, modify, merge, publish,
24 // distribute, sublicense, and/or sell copies of the Software, and to
25 // permit persons to whom the Software is furnished to do so, subject to
26 // the following conditions:
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 using System.Xml.XPath;
43 using System.Collections;
44 using System.Globalization;
46 namespace System.Data {
48 internal class XmlDiffLoader
53 private DataTable table;
54 private Hashtable DiffGrRows = new Hashtable ();
55 private Hashtable ErrorRows = new Hashtable ();
61 public XmlDiffLoader (DataSet DSet)
66 public XmlDiffLoader (DataTable table)
73 #region Public methods
75 public void Load (XmlReader reader)
77 bool origEnforceConstraint = false;
79 origEnforceConstraint = DSet.EnforceConstraints;
80 DSet.EnforceConstraints = false;
83 reader.MoveToContent ();
84 if (reader.IsEmptyElement) {
89 reader.ReadStartElement ("diffgram", XmlConstants.DiffgrNamespace);
90 reader.MoveToContent ();
92 while (reader.NodeType != XmlNodeType.EndElement)
94 if (reader.NodeType == XmlNodeType.Element)
96 if (reader.LocalName == "before" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
98 else if (reader.LocalName == "errors" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
101 LoadCurrent (reader);
107 reader.ReadEndElement ();
110 DSet.EnforceConstraints = origEnforceConstraint;
113 #endregion // Public methods
115 #region Private methods
117 private void LoadCurrent (XmlReader reader)
119 if (reader.IsEmptyElement) {
123 reader.ReadStartElement (); // Dataset root
124 reader.MoveToContent ();
126 while (reader.NodeType != XmlNodeType.EndElement)
128 if (reader.NodeType == XmlNodeType.Element)
130 DataTable t = GetTable (reader.LocalName);
132 LoadCurrentTable (t, reader);
138 throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));
145 reader.ReadEndElement ();
148 private void LoadBefore (XmlReader reader)
150 if (reader.IsEmptyElement) {
154 reader.ReadStartElement ();
155 reader.MoveToContent ();
157 while (reader.NodeType != XmlNodeType.EndElement)
159 if (reader.NodeType == XmlNodeType.Element)
161 DataTable t = GetTable (reader.LocalName);
163 LoadBeforeTable(t, reader);
165 throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));
171 reader.ReadEndElement ();
175 private void LoadErrors (XmlReader reader)
177 if (reader.IsEmptyElement) {
181 reader.ReadStartElement ();
182 reader.MoveToContent ();
184 while (reader.NodeType != XmlNodeType.EndElement)
186 if (reader.NodeType == XmlNodeType.Element)
190 // find the row in 'current' section
192 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
195 Row = (DataRow) ErrorRows [id];
197 if (reader.IsEmptyElement) continue;
198 reader.ReadStartElement ();
199 while (reader.NodeType != XmlNodeType.EndElement)
201 if (reader.NodeType == XmlNodeType.Element) {
202 string error = reader.GetAttribute ("Error", XmlConstants.DiffgrNamespace);
203 Row.SetColumnError (reader.LocalName, error);
211 reader.ReadEndElement ();
214 private void LoadColumns (DataTable Table, DataRow Row, XmlReader reader, DataRowVersion loadType)
216 if (reader.IsEmptyElement) {
220 reader.ReadStartElement ();
221 reader.MoveToContent ();
223 while (reader.NodeType != XmlNodeType.EndElement)
225 if (reader.NodeType != XmlNodeType.Element) { reader.Read (); continue; }
227 if (Table.Columns.Contains (reader.LocalName))
229 string colName = reader.LocalName;
230 object data = XmlDataLoader.StringToObject (Table.Columns[colName].DataType, reader.ReadString ());
232 if (loadType == DataRowVersion.Current) Row [colName] = data;
233 else Row.SetOriginalValue (colName, data);
238 DataTable t = GetTable (reader.LocalName);
240 if (loadType == DataRowVersion.Original)
241 LoadBeforeTable (t, reader);
242 else if (loadType == DataRowVersion.Current)
243 LoadCurrentTable (t, reader);
248 reader.ReadEndElement ();
251 private void LoadBeforeTable (DataTable Table, XmlReader reader)
253 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
254 string rowOrder = reader.GetAttribute ("rowOrder", XmlConstants.MsdataNamespace);
255 DataRow Row = (DataRow) DiffGrRows [id];
260 Row = Table.NewRow ();
261 LoadColumns (Table, Row, reader, DataRowVersion.Current);
262 Table.Rows.InsertAt (Row, int.Parse (rowOrder));
263 Row.AcceptChanges ();
268 LoadColumns (Table, Row, reader, DataRowVersion.Original);
272 private void LoadCurrentTable (DataTable Table, XmlReader reader)
275 DataRow Row = Table.NewRow ();
277 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
278 string error = reader.GetAttribute ("hasErrors");
279 string changes = reader.GetAttribute ("hasChanges", XmlConstants.DiffgrNamespace);
283 if (string.Compare (changes, "modified", true) == 0) {
284 DiffGrRows.Add (id, Row); // for later use
285 state = DataRowState.Modified;
287 else if (string.Compare (changes, "inserted", true) == 0) {
288 state = DataRowState.Added;
291 throw new InvalidOperationException ("Invalid row change state");
294 state = DataRowState.Unchanged;
296 // If row had errors add row to hashtable for later use
297 if (error != null && string.Compare (error, "true", true) == 0)
298 ErrorRows.Add (id, Row);
300 LoadColumns (Table, Row, reader, DataRowVersion.Current);
301 Table.Rows.Add (Row);
303 if (state != DataRowState.Added)
304 Row.AcceptChanges ();
307 DataTable GetTable (string name)
310 return DSet.Tables [name];
311 else if (name == table.TableName)
318 #endregion // Private methods