importing messaging-2008 branch to trunk [continued]
[mono.git] / mcs / class / System.Data / System.Data / DataViewManager.cs
1 //\r
2 // System.Data.DataViewManager\r
3 //\r
4 // Author:\r
5 //   Rodrigo Moya (rodrigo@ximian.com)\r
6 //   Tim Coleman (tim@timcoleman.com)\r
7 //   Atsushi Enomoto (atsushi@ximian.com)\r
8 //\r
9 // (C) Ximian, Inc. 2002\r
10 // Copyright (C) Tim Coleman, 2002\r
11 // Copyright (C) 2005 Novell Inc,\r
12 //\r
13 \r
14 //\r
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
16 //\r
17 // Permission is hereby granted, free of charge, to any person obtaining\r
18 // a copy of this software and associated documentation files (the\r
19 // "Software"), to deal in the Software without restriction, including\r
20 // without limitation the rights to use, copy, modify, merge, publish,\r
21 // distribute, sublicense, and/or sell copies of the Software, and to\r
22 // permit persons to whom the Software is furnished to do so, subject to\r
23 // the following conditions:\r
24 // \r
25 // The above copyright notice and this permission notice shall be\r
26 // included in all copies or substantial portions of the Software.\r
27 // \r
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
35 //\r
36 \r
37 using System;\r
38 using System.Collections;\r
39 using System.ComponentModel;\r
40 using System.IO;\r
41 using System.Xml;\r
42 \r
43 namespace System.Data\r
44 {\r
45         /// <summary>\r
46         /// Contains a default DataViewSettingCollection for each DataTable in a DataSet.\r
47         /// </summary>\r
48         //[Designer]\r
49         [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewManagerDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
50         public class DataViewManager : MarshalByValueComponent, IBindingList, ICollection, IList, ITypedList, IEnumerable\r
51         {\r
52                 #region Fields\r
53 \r
54                 DataSet dataSet;\r
55                 DataViewManagerListItemTypeDescriptor descriptor;\r
56                 DataViewSettingCollection settings;\r
57                 string xml;\r
58 \r
59                 #endregion // Fields\r
60 \r
61                 #region Constructors\r
62 \r
63                 public DataViewManager ()\r
64                         : this (null)\r
65                 {\r
66                 }\r
67 \r
68                 public DataViewManager (DataSet dataSet)\r
69                 {\r
70                         // Null argument is allowed here.\r
71                         SetDataSet (dataSet);\r
72                 }\r
73 \r
74                 #endregion // Constructors\r
75 \r
76                 #region Properties\r
77 \r
78 #if !NET_2_0\r
79                 [DataSysDescription ("Indicates the source of data for this DataViewManager.")]\r
80 #endif\r
81                 [DefaultValue (null)]\r
82                 public DataSet DataSet {\r
83                         get { return dataSet; }\r
84                         set {\r
85                                 if (value == null)\r
86                                         throw new DataException ("Cannot set null DataSet.");\r
87                                 SetDataSet (value);\r
88                         }\r
89                 }\r
90 \r
91                 public string DataViewSettingCollectionString {\r
92                         get { return xml; }\r
93                         set {\r
94                                 try {\r
95                                         ParseSettingString (value);\r
96                                         xml = BuildSettingString ();\r
97                                 } catch (XmlException ex) {\r
98                                         throw new DataException ("Cannot set DataViewSettingCollectionString.", ex);\r
99                                 }\r
100                         }\r
101                 }\r
102 \r
103 #if !NET_2_0\r
104                 [DataSysDescription ("Indicates the sorting/filtering/state settings for any table in the corresponding DataSet.")]\r
105 #endif\r
106                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
107                 public DataViewSettingCollection DataViewSettings {\r
108                         get { return settings; }\r
109                 }\r
110 \r
111                 int ICollection.Count {\r
112                         get { return 1; }\r
113                 }\r
114 \r
115                 bool ICollection.IsSynchronized {\r
116                         [MonoTODO]\r
117                         get { throw new NotImplementedException (); }\r
118                 }\r
119 \r
120                 object ICollection.SyncRoot {\r
121                         [MonoTODO]\r
122                         get { throw new NotImplementedException (); }\r
123                 }\r
124 \r
125                 bool IList.IsFixedSize {\r
126                         get { return true; }\r
127                 }\r
128 \r
129                 bool IList.IsReadOnly {\r
130                         get { return true; }\r
131                 }\r
132 \r
133                 object IList.this [int index] {\r
134                         get { \r
135                                 if (descriptor == null)\r
136                                         descriptor = new DataViewManagerListItemTypeDescriptor (this);\r
137 \r
138                                 return descriptor;\r
139                         }\r
140 \r
141                         set { throw new ArgumentException ("Not modifiable"); }\r
142                 }\r
143 \r
144                 bool IBindingList.AllowEdit {\r
145                         [MonoTODO]\r
146                         get { throw new NotImplementedException (); }\r
147                 }\r
148 \r
149                 bool IBindingList.AllowNew {\r
150                         [MonoTODO]\r
151                         get { throw new NotImplementedException (); }\r
152                 }\r
153 \r
154                 bool IBindingList.AllowRemove {\r
155                         [MonoTODO]\r
156                         get { throw new NotImplementedException (); }\r
157                 }\r
158 \r
159                 bool IBindingList.IsSorted {\r
160                         [MonoTODO]\r
161                         get { throw new NotImplementedException (); }\r
162                 }\r
163 \r
164                 ListSortDirection IBindingList.SortDirection {\r
165                         [MonoTODO]\r
166                         get { throw new NotImplementedException (); }\r
167                 }\r
168 \r
169                 PropertyDescriptor IBindingList.SortProperty {\r
170                         [MonoTODO]\r
171                         get { throw new NotImplementedException (); }\r
172                 }\r
173 \r
174                 bool IBindingList.SupportsChangeNotification {\r
175                         [MonoTODO]\r
176                         get { throw new NotImplementedException (); }\r
177                 }\r
178 \r
179                 bool IBindingList.SupportsSearching {\r
180                         [MonoTODO]\r
181                         get { throw new NotImplementedException (); }\r
182                 }\r
183 \r
184                 bool IBindingList.SupportsSorting {\r
185                         [MonoTODO]\r
186                         get { throw new NotImplementedException (); }\r
187                 }\r
188 \r
189                 #endregion // Properties\r
190 \r
191                 #region Methods\r
192 \r
193                 private void SetDataSet (DataSet ds)\r
194                 {\r
195                         dataSet = ds;\r
196                         settings = new DataViewSettingCollection (this);\r
197                         xml = BuildSettingString ();\r
198                 }\r
199 \r
200                 private void ParseSettingString (string source)\r
201                 {\r
202                         XmlTextReader xtr = new XmlTextReader (source,\r
203                                 XmlNodeType.Element, null);\r
204 \r
205                         xtr.Read ();\r
206                         if (xtr.Name != "DataViewSettingCollectionString")\r
207                                 // easy way to throw the expected exception ;-)\r
208                         xtr.ReadStartElement ("DataViewSettingCollectionString");\r
209                         if (xtr.IsEmptyElement)\r
210                                 return; // MS does not change the value.\r
211 \r
212                         xtr.Read ();\r
213                         do {\r
214                                 xtr.MoveToContent ();\r
215                                 if (xtr.NodeType == XmlNodeType.EndElement)\r
216                                         break;\r
217                                 if (xtr.NodeType == XmlNodeType.Element)\r
218                                         ReadTableSetting (xtr);\r
219                                 else\r
220                                         xtr.Skip ();\r
221                         } while (!xtr.EOF);\r
222                         if (xtr.NodeType == XmlNodeType.EndElement)\r
223                                 xtr.ReadEndElement ();\r
224                 }\r
225 \r
226                 private void ReadTableSetting (XmlReader reader)\r
227                 {\r
228                         // Namespace is ignored BTW.\r
229                         DataTable dt = DataSet.Tables [XmlConvert.DecodeName (\r
230                                 reader.LocalName)];\r
231                         // The code below might result in NullReference error.\r
232                         DataViewSetting s = settings [dt];\r
233                         string sort = reader.GetAttribute ("Sort");\r
234                         if (sort != null)\r
235                                 s.Sort = sort.Trim ();\r
236                         string ads = reader.GetAttribute ("ApplyDefaultSort");\r
237                         if (ads != null && ads.Trim () == "true")\r
238                                 s.ApplyDefaultSort = true;\r
239                         string rowFilter = reader.GetAttribute ("RowFilter");\r
240                         if (rowFilter != null)\r
241                                 s.RowFilter = rowFilter.Trim ();\r
242                         string rsf = reader.GetAttribute ("RowStateFilter");\r
243                         if (rsf != null)\r
244                                 s.RowStateFilter = (DataViewRowState)\r
245                                         Enum.Parse (typeof (DataViewRowState), \r
246                                         rsf.Trim ());\r
247                         reader.Skip ();\r
248                 }\r
249 \r
250                 private string BuildSettingString ()\r
251                 {\r
252                         if (dataSet == null)\r
253                                 return String.Empty;\r
254 \r
255                         StringWriter sw = new StringWriter ();\r
256                         sw.Write ('<');\r
257                         sw.Write ("DataViewSettingCollectionString>");\r
258                         foreach (DataViewSetting s in DataViewSettings) {\r
259                                 sw.Write ('<');\r
260                                 sw.Write (XmlConvert.EncodeName (\r
261                                                 s.Table.TableName));\r
262                                 sw.Write (" Sort=\"");\r
263                                 sw.Write (Escape (s.Sort));\r
264                                 sw.Write ('"');\r
265                                 // LAMESPEC: MS.NET does not seem to handle this property as expected.\r
266                                 if (s.ApplyDefaultSort)\r
267                                         sw.Write (" ApplyDefaultSort=\"true\"");\r
268                                 sw.Write (" RowFilter=\"");\r
269                                 sw.Write (Escape (s.RowFilter));\r
270                                 sw.Write ("\" RowStateFilter=\"");\r
271                                 sw.Write (s.RowStateFilter.ToString ());\r
272                                 sw.Write ("\"/>");\r
273                         }\r
274                         sw.Write ("</DataViewSettingCollectionString>");\r
275                         return sw.ToString ();\r
276                 }\r
277 \r
278                 private string Escape (string s)\r
279                 {\r
280                         return s.Replace ("&", "&amp;")\r
281                                 .Replace ("\"", "&quot;")\r
282                                 .Replace ("\'", "&apos;")\r
283                                 .Replace ("<", "&lt;")\r
284                                 .Replace (">", "&gt;");\r
285                 }\r
286 \r
287                 public DataView CreateDataView (DataTable table)\r
288                 {\r
289                         if (settings [table] != null) {\r
290                                 DataViewSetting s = settings [table];\r
291                                 return new DataView (table, this, s.Sort, s.RowFilter, s.RowStateFilter);\r
292                         } else {\r
293                                 return new DataView (table);\r
294                         }\r
295                 }\r
296 \r
297                 [MonoTODO]\r
298                 void IBindingList.AddIndex (PropertyDescriptor property)\r
299                 {\r
300                         throw new NotImplementedException ();\r
301                 }\r
302         \r
303                 [MonoTODO]\r
304                 object IBindingList.AddNew ()\r
305                 {\r
306                         throw new NotImplementedException ();\r
307                 }\r
308         \r
309                 [MonoTODO]\r
310                 void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)\r
311                 {\r
312                         throw new NotImplementedException ();\r
313                 }\r
314         \r
315                 [MonoTODO]\r
316                 int IBindingList.Find (PropertyDescriptor property, object key)\r
317                 {\r
318                         throw new NotImplementedException ();\r
319                 }\r
320         \r
321                 [MonoTODO]\r
322                 void IBindingList.RemoveIndex (PropertyDescriptor property)\r
323                 {\r
324                         throw new NotImplementedException ();\r
325                 }\r
326         \r
327                 [MonoTODO]\r
328                 void IBindingList.RemoveSort ()\r
329                 {\r
330                         throw new NotImplementedException ();\r
331                 }\r
332         \r
333                 [MonoTODO]\r
334                 void ICollection.CopyTo (Array array, int index)\r
335                 {\r
336                         throw new NotImplementedException ();\r
337                 }\r
338         \r
339                 [MonoTODO]\r
340                 IEnumerator IEnumerable.GetEnumerator ()\r
341                 {\r
342                         throw new NotImplementedException ();\r
343                 }\r
344         \r
345                 [MonoTODO]\r
346                 int IList.Add (object value)\r
347                 {\r
348                         throw new NotImplementedException ();\r
349                 }\r
350         \r
351                 [MonoTODO]\r
352                 void IList.Clear ()\r
353                 {\r
354                         throw new NotImplementedException ();\r
355                 }\r
356         \r
357                 [MonoTODO]\r
358                 bool IList.Contains (object value)\r
359                 {\r
360                         throw new NotImplementedException ();\r
361                 }\r
362         \r
363                 [MonoTODO]\r
364                 int IList.IndexOf (object value)\r
365                 {\r
366                         throw new NotImplementedException ();\r
367                 }\r
368         \r
369                 [MonoTODO]\r
370                 void IList.Insert (int index, object value)\r
371                 {\r
372                         throw new NotImplementedException ();\r
373                 }\r
374         \r
375                 [MonoTODO]\r
376                 void IList.Remove (object value)\r
377                 {\r
378                         throw new NotImplementedException ();\r
379                 }\r
380         \r
381                 [MonoTODO]\r
382                 void IList.RemoveAt (int index)\r
383                 {\r
384                         throw new NotImplementedException ();\r
385                 }\r
386         \r
387                 [MonoLimitation("Supported only empty list of listAccessors")]\r
388                 PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)\r
389                 {\r
390                         if (dataSet == null)\r
391                                 throw new DataException ("dataset is null");\r
392 \r
393                         if (listAccessors == null || listAccessors.Length == 0) {\r
394                                 ICustomTypeDescriptor desc = new DataViewManagerListItemTypeDescriptor (this);\r
395                                 return desc.GetProperties ();\r
396                         }\r
397                                 \r
398                         throw new NotImplementedException ();\r
399                 }\r
400         \r
401                 string ITypedList.GetListName (PropertyDescriptor[] listAccessors)\r
402                 {\r
403                         if (dataSet != null) {\r
404                                 if (listAccessors == null || listAccessors.Length == 0)\r
405                                         return  dataSet.DataSetName;\r
406                         }\r
407                         \r
408                         return string.Empty;\r
409                 }\r
410         \r
411                 protected virtual void OnListChanged (ListChangedEventArgs e)\r
412                 {\r
413                         if (ListChanged != null)\r
414                                 ListChanged (this, e);\r
415                 }\r
416 \r
417                 protected virtual void RelationCollectionChanged (object sender, CollectionChangeEventArgs e)\r
418                 {\r
419                         ListChangedEventArgs args;\r
420 \r
421                         if (e.Action == CollectionChangeAction.Remove) {\r
422                                 args = null;\r
423                         } else if (e.Action == CollectionChangeAction.Refresh) {\r
424                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorChanged, null);\r
425                         } else if (e.Action == CollectionChangeAction.Add) {\r
426                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorAdded, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
427                         } else {\r
428                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorDeleted, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
429                         }\r
430 \r
431                         this.OnListChanged(args);\r
432                 }\r
433 \r
434                 protected virtual void TableCollectionChanged (object sender, CollectionChangeEventArgs e)\r
435                 {\r
436                 }\r
437 \r
438                 #endregion // Methods\r
439 \r
440                 #region Events\r
441 \r
442                 public event ListChangedEventHandler ListChanged;\r
443 \r
444                 #endregion // Events\r
445         }\r
446 }\r