53325caf1c35a66f0783eaaf2d13c6e6e847c4c5
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / Edm / FilteredReadOnlyMetadataCollection.cs
1 //---------------------------------------------------------------------
2 // <copyright file="FilteredReadOnlyMetadataCollection.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.Collections;
12 using System.Collections.Generic;
13 using System.Collections.ObjectModel;
14 using System.Data.Common;
15 using System.Diagnostics;
16 using System.Reflection;
17 using System.Text;
18
19 namespace System.Data.Metadata.Edm
20 {
21     internal interface IBaseList<T> : IList
22     {
23         T this[string identity] { get;}
24
25         new T this[int index] { get;}
26
27         int IndexOf(T item);
28     }
29
30 #pragma warning disable 1711 // compiler 
31     /// <summary>
32     /// Class to filter stuff out from a metadata collection
33     /// </summary>
34     /* 
35
36
37 */
38     internal class FilteredReadOnlyMetadataCollection<TDerived, TBase> : ReadOnlyMetadataCollection<TDerived>, IBaseList<TBase>
39                 where TDerived : TBase 
40                 where TBase : MetadataItem
41     {
42         #region Constructors
43         /// <summary>
44         /// The constructor for constructing a read-only metadata collection to wrap another MetadataCollection.
45         /// </summary>
46         /// <param name="collection">The metadata collection to wrap</param>
47         /// <exception cref="System.ArgumentNullException">Thrown if collection argument is null</exception>
48         /// <param name="predicate">Predicate method which determines membership</param>
49         internal FilteredReadOnlyMetadataCollection(ReadOnlyMetadataCollection<TBase> collection, Predicate<TBase> predicate) : base(FilterCollection(collection, predicate))
50         {
51             Debug.Assert(collection != null);
52             Debug.Assert(collection.IsReadOnly, "wrappers should only be created once loading is over, and this collection is still loading");
53             _source = collection;
54             _predicate = predicate;
55
56         }
57         #endregion
58
59         #region Private Fields
60         // The original metadata collection over which this filtered collection is the view
61         private readonly ReadOnlyMetadataCollection<TBase> _source;
62         private readonly Predicate<TBase> _predicate;
63         #endregion
64
65         #region Properties
66
67         /// <summary>
68         /// Gets an item from the collection with the given identity
69         /// </summary>
70         /// <param name="identity">The identity of the item to search for</param>
71         /// <returns>An item from the collection</returns>
72         /// <exception cref="System.ArgumentNullException">Thrown if identity argument passed in is null</exception>
73         /// <exception cref="System.NotSupportedException">Thrown if setter is called</exception>
74         public override TDerived this[string identity]
75         {
76             get
77             {
78                 TBase item = _source[identity];
79                 if (_predicate(item))
80                 {
81                     return (TDerived)item; 
82                 }
83                 throw EntityUtil.ItemInvalidIdentity(identity, "identity");
84             }
85         }
86
87         #endregion
88
89         #region Methods
90         /// <summary>
91         /// Gets an item from the collection with the given identity
92         /// </summary>
93         /// <param name="identity">The identity of the item to search for</param>
94         /// <param name="ignoreCase">Whether case is ignore in the search</param>
95         /// <returns>An item from the collection</returns>
96         /// <exception cref="System.ArgumentNullException">Thrown if identity argument passed in is null</exception>
97         /// <exception cref="System.ArgumentException">Thrown if the Collection does not have an item with the given identity</exception>
98         public override TDerived GetValue(string identity, bool ignoreCase)
99         {
100             TBase item = _source.GetValue(identity, ignoreCase);
101
102             if (_predicate(item))
103             {
104                 return (TDerived)item;
105             }
106             throw EntityUtil.ItemInvalidIdentity(identity, "identity");
107         }
108
109         /// <summary>
110         /// Determines if this collection contains an item of the given identity
111         /// </summary>
112         /// <param name="identity">The identity of the item to check for</param>
113         /// <returns>True if the collection contains the item with the given identity</returns>
114         /// <exception cref="System.ArgumentNullException">Thrown if identity argument passed in is null</exception>
115         /// <exception cref="System.ArgumentException">Thrown if identity argument passed in is empty string</exception>
116         public override bool Contains(string identity)
117         {
118             TBase item;
119             if (_source.TryGetValue(identity, false/*ignoreCase*/, out item))
120             {
121                 return (_predicate(item));
122             }
123             return false;
124         }
125
126         /// <summary>
127         /// Gets an item from the collection with the given identity
128         /// </summary>
129         /// <param name="identity">The identity of the item to search for</param>
130         /// <param name="ignoreCase">Whether case is ignore in the search</param>
131         /// <param name="item">An item from the collection, null if the item is not found</param>
132         /// <returns>True an item is retrieved</returns>
133         /// <exception cref="System.ArgumentNullException">if identity argument is null</exception>
134         public override bool TryGetValue(string identity, bool ignoreCase, out TDerived item)
135         {
136             item = null; 
137             TBase baseTypeItem;
138             if (_source.TryGetValue(identity, ignoreCase, out baseTypeItem))
139             {
140                 if (_predicate(baseTypeItem))
141                 {
142                     item = (TDerived)baseTypeItem;
143                     return true;
144                 }
145             }
146             return false;
147         }
148
149         internal static List<TDerived> FilterCollection(ReadOnlyMetadataCollection<TBase> collection, Predicate<TBase> predicate)
150         {
151             List<TDerived> list = new List<TDerived>(collection.Count);
152             foreach (TBase item in collection)
153             {
154                 if (predicate(item))
155                 {
156                     list.Add((TDerived)item);
157                 }
158             }
159
160             return list;
161         }
162
163         /// <summary>
164         /// Get index of the element passed as the argument
165         /// </summary>
166         /// <param name="value"></param>
167         /// <returns></returns>
168         public override int IndexOf(TDerived value)
169         {
170             TBase item;
171             if (_source.TryGetValue(value.Identity, false /*ignoreCase*/, out item))
172             {
173                 if (_predicate(item))
174                 {
175                     // Since we are gauranteed to have a unique identity per collection, this item must of T Type
176                     return base.IndexOf((TDerived)item);
177                 }
178             }
179             return -1;
180         }
181
182         #endregion
183
184         #region IBaseList<TBaseItem> Members
185
186         TBase IBaseList<TBase>.this[string identity]
187         {
188             get { return this[identity]; }
189         }
190
191         TBase IBaseList<TBase>.this[int index]
192         {
193             get
194             {
195                 return this[index];
196             }
197         }
198
199         /// <summary>
200         /// Get index of the element passed as the argument
201         /// </summary>
202         /// <param name="item"></param>
203         /// <returns></returns>
204         int IBaseList<TBase>.IndexOf(TBase item)
205         {
206             if (_predicate(item))
207             {
208                 return this.IndexOf((TDerived)item);
209             }
210
211             return -1;
212         }
213
214         #endregion
215     }
216 #pragma warning restore 1711
217 }