importing messaging-2008 branch to trunk [continued]
[mono.git] / mcs / class / System.Web / System.Web.UI / StateManagedCollection.cs
1 //
2 // System.Web.UI.StateManagedCollection
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //      Marek Habersack (mhabersack@novell.com)
8 //
9 // (C) 2003 Ben Maurer
10 // Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if NET_2_0
33
34 using System.Collections;
35 using System.Collections.Generic;
36
37 namespace System.Web.UI {
38
39         public abstract class StateManagedCollection : IList, IStateManager
40         {               
41                 ArrayList items = new ArrayList ();
42                 bool saveEverything = false;
43
44                 protected virtual object CreateKnownType (int index)
45                 {
46                         return null;
47                 }
48
49                 public void SetDirty ()
50                 {
51                         saveEverything = true;
52                         for (int i = 0; i < items.Count; i++)
53                                 SetDirtyObject (items[i]);
54                 }
55
56                 protected abstract void SetDirtyObject (object o);
57
58                 protected virtual Type [] GetKnownTypes ()
59                 {
60                         return null;
61                 }
62                 
63                 #region OnXXX
64                 protected virtual void OnClear ()
65                 {
66                 }
67                 
68                 protected virtual void OnClearComplete ()
69                 {
70                 }
71                 
72                 protected virtual void OnInsert (int index, object value)
73                 {
74                 }
75                 
76                 protected virtual void OnInsertComplete (int index, object value)
77                 {
78                 }
79                 
80                 protected virtual void OnRemove (int index, object value)
81                 {
82                 }
83                 
84                 protected virtual void OnRemoveComplete (int index, object value)
85                 {
86                 }
87                 
88                 protected virtual void OnValidate (object value)
89                 {
90                         if (value == null)
91                                 throw new ArgumentNullException ("value");
92                 }
93                 #endregion
94                 
95                 #region IStateManager
96                 void IStateManager.LoadViewState (object savedState)
97                 {
98                         if (savedState == null) {
99                                 foreach (IStateManager i in items)
100                                         i.LoadViewState (null);
101                                 return;
102                         }
103
104                         Triplet state = savedState as Triplet;
105                         if (state == null)
106                                 throw new InvalidOperationException ("Internal error.");
107
108                         List <int> indices = state.First as List <int>;
109                         List <object> states = state.Second as List <object>;
110                         List <object> types = state.Third as List <object>;
111                         IList list = this as IList;
112                         IStateManager item;
113                         object t;
114                         
115                         saveEverything = indices == null;
116                         if (saveEverything) {
117                                 items.Clear ();
118
119                                 for (int i = 0; i < states.Count; i++) {
120                                         t = types [i];
121                                         if (t is Type)
122                                                 item = (IStateManager) Activator.CreateInstance ((Type) t);
123                                         else if (t is int)
124                                                 item = (IStateManager) CreateKnownType ((int) t);
125                                         else
126                                                 continue;
127
128                                         item.TrackViewState ();
129                                         item.LoadViewState (states [i]);
130                                         list.Add (item);
131                                 }
132                                 return;
133                         }
134
135                         int idx;
136                         for (int i = 0; i < indices.Count; i++) {
137                                 idx = indices [i];
138
139                                 if (idx < Count) {
140                                         item = list [idx] as IStateManager;
141                                         item.TrackViewState ();
142                                         item.LoadViewState (states [i]);
143                                         continue;
144                                 }
145
146                                 t = types [i];
147
148                                 if (t is Type)
149                                         item = (IStateManager) Activator.CreateInstance ((Type) t);
150                                 else if (t is int)
151                                         item = (IStateManager) CreateKnownType ((int) t);
152                                 else
153                                         continue;
154
155                                 item.TrackViewState ();
156                                 item.LoadViewState (states [i]);
157                                 list.Add (item);
158                         }
159                 }
160                 
161                 void AddListItem <T> (ref List <T> list, T item)
162                 {
163                         if (list == null)
164                                 list = new List <T> ();
165
166                         list.Add (item);
167                 }
168                         
169                 object IStateManager.SaveViewState ()
170                 {
171                         Type[] knownTypes = GetKnownTypes ();
172                         bool haveData = false, haveKnownTypes = knownTypes != null && knownTypes.Length > 0;
173                         int count = items.Count;
174                         IStateManager item;
175                         object itemState;
176                         Type type;
177                         int idx;
178                         List <int> indices = null;
179                         List <object> states = null;
180                         List <object> types = null;
181
182                         for (int i = 0; i < count; i++) {
183                                 item = items [i] as IStateManager;
184                                 if (item == null)
185                                         continue;
186                                 item.TrackViewState ();
187                                 itemState = item.SaveViewState ();
188                                 if (saveEverything || itemState != null) {
189                                         haveData = true;
190                                         type = item.GetType ();
191                                         idx = haveKnownTypes ? Array.IndexOf (knownTypes, type) : -1;
192
193                                         if (!saveEverything)
194                                                 AddListItem <int> (ref indices, i);
195                                         AddListItem <object> (ref states, itemState);
196                                         if (idx == -1)
197                                                 AddListItem <object> (ref types, type);
198                                         else
199                                                 AddListItem <object> (ref types, idx);
200                                 }
201                         }
202
203                         if (!haveData)
204                                 return null;
205
206                         return new Triplet (indices, states, types);
207                 }               
208                 
209                 void IStateManager.TrackViewState ()
210                 {
211                         isTrackingViewState = true;
212                         if (items != null && items.Count > 0) {
213                                 IStateManager item;
214                                 foreach (object o in items) {
215                                         item = o as IStateManager;
216                                         if (item == null)
217                                                 continue;
218                                         item.TrackViewState ();
219                                 }
220                         }
221                 }
222                 
223                 bool isTrackingViewState;
224                 bool IStateManager.IsTrackingViewState {
225                         get { return isTrackingViewState; }
226                 }
227                 #endregion
228                 
229                 #region ICollection, IList, IEnumerable
230                 
231                 public void Clear ()
232                 {
233                         this.OnClear ();
234                         items.Clear ();
235                         this.OnClearComplete ();
236                         
237                         if (isTrackingViewState)
238                                 SetDirty ();
239                 }
240                 
241                 public IEnumerator GetEnumerator ()
242                 {
243                         return items.GetEnumerator ();
244                 }
245                 
246                 public void CopyTo (Array array, int index)
247                 {
248                         items.CopyTo (array, index);
249                 }
250                 
251                 IEnumerator IEnumerable.GetEnumerator ()
252                 {
253                         return GetEnumerator ();
254                 }
255                 
256                 int IList.Add (object value)
257                 {
258                         OnValidate(value);
259                         if (isTrackingViewState) {
260                                 ((IStateManager) value).TrackViewState ();
261                                 SetDirtyObject (value);
262                         }
263                         
264                         OnInsert (-1, value);
265                         items.Add (value);
266                         OnInsertComplete (-1, value);
267                         
268                         return Count - 1;
269                 }
270                 
271                 void IList.Insert (int index, object value)
272                 {
273                         OnValidate(value);
274                         if (isTrackingViewState) {
275                                 ((IStateManager) value).TrackViewState ();
276                                 SetDirty ();
277                         }
278                         
279                         OnInsert (index, value);
280                         items.Insert (index, value);
281                         OnInsertComplete(index, value);
282                 }
283                 
284                 void IList.Remove (object value)
285                 {
286                         if (value == null)
287                                 return;
288                         OnValidate (value);
289                         IList list = (IList)this;
290                         int i = list.IndexOf (value);
291                         if (i >= 0)
292                                 list.RemoveAt (i);
293                 }
294
295                 void IList.RemoveAt (int index)
296                 {
297                         object o = items [index];
298                         
299                         OnRemove (index, o);
300                         items.RemoveAt (index);
301                         OnRemoveComplete(index, o);
302                         
303                         if (isTrackingViewState)
304                                 SetDirty ();
305                 }
306                         
307                 void IList.Clear ()
308                 {
309                         this.Clear ();
310                 }
311                 
312                 bool IList.Contains (object value)
313                 {
314                         if (value == null)
315                                 return false;
316                         
317                         OnValidate (value);
318                         return items.Contains (value);
319                 }
320                 
321                 int IList.IndexOf (object value)
322                 {
323                         if (value == null)
324                                 return -1;
325                         
326                         OnValidate (value);
327                         return items.IndexOf (value);
328                 }
329
330                 public int Count {
331                         get { return items.Count; }
332                 }
333                 
334                 int ICollection.Count {
335                         get { return items.Count; }
336                 }
337                 
338                 bool ICollection.IsSynchronized {
339                         get { return false; }
340                 }
341                 
342                 object ICollection.SyncRoot {
343                         get { return this; }
344                 }
345                 
346                 bool IList.IsFixedSize {
347                         get { return false; }
348                 }
349                 
350                 bool IList.IsReadOnly {
351                         get { return false; }
352                 }
353                 
354                 object IList.this [int index] {
355                         get { return items [index]; }
356                         set {
357                                 if (index < 0 || index >= Count)
358                                         throw new ArgumentOutOfRangeException ("index");
359                                 
360                                 OnValidate (value);
361                                 if (isTrackingViewState) {
362                                         ((IStateManager) value).TrackViewState ();
363                                         SetDirty ();
364                                 }
365                                 
366                                 items [index] = value;
367                         }
368                 }
369                 #endregion
370         }
371 }
372 #endif
373