Sat Jan 5 15:56:54 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / class / corlib / System.Collections / DictionaryBase.cs
1 //
2 // System.Collections.DictionaryBase.cs
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11
12 namespace System.Collections {
13
14         /// <summary>
15         ///   An abstract class that provides a simple way to monitor changes to a
16         ///   Hashtable.  Derived classes overwrite one or more of the `On' methods
17         ///   to track the changes to the Hashtable.
18         /// </summary>
19         ///
20         /// <remarks>
21         ///   This class is a base class that can simplify the development of
22         ///   strongly typed collections.  The idea being that the insertion of elements
23         ///   into the Hashtable can be forced to be of a given type.
24         ///
25         ///   The `On' members are protected and designed to be used only by derived
26         ///   classes.
27         /// </remarks>
28         public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable {
29
30                 Hashtable dictionary;
31                 
32                 protected DictionaryBase ()
33                 {
34                         dictionary = new Hashtable ();
35                 }
36
37                 /// <summary>
38                 ///   Clears the contents of the dictionary
39                 /// </summary>
40                 public void Clear ()
41                 {
42                         OnClear ();
43                         dictionary.Clear ();
44                         OnClearComplete ();
45                 }
46
47                 /// <summary>
48                 ///   Returns the number of items in the dictionary
49                 /// </summary>
50                 public int Count {
51                         get {
52                                 return dictionary.Count;
53                         }
54                 }
55
56                 /// <summary>
57                 ///   The collection contained as an IDictionary
58                 /// </summary>
59                 protected IDictionary Dictionary {
60                         get {
61                                 return dictionary;
62                         }
63                 }
64
65                 /// <summary>
66                 ///   The internal Hashtable representation for this dictionary
67                 /// </summary>
68                 protected Hashtable InnerHashtable {
69                         get {
70                                 return dictionary;
71                         }
72                 }
73
74                 /// <summary>
75                 ///   Copies the contents of the Dictionary into the target array
76                 /// </summary>
77                 /// <param name="array">
78                 ///   The array to copy the contents of the dictionary to.  The
79                 ///   array must have a zero-based indexing
80                 /// </param>
81                 /// <param name="index">
82                 ///   Starting index within the array where to copy the objects
83                 ///   to.
84                 /// </param>
85                 public void CopyTo (Array array, int index)
86                 {
87                         if (array == null)
88                                 throw new ArgumentNullException ("array");
89                         if (index < 0)
90                                 throw new ArgumentOutOfRangeException ("index must be possitive");
91                         if (array.Rank > 1)
92                                 throw new ArgumentException ("array is multidimensional");
93                         int size = array.Length;
94                         if (index > size)
95                                 throw new ArgumentException ("index is larger than array size");
96                         if (index + Count > size)
97                                 throw new ArgumentException ("Copy will overlflow array");
98
99                         DoCopy (array, index);
100                 }
101
102                 /// <summary>
103                 ///   Internal routine called by CopyTo to perform the actual
104                 ///   copying of the data
105                 /// </summary>
106                 virtual protected void DoCopy (Array array, int index)
107                 {
108                         foreach (DictionaryEntry de in dictionary)
109                                 array.SetValue (de, index++);
110                 }
111
112                 /// <summary>
113                 ///   Returns an enumerator for the dictionary
114                 /// </summary>
115                 public IDictionaryEnumerator GetEnumerator ()
116                 {
117                         return dictionary.GetEnumerator ();
118                 }
119
120                 /// <summary>
121                 ///   Hook invoked before the clear operation
122                 ///   is performed on the DictionaryBase
123                 /// </summary>
124                 protected virtual void OnClear ()
125                 {
126                 }
127
128                 /// <summary>
129                 ///   Hook invoked after the clear operation
130                 ///   is performed on the DictionaryBase
131                 /// </summary>
132                 ///
133                 /// <remarks>
134                 ///   The default implementation does nothing, derived classes
135                 ///   can override this method to be notified of changes
136                 /// </remarks>
137                 protected virtual void OnClearComplete ()
138                 {
139                 }
140
141                 /// <summary>
142                 ///   Hook invoked while fetching data from the DictionaryBase.
143                 /// </summary>
144                 ///
145                 /// <remarks>
146                 ///   This method is provided as a simple way to override the values
147                 ///   returned by the DictionaryBase. 
148                 /// </remarks>
149                 ///
150                 /// <param name="key">Key of the object to retrieve</param>
151                 /// <param name="current_value">Current value of the object associated with
152                 /// <paramref name="key"/></param>
153                 protected virtual object OnGet (object key, object current_value)
154                 {
155                         return current_value;
156                 }
157
158                 /// <summary>
159                 ///   Hook invoked before inserting data into the DictionaryBase.
160                 /// </summary>
161                 ///
162                 /// <remarks>
163                 ///   Derived classes can override this method and perform some
164                 ///   action before the <paramref name="current_value"/> is inserted
165                 ///   into the dictionary.
166                 ///
167                 ///   The default implementation does nothing, derived classes
168                 ///   can override this method to be notified of changes
169                 /// </remarks>
170                 ///
171                 /// <param name="key">Key of the object to insert</param>
172                 /// <param name="current_value">Current value of the object associated with
173                 /// <paramref name="key"/></param>
174                 protected virtual void OnInsert (object key, object current_value)
175                 {
176                 }
177                 
178                 /// <summary>
179                 ///   Hook invoked after inserting the data into the DictionaryBase
180                 /// </summary>
181                 ///
182                 /// <remarks>
183                 ///   The default implementation does nothing, derived classes
184                 ///   can override this method to be notified of changes
185                 /// </remarks>
186                 ///
187                 /// <param name="key">Key of the object to insert</param>
188                 /// <param name="current_value">Current value of the object associated with
189                 /// <paramref name="key"/></param>
190                 protected virtual void OnInsertComplete (object key, object current_value)
191                 {
192                 }
193
194                 /// <summary>
195                 ///   Hook invoked before changing a value for a key in the DictionaryBase.
196                 /// </summary>
197                 ///
198                 /// <remarks>
199                 ///   Derived classes can override this method and perform some
200                 ///   action before the <paramref name="current_value"/> is changed
201                 ///   in the dictionary.  
202                 /// </remarks>
203                 ///
204                 /// <param name="key">Key of the object to change</param>
205                 /// <param name="current_value">Current value of the object associated with
206                 /// <paramref name="key"/></param>
207                 protected virtual void OnSet (object key, object current_value)
208                 {
209                 }
210                 
211                 /// <summary>
212                 ///   Hook invoked after changing a value for a key in the DictionaryBase.
213                 /// </summary>
214                 ///
215                 /// <remarks>
216                 ///   The default implementation does nothing, derived classes
217                 ///   can override this method to be notified of changes
218                 /// </remarks>
219                 ///
220                 /// <param name="key">Key of the object to change</param>
221                 /// <param name="current_value">Current value of the object associated with
222                 /// <paramref name="key"/></param>
223                 protected virtual void OnSetComplete (object key, object current_value)
224                 {
225                 }
226
227                 /// <summary>
228                 ///   Hook invoked before removing a key/value from the DictionaryBase.
229                 /// </summary>
230                 ///
231                 /// <remarks>
232                 ///   Derived classes can override this method and perform some
233                 ///   action before the <paramref name="current_value"/> is removed
234                 ///   from the dictionary.  
235                 /// </remarks>
236                 ///
237                 /// <param name="key">Key of the object to remove</param>
238                 /// <param name="current_value">Current value of the object associated with
239                 /// <paramref name="key"/></param>
240                 protected virtual void OnRemove (object key, object current_value)
241                 {
242                 }
243                 
244                 /// <summary>
245                 ///   Hook invoked after removing a key/value from the DictionaryBase.
246                 /// </summary>
247                 ///
248                 /// <remarks>
249                 ///   The default implementation does nothing, derived classes
250                 ///   can override this method to be notified of changes.
251                 /// </remarks>
252                 ///
253                 /// <param name="key">Key of the object to remove</param>
254                 /// <param name="current_value">Current value of the object associated with
255                 /// <paramref name="key"/></param>
256                 protected virtual void OnRemoveComplete (object key, object current_value)
257                 {
258                 }
259                 
260                 /// <summary>
261                 ///   Hook invoked after the value has been validated
262                 /// </summary>
263                 ///
264                 /// <remarks>
265                 ///   The default implementation does nothing, derived classes
266                 ///   can override this method to monitor the DictionaryBase.
267                 /// </remarks>
268                 ///
269                 /// <param name="key">Key of the object to retrieve</param>
270                 /// <param name="current_value">Current value of the object associated with
271                 /// <paramref name="key"/></param>
272                 protected virtual void OnValidate (object key, object current_value)
273                 {
274                 }
275
276                 bool IDictionary.IsFixedSize {
277                         get {
278                                 return false;
279                         }
280                 }
281
282                 bool IDictionary.IsReadOnly {
283                         get {
284                                 return false;
285                         }
286                 }
287
288                 object IDictionary.this [object key] {
289                         get {
290                                 object value = dictionary [key];
291
292                                 OnGet (key, value);
293                                 return value;
294                         }
295
296                         set {
297                                 if (dictionary.ContainsKey (key)){
298                                         OnSet (key, value);
299                                         dictionary [key] = value;
300                                         OnSetComplete (key, value);
301                                 } else {
302                                         OnInsert (key, value);
303                                         dictionary [key] = value;
304                                         OnInsertComplete (key, value);
305                                 }
306                         }
307                 }
308
309                 ICollection IDictionary.Keys {
310                         get {
311                                 return dictionary.Keys;
312                         }
313                 }
314
315                 ICollection IDictionary.Values {
316                         get {
317                                 return dictionary.Values;
318                         }
319                 }
320
321                 /// <summary>
322                 ///   Adds a key/value pair to the dictionary.
323                 /// </summary>
324                 void IDictionary.Add (object key, object value)
325                 {
326                         OnInsert (key, value);
327                         dictionary.Add (key, value);
328                         OnInsertComplete (key, value);
329                 }
330
331                 /// <summary>
332                 ///   Removes a Dictionary Entry based on its key
333                 /// </summary>
334                 void IDictionary.Remove (object key)
335                 {
336                         if (! dictionary.ContainsKey (key))
337                                 return;
338
339                         object value = dictionary [key];
340                         OnRemove (key, value);
341                         dictionary.Remove (key);
342                         OnRemoveComplete (key, value);
343                 }
344
345                 /// <summary>
346                 ///   Tests whether the dictionary contains an entry
347                 /// </summary>
348                 bool IDictionary.Contains (object key)
349                 {
350                         return dictionary.Contains (key);
351                 }
352
353                 bool ICollection.IsSynchronized {
354                         get {
355                                 return dictionary.IsSynchronized;
356                         }
357                 }
358
359                 object ICollection.SyncRoot {
360                         get {
361                                 return dictionary.SyncRoot;
362                         }
363                 }
364
365                 IEnumerator IEnumerable.GetEnumerator ()
366                 {
367                         return dictionary.GetEnumerator ();
368                 }
369         }
370 }