root / trunk / Pithos.Core / Agents / CollectionExtensions.cs @ 8f44fd3a
History | View | Annotate | Download (11 kB)
1 | 255f5f86 | Panagiotis Kanavos | #region |
---|---|---|---|
2 | 255f5f86 | Panagiotis Kanavos | /* ----------------------------------------------------------------------- |
3 | 255f5f86 | Panagiotis Kanavos | * <copyright file="CollectionExtensions.cs" company="GRNet"> |
4 | 255f5f86 | Panagiotis Kanavos | * |
5 | 255f5f86 | Panagiotis Kanavos | * Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 | 255f5f86 | Panagiotis Kanavos | * |
7 | 255f5f86 | Panagiotis Kanavos | * Redistribution and use in source and binary forms, with or |
8 | 255f5f86 | Panagiotis Kanavos | * without modification, are permitted provided that the following |
9 | 255f5f86 | Panagiotis Kanavos | * conditions are met: |
10 | 255f5f86 | Panagiotis Kanavos | * |
11 | 255f5f86 | Panagiotis Kanavos | * 1. Redistributions of source code must retain the above |
12 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
13 | 255f5f86 | Panagiotis Kanavos | * disclaimer. |
14 | 255f5f86 | Panagiotis Kanavos | * |
15 | 255f5f86 | Panagiotis Kanavos | * 2. Redistributions in binary form must reproduce the above |
16 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
17 | 255f5f86 | Panagiotis Kanavos | * disclaimer in the documentation and/or other materials |
18 | 255f5f86 | Panagiotis Kanavos | * provided with the distribution. |
19 | 255f5f86 | Panagiotis Kanavos | * |
20 | 255f5f86 | Panagiotis Kanavos | * |
21 | 255f5f86 | Panagiotis Kanavos | * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 | 255f5f86 | Panagiotis Kanavos | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 | 255f5f86 | Panagiotis Kanavos | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | 255f5f86 | Panagiotis Kanavos | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 | 255f5f86 | Panagiotis Kanavos | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | 255f5f86 | Panagiotis Kanavos | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | 255f5f86 | Panagiotis Kanavos | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 | 255f5f86 | Panagiotis Kanavos | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 | 255f5f86 | Panagiotis Kanavos | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | 255f5f86 | Panagiotis Kanavos | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 | 255f5f86 | Panagiotis Kanavos | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | 255f5f86 | Panagiotis Kanavos | * POSSIBILITY OF SUCH DAMAGE. |
33 | 255f5f86 | Panagiotis Kanavos | * |
34 | 255f5f86 | Panagiotis Kanavos | * The views and conclusions contained in the software and |
35 | 255f5f86 | Panagiotis Kanavos | * documentation are those of the authors and should not be |
36 | 255f5f86 | Panagiotis Kanavos | * interpreted as representing official policies, either expressed |
37 | 255f5f86 | Panagiotis Kanavos | * or implied, of GRNET S.A. |
38 | 255f5f86 | Panagiotis Kanavos | * </copyright> |
39 | 255f5f86 | Panagiotis Kanavos | * ----------------------------------------------------------------------- |
40 | 255f5f86 | Panagiotis Kanavos | */ |
41 | 255f5f86 | Panagiotis Kanavos | #endregion |
42 | b9f5b594 | Panagiotis Kanavos | using System.Collections.Concurrent; |
43 | fec5da06 | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
44 | 759bd3c4 | Panagiotis Kanavos | using Pithos.Interfaces; |
45 | d78d765c | pkanavos | using System; |
46 | d78d765c | pkanavos | using System.Collections.Generic; |
47 | d78d765c | pkanavos | using System.Linq; |
48 | b9f5b594 | Panagiotis Kanavos | |
49 | b9f5b594 | Panagiotis Kanavos | namespace Pithos.Core.Agents |
50 | b9f5b594 | Panagiotis Kanavos | { |
51 | b9f5b594 | Panagiotis Kanavos | |
52 | b9f5b594 | Panagiotis Kanavos | /// <summary> |
53 | b9f5b594 | Panagiotis Kanavos | /// Extension methods for collections |
54 | b9f5b594 | Panagiotis Kanavos | /// </summary> |
55 | b9f5b594 | Panagiotis Kanavos | public static class CollectionExtensions |
56 | b9f5b594 | Panagiotis Kanavos | { |
57 | 92f18b56 | Panagiotis Kanavos | public static IEnumerable<T> Replace<T>(this IEnumerable<T> list,Func<T,bool> match, Func<T,IEnumerable<T>> generate) |
58 | 99e6329f | Panagiotis Kanavos | { |
59 | 99e6329f | Panagiotis Kanavos | foreach (var item in list) |
60 | 99e6329f | Panagiotis Kanavos | { |
61 | 99e6329f | Panagiotis Kanavos | if (match(item)) |
62 | 92f18b56 | Panagiotis Kanavos | foreach (var newItem in generate(item)) |
63 | 99e6329f | Panagiotis Kanavos | { |
64 | 99e6329f | Panagiotis Kanavos | yield return newItem; |
65 | 99e6329f | Panagiotis Kanavos | } |
66 | 99e6329f | Panagiotis Kanavos | else |
67 | 99e6329f | Panagiotis Kanavos | yield return item; |
68 | 99e6329f | Panagiotis Kanavos | } |
69 | 99e6329f | Panagiotis Kanavos | } |
70 | 99e6329f | Panagiotis Kanavos | |
71 | 99e6329f | Panagiotis Kanavos | |
72 | b9f5b594 | Panagiotis Kanavos | /// <summary> |
73 | b9f5b594 | Panagiotis Kanavos | /// Remove the first message in a queue that matches the predicate |
74 | b9f5b594 | Panagiotis Kanavos | /// </summary> |
75 | d78d765c | pkanavos | /// <param name="queue">The queue</param> |
76 | b9f5b594 | Panagiotis Kanavos | /// <param name="predicate">The condition to match</param> |
77 | b9f5b594 | Panagiotis Kanavos | /// <remarks>Removes the first message that matches the predicate by dequeing all |
78 | b9f5b594 | Panagiotis Kanavos | /// messages and re-enqueing all except the first matching message</remarks> |
79 | b9f5b594 | Panagiotis Kanavos | public static void RemoveFirst<TMessage>(this ConcurrentQueue<TMessage> queue, Func<TMessage, bool> predicate) |
80 | b9f5b594 | Panagiotis Kanavos | { |
81 | b9f5b594 | Panagiotis Kanavos | //Can this work? Dequeue all items |
82 | b9f5b594 | Panagiotis Kanavos | //and then enqueue everything except the filtered items |
83 | b9f5b594 | Panagiotis Kanavos | |
84 | b9f5b594 | Panagiotis Kanavos | //Possible problems: |
85 | b9f5b594 | Panagiotis Kanavos | //* A matching item may be dequeued between one TryDequeue and the next |
86 | b9f5b594 | Panagiotis Kanavos | var temp = new Queue<TMessage>(); |
87 | b9f5b594 | Panagiotis Kanavos | TMessage message; |
88 | b9f5b594 | Panagiotis Kanavos | var alreadyFound = false; |
89 | b9f5b594 | Panagiotis Kanavos | while (queue.TryDequeue(out message)) |
90 | b9f5b594 | Panagiotis Kanavos | { |
91 | b9f5b594 | Panagiotis Kanavos | if (!predicate(message) || alreadyFound) |
92 | b9f5b594 | Panagiotis Kanavos | temp.Enqueue(message); |
93 | b9f5b594 | Panagiotis Kanavos | else |
94 | b9f5b594 | Panagiotis Kanavos | { |
95 | b9f5b594 | Panagiotis Kanavos | alreadyFound = true; |
96 | b9f5b594 | Panagiotis Kanavos | } |
97 | b9f5b594 | Panagiotis Kanavos | } |
98 | b9f5b594 | Panagiotis Kanavos | |
99 | b9f5b594 | Panagiotis Kanavos | queue.AddFromEnumerable(temp); |
100 | b9f5b594 | Panagiotis Kanavos | } |
101 | 759bd3c4 | Panagiotis Kanavos | |
102 | 759bd3c4 | Panagiotis Kanavos | |
103 | 99e6329f | Panagiotis Kanavos | /// <summary> |
104 | 99e6329f | Panagiotis Kanavos | /// Return only the info objects that are below one of the filter Uris |
105 | 99e6329f | Panagiotis Kanavos | /// </summary> |
106 | 99e6329f | Panagiotis Kanavos | /// <param name="infos">ObjectInfo items to filter</param> |
107 | 99e6329f | Panagiotis Kanavos | /// <param name="filterUris">List of filter Uris</param> |
108 | 99e6329f | Panagiotis Kanavos | /// <returns>An enumerable of ObjectInfo items. If the list of filter Uris is empty or null, the original list is returned</returns> |
109 | 759bd3c4 | Panagiotis Kanavos | public static IEnumerable<ObjectInfo> FilterBelow(this IEnumerable<ObjectInfo> infos,List<Uri> filterUris ) |
110 | 759bd3c4 | Panagiotis Kanavos | { |
111 | 759bd3c4 | Panagiotis Kanavos | if (filterUris == null) |
112 | 759bd3c4 | Panagiotis Kanavos | return infos; |
113 | 759bd3c4 | Panagiotis Kanavos | if (filterUris.Count == 0) |
114 | 759bd3c4 | Panagiotis Kanavos | return infos; |
115 | fec5da06 | Panagiotis Kanavos | //Allow all objects whose Uris start with any of the filters |
116 | 759bd3c4 | Panagiotis Kanavos | var filteredUris = from info in infos |
117 | fec5da06 | Panagiotis Kanavos | where filterUris.Any(f => info.Uri.IsAtOrBelow(f)) |
118 | fec5da06 | Panagiotis Kanavos | select info; |
119 | 759bd3c4 | Panagiotis Kanavos | return filteredUris; |
120 | 759bd3c4 | Panagiotis Kanavos | } |
121 | fec5da06 | Panagiotis Kanavos | |
122 | 99e6329f | Panagiotis Kanavos | /// <summary> |
123 | 99e6329f | Panagiotis Kanavos | /// Return only the info objects that are directly below one of the filter Uris |
124 | 99e6329f | Panagiotis Kanavos | /// </summary> |
125 | 99e6329f | Panagiotis Kanavos | /// <param name="infos">ObjectInfo items to filter</param> |
126 | 99e6329f | Panagiotis Kanavos | /// <param name="filterUris">List of filter Uris</param> |
127 | 99e6329f | Panagiotis Kanavos | /// <returns>An enumerable of ObjectInfo items. If the list of filter Uris is empty or null, the original list is returned</returns> |
128 | 99e6329f | Panagiotis Kanavos | public static IEnumerable<ObjectInfo> FilterDirectlyBelow(this IEnumerable<ObjectInfo> infos, List<Uri> filterUris) |
129 | fec5da06 | Panagiotis Kanavos | { |
130 | fec5da06 | Panagiotis Kanavos | if (filterUris == null) |
131 | fec5da06 | Panagiotis Kanavos | return infos; |
132 | fec5da06 | Panagiotis Kanavos | if (filterUris.Count == 0) |
133 | fec5da06 | Panagiotis Kanavos | return infos; |
134 | fec5da06 | Panagiotis Kanavos | //Allow all objects whose Uris start with any of the filters |
135 | fec5da06 | Panagiotis Kanavos | var filteredUris = from info in infos |
136 | fec5da06 | Panagiotis Kanavos | where filterUris.Any(f => info.Uri.IsAtOrDirectlyBelow(f)) |
137 | fec5da06 | Panagiotis Kanavos | select info; |
138 | fec5da06 | Panagiotis Kanavos | return filteredUris; |
139 | fec5da06 | Panagiotis Kanavos | } |
140 | fec5da06 | Panagiotis Kanavos | |
141 | 99e6329f | Panagiotis Kanavos | /// <summary> |
142 | 99e6329f | Panagiotis Kanavos | /// Checkes whether a Uri is below a root Uri |
143 | 99e6329f | Panagiotis Kanavos | /// </summary> |
144 | 99e6329f | Panagiotis Kanavos | /// <param name="target"></param> |
145 | 99e6329f | Panagiotis Kanavos | /// <param name="root"></param> |
146 | 99e6329f | Panagiotis Kanavos | /// <returns></returns> |
147 | fec5da06 | Panagiotis Kanavos | public static bool IsAtOrBelow(this Uri target,Uri root) |
148 | fec5da06 | Panagiotis Kanavos | { |
149 | d78d765c | pkanavos | if(root == null) |
150 | d78d765c | pkanavos | throw new ArgumentNullException("root"); |
151 | d78d765c | pkanavos | if(target == null) |
152 | d78d765c | pkanavos | throw new ArgumentNullException("target"); |
153 | d78d765c | pkanavos | Contract.EndContractBlock(); |
154 | fec5da06 | Panagiotis Kanavos | |
155 | fec5da06 | Panagiotis Kanavos | var targetSegments = target.Segments; |
156 | fec5da06 | Panagiotis Kanavos | var rootSegments = root.Segments; |
157 | fec5da06 | Panagiotis Kanavos | |
158 | fec5da06 | Panagiotis Kanavos | return InnerAtOrBelow(targetSegments, rootSegments); |
159 | fec5da06 | Panagiotis Kanavos | } |
160 | fec5da06 | Panagiotis Kanavos | |
161 | fec5da06 | Panagiotis Kanavos | private static bool InnerAtOrBelow(string[] targetSegments, string[] rootSegments) |
162 | fec5da06 | Panagiotis Kanavos | { |
163 | fec5da06 | Panagiotis Kanavos | //If the uri is shorter than the root, no point in comparing |
164 | fec5da06 | Panagiotis Kanavos | if (targetSegments.Length < rootSegments.Length) |
165 | fec5da06 | Panagiotis Kanavos | return false; |
166 | fec5da06 | Panagiotis Kanavos | //If the uri is below the root, it should match the root's segments one by one |
167 | fec5da06 | Panagiotis Kanavos | //If there is any root segment that doesn't match its corresponding target segment, |
168 | fec5da06 | Panagiotis Kanavos | //the target is not below the root |
169 | 1a41e9ec | pkanavos | //DON'T FORGET that Uri segments include the slashes. Must remove them to ensure proper checks |
170 | fec5da06 | Panagiotis Kanavos | var mismatch = rootSegments |
171 | 8f44fd3a | pkanavos | .Where((t, i) => !String.Equals(targetSegments[i].TrimEnd('/'), t.TrimEnd('/'),StringComparison.InvariantCultureIgnoreCase)) |
172 | fec5da06 | Panagiotis Kanavos | .Any(); |
173 | fec5da06 | Panagiotis Kanavos | return !mismatch; |
174 | fec5da06 | Panagiotis Kanavos | } |
175 | fec5da06 | Panagiotis Kanavos | |
176 | fec5da06 | Panagiotis Kanavos | |
177 | 99e6329f | Panagiotis Kanavos | /// <summary> |
178 | 99e6329f | Panagiotis Kanavos | /// Checks whether a Uri is directly below a root Uri |
179 | 99e6329f | Panagiotis Kanavos | /// </summary> |
180 | 99e6329f | Panagiotis Kanavos | /// <param name="target"></param> |
181 | 99e6329f | Panagiotis Kanavos | /// <param name="root"></param> |
182 | 99e6329f | Panagiotis Kanavos | /// <returns></returns> |
183 | fec5da06 | Panagiotis Kanavos | public static bool IsAtOrDirectlyBelow(this Uri target,Uri root) |
184 | fec5da06 | Panagiotis Kanavos | { |
185 | d78d765c | pkanavos | if (root==null) |
186 | d78d765c | pkanavos | throw new ArgumentNullException("root"); |
187 | d78d765c | pkanavos | if (target==null) |
188 | d78d765c | pkanavos | throw new ArgumentNullException("target"); |
189 | d78d765c | pkanavos | Contract.EndContractBlock(); |
190 | fec5da06 | Panagiotis Kanavos | |
191 | 1a41e9ec | pkanavos | if (target.Equals(root)) |
192 | 1a41e9ec | pkanavos | return true; |
193 | fec5da06 | Panagiotis Kanavos | return |
194 | fec5da06 | Panagiotis Kanavos | //If the target is directly below the root, it will have exactly |
195 | fec5da06 | Panagiotis Kanavos | //one segment more than the root |
196 | fec5da06 | Panagiotis Kanavos | target.Segments.Length == root.Segments.Length + 1 |
197 | fec5da06 | Panagiotis Kanavos | //Ensure that the candidate target is indeed below the root |
198 | fec5da06 | Panagiotis Kanavos | && target.IsAtOrBelow(root); |
199 | fec5da06 | Panagiotis Kanavos | } |
200 | fec5da06 | Panagiotis Kanavos | |
201 | 99e6329f | Panagiotis Kanavos | /// <summary> |
202 | 99e6329f | Panagiotis Kanavos | /// Checkes whether a file path is below a root path |
203 | 99e6329f | Panagiotis Kanavos | /// </summary> |
204 | 99e6329f | Panagiotis Kanavos | /// <param name="targetPath"></param> |
205 | 99e6329f | Panagiotis Kanavos | /// <param name="rootPath"></param> |
206 | 99e6329f | Panagiotis Kanavos | /// <returns></returns> |
207 | fec5da06 | Panagiotis Kanavos | public static bool IsAtOrBelow(this string targetPath, string rootPath) |
208 | fec5da06 | Panagiotis Kanavos | { |
209 | d78d765c | pkanavos | if(String.IsNullOrWhiteSpace(targetPath)) |
210 | d78d765c | pkanavos | throw new ArgumentNullException("targetPath"); |
211 | d78d765c | pkanavos | if(String.IsNullOrWhiteSpace(rootPath)) |
212 | d78d765c | pkanavos | throw new ArgumentNullException("rootPath"); |
213 | d78d765c | pkanavos | Contract.EndContractBlock(); |
214 | fec5da06 | Panagiotis Kanavos | |
215 | fec5da06 | Panagiotis Kanavos | var targetSegments = targetPath.Split('\\'); |
216 | fec5da06 | Panagiotis Kanavos | var rootSegments = rootPath.Split('\\'); |
217 | fec5da06 | Panagiotis Kanavos | |
218 | fec5da06 | Panagiotis Kanavos | return InnerAtOrBelow(targetSegments, rootSegments); |
219 | fec5da06 | Panagiotis Kanavos | } |
220 | fec5da06 | Panagiotis Kanavos | |
221 | 99e6329f | Panagiotis Kanavos | /// <summary> |
222 | 99e6329f | Panagiotis Kanavos | /// Checks whether a file path is directly below a root path |
223 | 99e6329f | Panagiotis Kanavos | /// </summary> |
224 | 99e6329f | Panagiotis Kanavos | /// <param name="targetPath"></param> |
225 | 99e6329f | Panagiotis Kanavos | /// <param name="rootPath"></param> |
226 | 99e6329f | Panagiotis Kanavos | /// <returns></returns> |
227 | fec5da06 | Panagiotis Kanavos | public static bool IsAtOrDirectlyBelow(this string targetPath, string rootPath) |
228 | fec5da06 | Panagiotis Kanavos | { |
229 | d78d765c | pkanavos | if (String.IsNullOrWhiteSpace(targetPath)) |
230 | d78d765c | pkanavos | throw new ArgumentNullException("targetPath"); |
231 | d78d765c | pkanavos | if (String.IsNullOrWhiteSpace(rootPath)) |
232 | d78d765c | pkanavos | throw new ArgumentNullException("rootPath"); |
233 | d78d765c | pkanavos | Contract.EndContractBlock(); |
234 | d78d765c | pkanavos | |
235 | 1a41e9ec | pkanavos | if (targetPath==rootPath) |
236 | 1a41e9ec | pkanavos | return true; |
237 | fec5da06 | Panagiotis Kanavos | var targetSegments = targetPath.Split('\\'); |
238 | fec5da06 | Panagiotis Kanavos | var rootSegments = rootPath.Split('\\'); |
239 | fec5da06 | Panagiotis Kanavos | |
240 | fec5da06 | Panagiotis Kanavos | return |
241 | fec5da06 | Panagiotis Kanavos | //If the target is directly below the root, it will have exactly |
242 | fec5da06 | Panagiotis Kanavos | //one segment more than the root |
243 | fec5da06 | Panagiotis Kanavos | targetSegments.Length == rootSegments.Length + 1 |
244 | fec5da06 | Panagiotis Kanavos | //Ensure that the candidate target is indeed below the root |
245 | fec5da06 | Panagiotis Kanavos | && InnerAtOrBelow(targetSegments, rootSegments); |
246 | fec5da06 | Panagiotis Kanavos | } |
247 | 62d5b25f | Panagiotis Kanavos | |
248 | 62d5b25f | Panagiotis Kanavos | /// <summary> |
249 | 62d5b25f | Panagiotis Kanavos | /// Returns the part of the target string that comes after the prefix string. |
250 | 62d5b25f | Panagiotis Kanavos | /// The target is not modified if it doesn't start with the prefix string |
251 | 62d5b25f | Panagiotis Kanavos | /// </summary> |
252 | 62d5b25f | Panagiotis Kanavos | /// <param name="target"></param> |
253 | d78d765c | pkanavos | /// <param name="prefix"></param> |
254 | 62d5b25f | Panagiotis Kanavos | /// <returns></returns> |
255 | 62d5b25f | Panagiotis Kanavos | public static string After(this string target,string prefix) |
256 | 62d5b25f | Panagiotis Kanavos | { |
257 | 62d5b25f | Panagiotis Kanavos | //If the prefix or the target are empty, return the target |
258 | 62d5b25f | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(prefix) || String.IsNullOrWhiteSpace(target)) |
259 | 62d5b25f | Panagiotis Kanavos | return target; |
260 | 62d5b25f | Panagiotis Kanavos | if (target.StartsWith(prefix)) |
261 | 62d5b25f | Panagiotis Kanavos | return target.Remove(0,prefix.Length); |
262 | 62d5b25f | Panagiotis Kanavos | return target; |
263 | 62d5b25f | Panagiotis Kanavos | } |
264 | b9f5b594 | Panagiotis Kanavos | } |
265 | 62d5b25f | Panagiotis Kanavos | |
266 | 62d5b25f | Panagiotis Kanavos | |
267 | b9f5b594 | Panagiotis Kanavos | } |