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