2006-02-17 Chris Toshok <toshok@ximian.com>
[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 ds)\r
69                 {\r
70                         // Null argument is allowed here.\r
71                         SetDataSet (ds);\r
72                 }\r
73 \r
74                 #endregion // Constructors\r
75 \r
76                 #region Properties\r
77 \r
78                 [DataSysDescription ("Indicates the source of data for this DataViewManager.")]\r
79                 [DefaultValue (null)]\r
80                 public DataSet DataSet {\r
81                         get { return dataSet; }\r
82                         set {\r
83                                 if (value == null)\r
84                                         throw new DataException ("Cannot set null DataSet.");\r
85                                 SetDataSet (value);\r
86                         }\r
87                 }\r
88 \r
89                 public string DataViewSettingCollectionString {\r
90                         get { return xml; }\r
91                         set {\r
92                                 try {\r
93                                         ParseSettingString (value);\r
94                                         xml = BuildSettingString ();\r
95                                 } catch (XmlException ex) {\r
96                                         throw new DataException ("Cannot set DataViewSettingCollectionString.", ex);\r
97                                 }\r
98                         }\r
99                 }\r
100 \r
101                 [DataSysDescription ("Indicates the sorting/filtering/state settings for any table in the corresponding DataSet.")]\r
102                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
103                 public DataViewSettingCollection DataViewSettings {\r
104                         get { return settings; }\r
105                 }\r
106 \r
107                 int ICollection.Count {\r
108                         get { return settings.Count; }\r
109                 }\r
110 \r
111                 bool ICollection.IsSynchronized {\r
112                         [MonoTODO]\r
113                         get { throw new NotImplementedException (); }\r
114                 }\r
115 \r
116                 object ICollection.SyncRoot {\r
117                         [MonoTODO]\r
118                         get { throw new NotImplementedException (); }\r
119                 }\r
120 \r
121                 bool IList.IsFixedSize {\r
122                         get { return true; }\r
123                 }\r
124 \r
125                 bool IList.IsReadOnly {\r
126                         get { return true; }\r
127                 }\r
128 \r
129                 object IList.this [int index] {\r
130                         get { \r
131                                 if (descriptor == null)\r
132                                         descriptor = new DataViewManagerListItemTypeDescriptor (this);\r
133 \r
134                                 return descriptor;\r
135                         }\r
136 \r
137                         set { throw new ArgumentException ("Not modifiable"); }\r
138                 }\r
139 \r
140                 bool IBindingList.AllowEdit {\r
141                         [MonoTODO]\r
142                         get { throw new NotImplementedException (); }\r
143                 }\r
144 \r
145                 bool IBindingList.AllowNew {\r
146                         [MonoTODO]\r
147                         get { throw new NotImplementedException (); }\r
148                 }\r
149 \r
150                 bool IBindingList.AllowRemove {\r
151                         [MonoTODO]\r
152                         get { throw new NotImplementedException (); }\r
153                 }\r
154 \r
155                 bool IBindingList.IsSorted {\r
156                         [MonoTODO]\r
157                         get { throw new NotImplementedException (); }\r
158                 }\r
159 \r
160                 ListSortDirection IBindingList.SortDirection {\r
161                         [MonoTODO]\r
162                         get { throw new NotImplementedException (); }\r
163                 }\r
164 \r
165                 PropertyDescriptor IBindingList.SortProperty {\r
166                         [MonoTODO]\r
167                         get { throw new NotImplementedException (); }\r
168                 }\r
169 \r
170                 bool IBindingList.SupportsChangeNotification {\r
171                         [MonoTODO]\r
172                         get { throw new NotImplementedException (); }\r
173                 }\r
174 \r
175                 bool IBindingList.SupportsSearching {\r
176                         [MonoTODO]\r
177                         get { throw new NotImplementedException (); }\r
178                 }\r
179 \r
180                 bool IBindingList.SupportsSorting {\r
181                         [MonoTODO]\r
182                         get { throw new NotImplementedException (); }\r
183                 }\r
184 \r
185                 #endregion // Properties\r
186 \r
187                 #region Methods\r
188                 private void SetDataSet (DataSet ds)\r
189                 {\r
190                         dataSet = ds;\r
191                         settings = new DataViewSettingCollection (this);\r
192                         xml = BuildSettingString ();\r
193                 }\r
194 \r
195                 private void ParseSettingString (string source)\r
196                 {\r
197                         XmlTextReader xtr = new XmlTextReader (source,\r
198                                 XmlNodeType.Element, null);\r
199 \r
200                         xtr.Read ();\r
201                         if (xtr.Name != "DataViewSettingCollectionString")\r
202                                 // easy way to throw the expected exception ;-)\r
203                         xtr.ReadStartElement ("DataViewSettingCollectionString");\r
204                         if (xtr.IsEmptyElement)\r
205                                 return; // MS does not change the value.\r
206 \r
207                         ArrayList result = new ArrayList ();\r
208                         xtr.Read ();\r
209                         do {\r
210                                 xtr.MoveToContent ();\r
211                                 if (xtr.NodeType == XmlNodeType.EndElement)\r
212                                         break;\r
213                                 if (xtr.NodeType == XmlNodeType.Element)\r
214                                         ReadTableSetting (xtr);\r
215                                 else\r
216                                         xtr.Skip ();\r
217                         } while (!xtr.EOF);\r
218                         if (xtr.NodeType == XmlNodeType.EndElement)\r
219                                 xtr.ReadEndElement ();\r
220                 }\r
221 \r
222                 private void ReadTableSetting (XmlReader reader)\r
223                 {\r
224                         // Namespace is ignored BTW.\r
225                         DataTable dt = DataSet.Tables [XmlConvert.DecodeName (\r
226                                 reader.LocalName)];\r
227                         // The code below might result in NullReference error.\r
228                         DataViewSetting s = settings [dt];\r
229                         string sort = reader.GetAttribute ("Sort");\r
230                         if (sort != null)\r
231                                 s.Sort = sort.Trim ();\r
232                         string ads = reader.GetAttribute ("ApplyDefaultSort");\r
233                         if (ads != null && ads.Trim () == "true")\r
234                                 s.ApplyDefaultSort = true;\r
235                         string rowFilter = reader.GetAttribute ("RowFilter");\r
236                         if (rowFilter != null)\r
237                                 s.RowFilter = rowFilter.Trim ();\r
238                         string rsf = reader.GetAttribute ("RowStateFilter");\r
239                         if (rsf != null)\r
240                                 s.RowStateFilter = (DataViewRowState)\r
241                                         Enum.Parse (typeof (DataViewRowState), \r
242                                         rsf.Trim ());\r
243                         reader.Skip ();\r
244                 }\r
245 \r
246                 private string BuildSettingString ()\r
247                 {\r
248                         if (dataSet == null)\r
249                                 return String.Empty;\r
250 \r
251                         StringWriter sw = new StringWriter ();\r
252                         sw.Write ('<');\r
253                         sw.Write ("DataViewSettingCollectionString>");\r
254                         foreach (DataViewSetting s in DataViewSettings) {\r
255                                 sw.Write ('<');\r
256                                 sw.Write (XmlConvert.EncodeName (\r
257                                                 s.Table.TableName));\r
258                                 sw.Write (" Sort=\"");\r
259                                 sw.Write (Escape (s.Sort));\r
260                                 sw.Write ('"');\r
261                                 // LAMESPEC: MS.NET does not seem to handle this property as expected.\r
262                                 if (s.ApplyDefaultSort)\r
263                                         sw.Write (" ApplyDefaultSort=\"true\"");\r
264                                 sw.Write (" RowFilter=\"");\r
265                                 sw.Write (Escape (s.RowFilter));\r
266                                 sw.Write ("\" RowStateFilter=\"");\r
267                                 sw.Write (s.RowStateFilter.ToString ());\r
268                                 sw.Write ("\"/>");\r
269                         }\r
270                         sw.Write ("</DataViewSettingCollectionString>");\r
271                         return sw.ToString ();\r
272                 }\r
273 \r
274                 private string Escape (string s)\r
275                 {\r
276                         return s.Replace ("&", "&amp;")\r
277                                 .Replace ("\"", "&quot;")\r
278                                 .Replace ("\'", "&apos;")\r
279                                 .Replace ("<", "&lt;")\r
280                                 .Replace (">", "&gt;");\r
281                 }\r
282 \r
283                 public DataView CreateDataView (DataTable table) \r
284                 {\r
285                         if (settings [table] != null) {\r
286                                 DataViewSetting s = settings [table];\r
287                                 return new DataView (table, this, s.Sort, s.RowFilter, s.RowStateFilter);\r
288                         } else {\r
289                                 return new DataView (table);\r
290                         }\r
291                 }\r
292 \r
293                 [MonoTODO]\r
294                 void IBindingList.AddIndex (PropertyDescriptor property)\r
295                 {\r
296                         throw new NotImplementedException ();\r
297                 }\r
298         \r
299                 [MonoTODO]\r
300                 object IBindingList.AddNew ()\r
301                 {\r
302                         throw new NotImplementedException ();\r
303                 }\r
304         \r
305                 [MonoTODO]\r
306                 void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)\r
307                 {\r
308                         throw new NotImplementedException ();\r
309                 }\r
310         \r
311                 [MonoTODO]\r
312                 int IBindingList.Find (PropertyDescriptor property, object key)\r
313                 {\r
314                         throw new NotImplementedException ();\r
315                 }\r
316         \r
317                 [MonoTODO]\r
318                 void IBindingList.RemoveIndex (PropertyDescriptor property)\r
319                 {\r
320                         throw new NotImplementedException ();\r
321                 }\r
322         \r
323                 [MonoTODO]\r
324                 void IBindingList.RemoveSort ()\r
325                 {\r
326                         throw new NotImplementedException ();\r
327                 }\r
328         \r
329                 [MonoTODO]\r
330                 void ICollection.CopyTo (Array array, int index)\r
331                 {\r
332                         throw new NotImplementedException ();\r
333                 }\r
334         \r
335                 [MonoTODO]\r
336                 IEnumerator IEnumerable.GetEnumerator ()\r
337                 {\r
338                         throw new NotImplementedException ();\r
339                 }\r
340         \r
341                 [MonoTODO]\r
342                 int IList.Add (object value)\r
343                 {\r
344                         throw new NotImplementedException ();\r
345                 }\r
346         \r
347                 [MonoTODO]\r
348                 void IList.Clear ()\r
349                 {\r
350                         throw new NotImplementedException ();\r
351                 }\r
352         \r
353                 [MonoTODO]\r
354                 bool IList.Contains (object value)\r
355                 {\r
356                         throw new NotImplementedException ();\r
357                 }\r
358         \r
359                 [MonoTODO]\r
360                 int IList.IndexOf (object value)\r
361                 {\r
362                         throw new NotImplementedException ();\r
363                 }\r
364         \r
365                 [MonoTODO]\r
366                 void IList.Insert (int index, object value)\r
367                 {\r
368                         throw new NotImplementedException ();\r
369                 }\r
370         \r
371                 [MonoTODO]\r
372                 void IList.Remove (object value)\r
373                 {\r
374                         throw new NotImplementedException ();\r
375                 }\r
376         \r
377                 [MonoTODO]\r
378                 void IList.RemoveAt (int index)\r
379                 {\r
380                         throw new NotImplementedException ();\r
381                 }\r
382         \r
383                 PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)\r
384                 {\r
385                         if (dataSet == null)\r
386                                 throw new DataException ("dataset is null");\r
387 \r
388                         if (listAccessors == null || listAccessors.Length == 0) {\r
389                                 ICustomTypeDescriptor desc = new DataViewManagerListItemTypeDescriptor (this);\r
390                                 return desc.GetProperties ();\r
391                         }\r
392                                 \r
393                         throw new NotImplementedException ();\r
394                 }\r
395         \r
396                 string ITypedList.GetListName (PropertyDescriptor[] listAccessors)\r
397                 {\r
398                         if (dataSet != null) {                                                  \r
399                                 if (listAccessors == null || listAccessors.Length == 0) {\r
400                                         return  dataSet.DataSetName;\r
401                                 }                               \r
402                         }                       \r
403                         \r
404                         return string.Empty;\r
405                 }\r
406         \r
407                 protected virtual void OnListChanged (ListChangedEventArgs e) \r
408                 {\r
409                         if (ListChanged != null)\r
410                                 ListChanged (this, e);\r
411                 }\r
412 \r
413                 protected virtual void RelationCollectionChanged (object sender, CollectionChangeEventArgs e) \r
414                 {\r
415                         ListChangedEventArgs args;\r
416 \r
417                         if (e.Action == CollectionChangeAction.Remove) {\r
418                                 args = null;\r
419                         }\r
420                         else if (e.Action == CollectionChangeAction.Refresh) {\r
421                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorChanged, null);\r
422                         }\r
423                         else if (e.Action == CollectionChangeAction.Add) {\r
424                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorAdded, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
425                         }\r
426                         else {\r
427                                 args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorDeleted, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
428                         }\r
429 \r
430                         this.OnListChanged(args);\r
431                 }\r
432 \r
433                 protected virtual void TableCollectionChanged (object sender, CollectionChangeEventArgs e) \r
434                 {\r
435                 }\r
436 \r
437                 #endregion // Methods\r
438 \r
439                 #region Events\r
440 \r
441                 public event ListChangedEventHandler ListChanged;\r
442 \r
443                 #endregion // Events\r
444         }\r
445 }\r