More patches from Eran Domb <erand@mainsoft.com>.
[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
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                         XmlTextReader TextReader = new XmlTextReader (Reader.BaseURI);
49                         XmlDocument Document = new XmlDocument ();
50                         Document.Load (TextReader);
51                         TextReader.Close ();
52
53                         XPathNavigator Navigator = Document.CreateNavigator ();
54                         LoadBefore (Navigator);
55                         LoadCurrent (Navigator);
56                         LoadErrors (Navigator);
57                 }
58
59                 #endregion // Public methods
60
61                 #region Private methods
62
63                 private void LoadCurrent (XPathNavigator Navigator)
64                 {                       
65                         Navigator.MoveToRoot ();
66
67                         if (Navigator.MoveToFirstChild ()) {
68
69                                 if (Navigator.Name == "diffgr:diffgram") {
70
71                                         if (Navigator.MoveToFirstChild ()) {
72
73                                                 if (Navigator.MoveToFirstChild ()) {
74
75                                                         if (DSet.Tables.Contains (Navigator.LocalName)) {
76
77                                                                 DataTable Table = DSet.Tables [Navigator.LocalName];
78                                                                 DataRow Row = null;
79                                                                 bool NewRow = false;
80                                                                 bool HasErrors = false;
81                                                                 string id = "";
82                                                                 
83                                                                 if (Navigator.MoveToFirstAttribute ()) {
84                                                                         
85                                                                         do {
86                                                                                 // Find out was there same row in 'before' section
87                                                                                 if (Navigator.LocalName == "id") {
88                                                                                         id = Navigator.Value;
89                                                                                         if (DiffGrRows.Contains (id))
90                                                                                                 Row = (DataRow)DiffGrRows [id];
91
92                                                                                 }
93                                                                                 else if (Navigator.LocalName == "hasErrors" && String.Compare (Navigator.Value, "true", true) == 0)
94                                                                                    HasErrors = true;
95                                                                         } while (Navigator.MoveToNextAttribute ());
96
97                                                                         // back to business
98                                                                         Navigator.MoveToParent ();
99                                                                 }
100
101                                                                 if (Row == null) {
102                                                                         
103                                                                         Row = Table.NewRow ();
104                                                                         NewRow = true;
105                                                                 }
106                                                                                                                                 
107                                                                 LoadColumns (Table, Row, Navigator, NewRow);
108
109                                                                 if (HasErrors) // If row had errors add row to hashtable for later use
110                                                                         ErrorRows.Add (id, Row);
111                                                         }
112                                                 }
113                                         }
114                                 }
115                         }
116                 }
117
118                 private void LoadBefore (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:before") {
131
132                                         if (!Navigator.MoveToNext ()) // there is no before
133                                                 return;
134                                 }
135
136                                 if (Navigator.MoveToFirstChild ()) {
137
138                                         do {
139                                                 if (DSet.Tables.Contains (Navigator.LocalName)) {
140
141                                                         String id = null;
142                                                         DataTable Table = DSet.Tables [Navigator.LocalName];
143                                                         DataRow Row = Table.NewRow ();
144                                                         
145                                                         if (Navigator.MoveToFirstAttribute ()) {
146                                                                 
147                                                                 do {
148                                                                         if (Navigator.Name == "diffgr:id")
149                                                                                 id = Navigator.Value;
150                                                                        
151                                                                 } while (Navigator.MoveToNextAttribute ());
152                                                                 
153                                                                 Navigator.MoveToParent ();
154                                                         }
155                                                                                                                 
156                                                         LoadColumns (Table, Row, Navigator, true);
157                                                         DiffGrRows.Add (id, Row); // for later use
158                                                         Row.AcceptChanges ();
159                                                 } 
160                                                 else {
161                                                         throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + Navigator.LocalName + "' is missing in the destination dataset"));
162                                                 }
163                                         } while (Navigator.MoveToNext ());
164                                 }
165                         }
166                 }                                
167                                 
168                                            
169                 private void LoadErrors (XPathNavigator Navigator)
170                 {
171                         Navigator.MoveToRoot ();
172
173                         if (!Navigator.MoveToFirstChild ())
174                                 return; // FIXME: exception
175                         
176                         if (Navigator.Name != "diffgr:diffgram")
177                                 return; // FIXME: exception
178
179                         if (Navigator.MoveToFirstChild ()) {
180                                 
181                                 while (Navigator.Name != "diffgr:errors") {
182                                         if (!Navigator.MoveToNext ())
183                                                 return;
184                                 }
185
186                                 if (Navigator.MoveToFirstChild ()) {
187
188                                         DataRow Row = null;
189
190                                         // find the row in 'current' section
191                                         if (Navigator.MoveToFirstAttribute ()) {
192
193                                                 do {
194                                                         if (Navigator.Name == "diffgr:id") {
195                                                                 
196                                                                 if (ErrorRows.Contains (Navigator.Value))
197                                                                         Row = (DataRow)ErrorRows [Navigator.Value];
198                                                         }
199
200                                                 } while (Navigator.MoveToNextAttribute ());
201                                                 
202                                                 Navigator.MoveToParent ();                                              
203                                         }
204
205                                         if (Navigator.MoveToFirstChild ()) {
206
207                                                 string Error = "";
208                                                 
209                                                 do {
210                                                         if (Navigator.MoveToFirstAttribute ()) {
211                                                                 do {
212                                                                         if (Navigator.Name == "diffgr:Error")
213                                                                                 Error = Navigator.Value;
214
215                                                                 } while (Navigator.MoveToNextAttribute ());
216                                                                 
217                                                                 Navigator.MoveToParent ();
218                                                         }
219
220                                                         Row.SetColumnError (Navigator.LocalName, Error);
221
222                                                 } while (Navigator.MoveToNext ());
223                                         }
224                                 }
225                         }
226                 }
227
228                 private void LoadColumns (DataTable Table, DataRow Row, XPathNavigator Navigator, bool NewRow)
229                 {
230                         if (Navigator.MoveToFirstChild ()) {
231
232                                 do {
233                                         if (Table.Columns.Contains (Navigator.LocalName))
234                                                 Row [Navigator.LocalName] = Navigator.Value;
235                                                                                 
236                                 } while (Navigator.MoveToNext ());
237                                 
238                                 if (NewRow)
239                                         Table.Rows.Add (Row);
240                         }
241                 }
242
243
244                 #endregion // Private methods
245         }
246 }