DataSet.cs : Adding support for WriteXml with diffgram. Code style changes.
[mono.git] / mcs / class / System.Data / System.Data / XmlDiffLoader.cs
1 //
2 // mcs/class/System.Data/System.Data/XmlDiffLoader.cs
3 //
4 // Purpose: Loads XmlDiffGrams to DataSet 
5 //
6 // class: XmlDiffLoader
7 // assembly: System.Data.dll
8 // namespace: System.Data
9 //
10 // Author:
11 //     Ville Palo <vi64pa@koti.soon.fi>
12 //
13 // (c)copyright 2003 Ville Palo
14 //
15 using System;
16 using System.Data;
17 using System.Xml;
18 using System.Xml.XPath;
19 using System.Collections;
20 using System.Globalization;
21
22 namespace System.Data {
23
24         internal class XmlDiffLoader 
25         {
26
27                 #region Fields
28                 enum LoadType {CURRENT, BEFORE, ERROR};
29                 private DataSet DSet;
30                 private Hashtable DiffGrRows = new Hashtable ();
31                 private Hashtable ErrorRows = new Hashtable ();
32
33                 #endregion // Fields
34
35                 #region ctors
36
37                 public XmlDiffLoader (DataSet DSet) 
38                 {
39                         this.DSet = DSet;
40                 }
41
42                 #endregion //ctors
43
44                 #region Public methods
45
46                 public void Load (XmlReader Reader) 
47                 {
48
49                         XmlDocument Document = XmlDataLoader.buildXmlDocument(Reader);
50                         
51                         XPathNavigator Navigator = Document.CreateNavigator ();
52                         bool origEnforceConstraint = DSet.EnforceConstraints;
53                         DSet.EnforceConstraints = false;
54                         LoadBefore (Navigator);
55                         LoadCurrent (Navigator);
56                         LoadErrors (Navigator);
57                         DSet.EnforceConstraints = origEnforceConstraint;
58                 }
59
60                 #endregion // Public methods
61
62                 #region Private methods
63
64                 private void LoadCurrent (XPathNavigator Navigator) 
65                 {                       
66                         Navigator.MoveToRoot ();
67
68                         if (Navigator.MoveToFirstChild ()) {
69
70                                 if (Navigator.Name == "diffgr:diffgram") {
71
72                                         if (Navigator.MoveToFirstChild ()) {
73
74                                                 if (Navigator.MoveToFirstChild ()) {
75                                                         do {
76                                                                 if (DSet.Tables.Contains (Navigator.LocalName))
77                                                                         LoadCurrentTable(Navigator);
78                                                                 else 
79                                                                         throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + Navigator.LocalName + "' is missing in the destination dataset"));   
80                                                         }while (Navigator.MoveToNext());
81                                                 }
82                                         }
83                                 }
84                         }
85                 }
86
87                 private void LoadBefore (XPathNavigator Navigator) 
88                 {
89                         Navigator.MoveToRoot ();
90
91                         if (!Navigator.MoveToFirstChild ())
92                                 return; // FIXME: exception
93                         
94                         if (Navigator.Name != "diffgr:diffgram")
95                                 return; // FIXME: exception
96
97                         if (Navigator.MoveToFirstChild ()) {
98
99                                 while (Navigator.Name != "diffgr:before") {
100
101                                         if (!Navigator.MoveToNext ()) // there is no before
102                                                 return;
103                                 }
104
105                                 if (Navigator.MoveToFirstChild ()) {
106
107                                         do {
108                                                 if (DSet.Tables.Contains (Navigator.LocalName))
109                                                         LoadBeforeTable(Navigator);
110                                                 else
111                                                         throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + Navigator.LocalName + "' is missing in the destination dataset"));
112                                         } while (Navigator.MoveToNext ());
113                                 }
114                         }
115                 }                                
116                                 
117                                            
118                 private void LoadErrors (XPathNavigator Navigator) 
119                 {
120                         Navigator.MoveToRoot ();
121
122                         if (!Navigator.MoveToFirstChild ())
123                                 return; // FIXME: exception
124                         
125                         if (Navigator.Name != "diffgr:diffgram")
126                                 return; // FIXME: exception
127
128                         if (Navigator.MoveToFirstChild ()) {
129                                 
130                                 while (Navigator.Name != "diffgr:errors") {
131                                         if (!Navigator.MoveToNext ())
132                                                 return;
133                                 }
134
135                                 if (Navigator.MoveToFirstChild ()) {
136
137                                         DataRow Row = null;
138
139                                         // find the row in 'current' section
140                                         if (Navigator.MoveToFirstAttribute ()) {
141
142                                                 do {
143                                                         if (Navigator.Name == "diffgr:id") {
144                                                                 
145                                                                 if (ErrorRows.Contains (Navigator.Value))
146                                                                         Row = (DataRow)ErrorRows [Navigator.Value];
147                                                         }
148
149                                                 } while (Navigator.MoveToNextAttribute ());
150                                                 
151                                                 Navigator.MoveToParent ();                                              
152                                         }
153
154                                         if (Navigator.MoveToFirstChild ()) {
155
156                                                 string Error = "";
157                                                 
158                                                 do {
159                                                         if (Navigator.MoveToFirstAttribute ()) {
160                                                                 do {
161                                                                         if (Navigator.Name == "diffgr:Error")
162                                                                                 Error = Navigator.Value;
163
164                                                                 } while (Navigator.MoveToNextAttribute ());
165                                                                 
166                                                                 Navigator.MoveToParent ();
167                                                         }
168
169                                                         Row.SetColumnError (Navigator.LocalName, Error);
170
171                                                 } while (Navigator.MoveToNext ());
172                                         }
173                                 }
174                         }
175                 }
176
177                 private void LoadColumns (DataTable Table, DataRow Row, XPathNavigator Navigator, bool NewRow, LoadType loadType) 
178                 {
179                         if (Navigator.MoveToFirstChild ()) {
180
181                                 do {
182                                         if (Table.Columns.Contains (Navigator.LocalName))
183                                                 Row [Navigator.LocalName] = Navigator.Value;
184                                         else if (DSet.Tables.Contains (Navigator.LocalName)){
185                                                 if (loadType == LoadType.BEFORE)
186                                                         LoadBeforeTable(Navigator);
187                                                 else if (loadType == LoadType.CURRENT)
188                                                         LoadCurrentTable(Navigator);
189                                         }
190                                                                                 
191                                 } while (Navigator.MoveToNext ());
192                                 
193                                 if (NewRow)
194                                         Table.Rows.Add (Row);
195                         }
196                 }
197
198                 private void LoadBeforeTable (XPathNavigator Navigator) 
199                 {
200                                 
201                         String id = null;
202                         DataTable Table = DSet.Tables [Navigator.LocalName];
203                         DataRow Row = Table.NewRow ();
204                                                         
205                         if (Navigator.MoveToFirstAttribute ()) {
206                                                                 
207                                 do {
208                                         if (Navigator.Name == "diffgr:id")
209                                                 id = Navigator.Value;
210                                                                        
211                                 } while (Navigator.MoveToNextAttribute ());
212                                                                 
213                                 Navigator.MoveToParent ();
214                         }
215                                                                                                                 
216                         LoadColumns (Table, Row, Navigator, true, LoadType.BEFORE);
217                         DiffGrRows.Add (id, Row); // for later use
218                         Row.AcceptChanges ();
219                 }
220
221                 private void LoadCurrentTable (XPathNavigator Navigator) 
222                 {
223                         
224                         DataTable Table = DSet.Tables [Navigator.LocalName];
225                         DataRow Row = null;
226                         bool NewRow = false;
227                         bool HasErrors = false;
228                         string id = "";
229                                                                 
230                         if (Navigator.MoveToFirstAttribute ()) {
231                                                                         
232                                 do {
233                                         // Find out was there same row in 'before' section
234                                         if (Navigator.LocalName == "id") {
235                                                 id = Navigator.Value;
236                                                 if (DiffGrRows.Contains (id))
237                                                         Row = (DataRow)DiffGrRows [id];
238
239                                         }
240                                         else if (Navigator.LocalName == "hasErrors" && String.Compare (Navigator.Value, "true", true) == 0)
241                                                 HasErrors = true;
242                                 } while (Navigator.MoveToNextAttribute ());
243
244                                 // back to business
245                                 Navigator.MoveToParent ();
246                         }
247
248                         if (Row == null) {
249                                 Row = Table.NewRow ();
250                                 NewRow = true;
251                         }
252                                                                                                                                 
253                         LoadColumns (Table, Row, Navigator, NewRow, LoadType.CURRENT);
254                                                                         
255                         // back to business
256                         Navigator.MoveToParent();
257                                                                         
258                         if (HasErrors) // If row had errors add row to hashtable for later use
259                                 ErrorRows.Add (id, Row);
260                 
261                 }
262
263
264                 #endregion // Private methods
265         }
266 }