2005-05-26 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI.WebControls / PagedDataSource.cs
1
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 /**
23  * Namespace: System.Web.UI.WebControls
24  * Class:     PagedDataSource
25  *
26  * Author:  Gaurav Vaish
27  * Maintainer: gvaish@iitk.ac.in
28  * Contact: <my_scripts2001@yahoo.com>, <gvaish@iitk.ac.in>
29  * Implementation: yes
30  * Status:  100%
31  *
32  * (C) Gaurav Vaish (2002)
33  */
34
35 using System;
36 using System.ComponentModel;
37 using System.Collections;
38 using System.Web;
39 using System.Web.UI;
40
41 namespace System.Web.UI.WebControls
42 {
43         public sealed class PagedDataSource : ICollection, IEnumerable, ITypedList
44         {
45                 private int  pageSize;
46                 private bool allowPaging;
47                 private int  currentPageIndex;
48                 private bool allowCustomPaging;
49                 private int  virtualCount;
50                 
51 #if NET_2_0
52                 DataSourceSelectArguments arguments;
53                 DataSourceView view;
54                 bool serverPaging;
55 #endif
56
57                 private IEnumerable dataSource;
58
59                 public PagedDataSource()
60                 {
61                         Initialize();
62                 }
63
64                 private void Initialize()
65                 {
66                         pageSize          = 10;
67                         allowPaging       = false;
68                         currentPageIndex  = 0;
69                         allowCustomPaging = false;
70                         virtualCount      = 0;
71                 }
72
73 #if NET_2_0
74                 public DataSourceSelectArguments DataSourceSelectArguments {
75                         get { return arguments; }
76                         set { arguments = value; }
77                 }
78
79                 public DataSourceView DataSourceView {
80                         get { return view; }
81                         set { view = value; }
82                 }
83
84                 public bool AllowServerPaging {
85                         get { return serverPaging; }
86                         set { serverPaging = value; }
87                 }
88                 
89                 public bool IsServerPagingEnabled {
90                         get { return allowPaging && serverPaging; }
91                 }
92                 
93                 public void SetItemCountFromPageIndex (int highestPageIndex)
94                 {
95                         arguments.StartRowIndex = CurrentPageIndex * PageSize;
96                         arguments.MaximumRows = (highestPageIndex - CurrentPageIndex) * PageSize + 1;
97                         IEnumerable data = view.ExecuteSelect (arguments);
98                         
99                         virtualCount = CurrentPageIndex * PageSize;
100                         if (data is ICollection) {
101                                 virtualCount += ((ICollection)data).Count;
102                         } else {
103                                 IEnumerator e = data.GetEnumerator ();
104                                 while (e.MoveNext())
105                                         virtualCount++;
106                         }
107                 }
108
109 #endif
110
111                 public bool AllowCustomPaging
112                 {
113                         get
114                         {
115                                 return allowCustomPaging;
116                         }
117                         set
118                         {
119                                 allowCustomPaging = value;
120                         }
121                 }
122
123                 public bool AllowPaging
124                 {
125                         get
126                         {
127                                 return allowPaging;
128                         }
129                         set
130                         {
131                                 allowPaging = value;
132                         }
133                 }
134
135                 public int Count
136                 {
137                         get
138                         {
139                                 if(dataSource != null)
140                                 {
141                                         if(!IsPagingEnabled)
142                                         {
143                                                 return DataSourceCount;
144                                         }
145                                         if(IsCustomPagingEnabled)
146                                         {
147                                                 return pageSize;
148                                         }
149                                         
150                                         if(IsLastPage)
151                                         {
152                                                 int n = DataSourceCount;
153                                                 if (n == 0) return 0;
154                                                 else return (n - FirstIndexInPage);
155                                         }
156                                         return pageSize;
157                                 }
158                                 return 0;
159                         }
160                 }
161
162                 public int CurrentPageIndex
163                 {
164                         get
165                         {
166                                 return currentPageIndex;
167                         }
168
169                         set
170                         {
171                                 currentPageIndex = value;
172                         }
173                 }
174
175                 public IEnumerable DataSource
176                 {
177                         get
178                         {
179                                 return dataSource;
180                         }
181                         set
182                         {
183                                 dataSource = value;
184                         }
185                 }
186
187                 public int DataSourceCount
188                 {
189                         get
190                         {
191                                 if(dataSource != null)
192                                 {
193 #if NET_2_0
194                                         if (serverPaging)
195                                         {
196                                                 return virtualCount;
197                                         }
198 #endif
199                                         if(IsCustomPagingEnabled)
200                                         {
201                                                 return virtualCount;
202                                         }
203                                         if(dataSource is ICollection)
204                                         {
205                                                 return ((ICollection)dataSource).Count;
206                                         }
207                                         throw new HttpException(HttpRuntime.FormatResourceString("PagedDataSource_Cannot_Get_Count"));
208                                 }
209                                 return 0;
210                         }
211                 }
212
213                 public int FirstIndexInPage
214                 {
215                         get
216                         {
217                                 if(dataSource != null && IsPagingEnabled && !IsCustomPagingEnabled)
218                                 {
219                                         return (currentPageIndex * pageSize);
220                                 }
221                                 return 0;
222                         }
223                 }
224
225                 public bool IsCustomPagingEnabled
226                 {
227                         get
228                         {
229                                 return (IsPagingEnabled && allowCustomPaging);
230                         }
231                 }
232
233                 public bool IsFirstPage
234                 {
235                         get
236                         {
237                                 return (!IsPagingEnabled || (CurrentPageIndex == 0));
238                         }
239                 }
240
241                 public bool IsLastPage
242                 {
243                         get
244                         {
245                                 return (!IsPagingEnabled || (CurrentPageIndex == (PageCount - 1)) || PageCount <= 1);
246                         }
247                 }
248
249                 public bool IsPagingEnabled
250                 {
251                         get
252                         {
253                                 return (allowPaging && pageSize != 0);
254                         }
255                 }
256
257                 public bool IsReadOnly
258                 {
259                         get
260                         {
261                                 return false;
262                         }
263                 }
264
265                 public bool IsSynchronized
266                 {
267                         get
268                         {
269                                 return false;
270                         }
271                 }
272
273                 public int PageCount
274                 {
275                         get
276                         {
277                                 if(dataSource != null) {
278                                         if(!IsPagingEnabled)
279                                                 return 1;
280                                         
281                                         int total = (DataSourceCount + pageSize - 1) / pageSize;
282                                         return (total > 0 ? total : 1);
283                                 }
284                                 return 0;
285                         }
286                 }
287
288                 public int PageSize
289                 {
290                         get
291                         {
292                                 return pageSize;
293                         }
294                         set
295                         {
296                                 pageSize = value;
297                         }
298                 }
299
300                 public object SyncRoot
301                 {
302                         get
303                         {
304                                 return this;
305                         }
306                 }
307
308                 public int VirtualCount
309                 {
310                         get
311                         {
312                                 return virtualCount;
313                         }
314                         set
315                         {
316                                 virtualCount = value;
317                         }
318                 }
319                 
320                 public void CopyTo(Array array, int index)
321                 {
322                         IEnumerator enumerator = this.GetEnumerator();
323                         if(enumerator == null) return;
324
325                         while(enumerator.MoveNext())
326                                 array.SetValue(enumerator.Current, index++);
327                 }
328
329                 public IEnumerator GetEnumerator()
330                 {
331 #if NET_2_0
332                         int fInd = serverPaging ? 0 : FirstIndexInPage;
333 #else
334                         int fInd = FirstIndexInPage;
335 #endif
336                         int count = -1;
337
338                         if(dataSource is ICollection)
339                         {
340                                 count = Count;
341                         }
342
343                         if(dataSource is IList)
344                         {
345                                 return (new PrivateListEnumerator((IList)dataSource, fInd, count));
346                         }
347                         if(dataSource is Array)
348                         {
349                                 return (new PrivateArrayEnumerator((object[])dataSource, fInd, count));
350                         }
351                         if(dataSource is ICollection)
352                         {
353                                 return (new PrivateICollectionEnumerator((ICollection)dataSource, fInd, count));
354                         }
355                         if(allowCustomPaging)
356                         {
357                                 return (new PrivateIEnumeratorEnumerator(dataSource.GetEnumerator(), Count));
358                         }
359                         return dataSource.GetEnumerator();
360                 }
361
362                 class PrivateIEnumeratorEnumerator : IEnumerator
363                 {
364                         private int index;
365                         private int max;
366
367                         private IEnumerator enumerator;
368
369                         public PrivateIEnumeratorEnumerator(IEnumerator enumerator, int count)
370                         {
371                                 this.enumerator = enumerator;
372                                 index = -1;
373                                 max   = count;
374                         }
375
376                         public bool MoveNext()
377                         {
378                                 enumerator.MoveNext();
379                                 index++;
380                                 return (index < max);
381                         }
382
383                         public void Reset()
384                         {
385                                 index = -1;
386                                 enumerator.Reset();
387                         }
388
389                         public object Current
390                         {
391                                 get
392                                 {
393                                         return enumerator.Current;
394                                 }
395                         }
396                 }
397
398                 class PrivateICollectionEnumerator : IEnumerator
399                 {
400                         private int index;
401                         private int start;
402                         private int max;
403
404                         private ICollection collection;
405                         private IEnumerator collEnum;
406
407                         public PrivateICollectionEnumerator(ICollection collection, int start, int count)
408                         {
409                                 this.collection = collection;
410                                 this.start  = start;
411                                 index = -1;
412                                 max = start + count;
413                                 if(max > collection.Count)
414                                 {
415                                         max = collection.Count;
416                                 }
417                         }
418
419                         public bool MoveNext()
420                         {
421                                 if(collEnum == null)
422                                 {
423                                         int cIndex = 0;
424                                         collEnum = collection.GetEnumerator();
425                                         while(cIndex < start)
426                                         {
427                                                 collEnum.MoveNext();
428                                                 cIndex++;
429                                         }
430                                 }
431                                 collEnum.MoveNext();
432                                 index++;
433                                 return (start + index < max);
434                         }
435
436                         public void Reset()
437                         {
438                                 index = -1;
439                                 collEnum = null;
440                         }
441
442                         public object Current
443                         {
444                                 get
445                                 {
446                                         return collEnum.Current;
447                                 }
448                         }
449                 }
450
451                 class PrivateArrayEnumerator : IEnumerator
452                 {
453                         private int index;
454                         private int start;
455                         private int max;
456                         private object[] values;
457
458                         public PrivateArrayEnumerator(object[] values, int start, int count)
459                         {
460                                 this.values = values;
461                                 this.start  = start;
462                                 index = -1;
463                                 max = start + count;
464                                 if(max > this.values.Length)
465                                 {
466                                         max = this.values.Length;
467                                 }
468                         }
469
470                         public bool MoveNext()
471                         {
472                                 index++;
473                                 return (index + start < max);
474                         }
475
476                         public void Reset()
477                         {
478                                 index = -1;
479                         }
480
481                         public object Current
482                         {
483                                 get
484                                 {
485                                         if(index >= 0)
486                                         {
487                                                 return values[index + start];
488                                         }
489                                         throw new InvalidOperationException("Enumerator_MoveNext_Not_Called");
490                                 }
491                         }
492                 }
493
494                 class PrivateListEnumerator : IEnumerator
495                 {
496                         private int   index;
497                         private int   start;
498                         private int   max;
499                         private IList collection;
500
501                         public PrivateListEnumerator(IList list, int start, int count)
502                         {
503                                 collection = list;
504                                 this.start = start;
505                                 index = -1;
506                                 max = start + count;
507                                 if(max > list.Count)
508                                 {
509                                         max = list.Count;
510                                 }
511                         }
512
513                         public bool MoveNext()
514                         {
515                                 index++;
516                                 return (index + start < max);
517                         }
518
519                         public void Reset()
520                         {
521                                 index = -1;
522                         }
523
524                         public object Current
525                         {
526                                 get
527                                 {
528                                         if(index >= 0)
529                                         {
530                                                 return collection[index + start];
531                                         }
532                                         throw new InvalidOperationException("Enumerator_MoveNext_Not_Called");
533                                 }
534                         }
535                 }
536
537                 public string GetListName(PropertyDescriptor[] listAccessors)
538                 {
539                         return String.Empty;
540                 }
541
542                 public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
543                 {
544                         if(dataSource != null)
545                         {
546                                 if(dataSource is ITypedList)
547                                 {
548                                         return ((ITypedList)dataSource).GetItemProperties(listAccessors);
549                                 }
550                         }
551                         return null;
552                 }
553         }
554 }