Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / Agents / CollectionExtensions.cs @ 126f90b3

History | View | Annotate | Download (7.3 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 b9f5b594 Panagiotis Kanavos
46 b9f5b594 Panagiotis Kanavos
namespace Pithos.Core.Agents
47 b9f5b594 Panagiotis Kanavos
{
48 b9f5b594 Panagiotis Kanavos
    using System;
49 b9f5b594 Panagiotis Kanavos
    using System.Collections.Generic;
50 b9f5b594 Panagiotis Kanavos
    using System.Linq;
51 b9f5b594 Panagiotis Kanavos
    using System.Text;
52 b9f5b594 Panagiotis Kanavos
53 b9f5b594 Panagiotis Kanavos
    /// <summary>
54 b9f5b594 Panagiotis Kanavos
    /// Extension methods for collections
55 b9f5b594 Panagiotis Kanavos
    /// </summary>
56 b9f5b594 Panagiotis Kanavos
    public static class CollectionExtensions
57 b9f5b594 Panagiotis Kanavos
    {
58 b9f5b594 Panagiotis Kanavos
        /// <summary>
59 b9f5b594 Panagiotis Kanavos
        /// Remove the first message in a queue that matches the predicate
60 b9f5b594 Panagiotis Kanavos
        /// </summary>
61 b9f5b594 Panagiotis Kanavos
        /// <param name="predicate">The condition to match</param>
62 b9f5b594 Panagiotis Kanavos
        /// <remarks>Removes the first message that matches the predicate by dequeing all 
63 b9f5b594 Panagiotis Kanavos
        /// messages and re-enqueing all except the first matching message</remarks>
64 b9f5b594 Panagiotis Kanavos
        public static void RemoveFirst<TMessage>(this ConcurrentQueue<TMessage> queue, Func<TMessage, bool> predicate)
65 b9f5b594 Panagiotis Kanavos
        {
66 b9f5b594 Panagiotis Kanavos
            //Can this work? Dequeue all items 
67 b9f5b594 Panagiotis Kanavos
            //and then enqueue everything except the filtered items
68 b9f5b594 Panagiotis Kanavos
69 b9f5b594 Panagiotis Kanavos
            //Possible problems: 
70 b9f5b594 Panagiotis Kanavos
            //* A matching item may be dequeued between one TryDequeue and the next
71 b9f5b594 Panagiotis Kanavos
            var temp = new Queue<TMessage>();
72 b9f5b594 Panagiotis Kanavos
            TMessage message;
73 b9f5b594 Panagiotis Kanavos
            var alreadyFound = false;
74 b9f5b594 Panagiotis Kanavos
            while (queue.TryDequeue(out message))
75 b9f5b594 Panagiotis Kanavos
            {
76 b9f5b594 Panagiotis Kanavos
                if (!predicate(message) || alreadyFound)
77 b9f5b594 Panagiotis Kanavos
                    temp.Enqueue(message);
78 b9f5b594 Panagiotis Kanavos
                else
79 b9f5b594 Panagiotis Kanavos
                {
80 b9f5b594 Panagiotis Kanavos
                    alreadyFound = true;
81 b9f5b594 Panagiotis Kanavos
                }
82 b9f5b594 Panagiotis Kanavos
            }
83 b9f5b594 Panagiotis Kanavos
84 b9f5b594 Panagiotis Kanavos
            queue.AddFromEnumerable(temp);
85 b9f5b594 Panagiotis Kanavos
        }
86 759bd3c4 Panagiotis Kanavos
87 759bd3c4 Panagiotis Kanavos
88 759bd3c4 Panagiotis Kanavos
        public static IEnumerable<ObjectInfo> FilterBelow(this IEnumerable<ObjectInfo> infos,List<Uri> filterUris  )
89 759bd3c4 Panagiotis Kanavos
        {
90 759bd3c4 Panagiotis Kanavos
            if (filterUris == null)
91 759bd3c4 Panagiotis Kanavos
                return infos;
92 759bd3c4 Panagiotis Kanavos
            if (filterUris.Count == 0)
93 759bd3c4 Panagiotis Kanavos
                return infos;
94 fec5da06 Panagiotis Kanavos
            //Allow all objects whose Uris start with any of the filters            
95 759bd3c4 Panagiotis Kanavos
            var filteredUris = from info in infos
96 fec5da06 Panagiotis Kanavos
                                  where filterUris.Any(f => info.Uri.IsAtOrBelow(f)) 
97 fec5da06 Panagiotis Kanavos
                                  select info;            
98 759bd3c4 Panagiotis Kanavos
            return filteredUris;
99 759bd3c4 Panagiotis Kanavos
        }
100 fec5da06 Panagiotis Kanavos
101 fec5da06 Panagiotis Kanavos
        public static IEnumerable<ObjectInfo> FilterDirectlyBelow(this IEnumerable<ObjectInfo> infos,List<Uri> filterUris  )
102 fec5da06 Panagiotis Kanavos
        {
103 fec5da06 Panagiotis Kanavos
            if (filterUris == null)
104 fec5da06 Panagiotis Kanavos
                return infos;
105 fec5da06 Panagiotis Kanavos
            if (filterUris.Count == 0)
106 fec5da06 Panagiotis Kanavos
                return infos;
107 fec5da06 Panagiotis Kanavos
            //Allow all objects whose Uris start with any of the filters            
108 fec5da06 Panagiotis Kanavos
            var filteredUris = from info in infos
109 fec5da06 Panagiotis Kanavos
                                  where filterUris.Any(f => info.Uri.IsAtOrDirectlyBelow(f)) 
110 fec5da06 Panagiotis Kanavos
                                  select info;            
111 fec5da06 Panagiotis Kanavos
            return filteredUris;
112 fec5da06 Panagiotis Kanavos
        }
113 fec5da06 Panagiotis Kanavos
114 fec5da06 Panagiotis Kanavos
        public static bool IsAtOrBelow(this Uri target,Uri root)
115 fec5da06 Panagiotis Kanavos
        {
116 fec5da06 Panagiotis Kanavos
            Contract.Requires(root != null);
117 fec5da06 Panagiotis Kanavos
            Contract.Requires(target != null);
118 fec5da06 Panagiotis Kanavos
119 fec5da06 Panagiotis Kanavos
            var targetSegments = target.Segments;
120 fec5da06 Panagiotis Kanavos
            var rootSegments = root.Segments;
121 fec5da06 Panagiotis Kanavos
122 fec5da06 Panagiotis Kanavos
            return InnerAtOrBelow(targetSegments, rootSegments);
123 fec5da06 Panagiotis Kanavos
        }
124 fec5da06 Panagiotis Kanavos
125 fec5da06 Panagiotis Kanavos
        private static bool InnerAtOrBelow(string[] targetSegments, string[] rootSegments)
126 fec5da06 Panagiotis Kanavos
        {
127 fec5da06 Panagiotis Kanavos
            //If the uri is shorter than the root, no point in comparing
128 fec5da06 Panagiotis Kanavos
            if (targetSegments.Length < rootSegments.Length)
129 fec5da06 Panagiotis Kanavos
                return false;
130 fec5da06 Panagiotis Kanavos
            //If the uri is below the root, it should match the root's segments one by one
131 fec5da06 Panagiotis Kanavos
            //If there is any root segment that doesn't match its corresponding target segment,
132 fec5da06 Panagiotis Kanavos
            //the target is not below the root
133 fec5da06 Panagiotis Kanavos
            var mismatch = rootSegments
134 fec5da06 Panagiotis Kanavos
                .Where((t, i) => !String.Equals(targetSegments[i], t))
135 fec5da06 Panagiotis Kanavos
                .Any();
136 fec5da06 Panagiotis Kanavos
            return !mismatch;
137 fec5da06 Panagiotis Kanavos
        }
138 fec5da06 Panagiotis Kanavos
139 fec5da06 Panagiotis Kanavos
140 fec5da06 Panagiotis Kanavos
        public static bool IsAtOrDirectlyBelow(this Uri target,Uri root)
141 fec5da06 Panagiotis Kanavos
        {
142 fec5da06 Panagiotis Kanavos
            Contract.Requires(root!=null);
143 fec5da06 Panagiotis Kanavos
            Contract.Requires(target!=null);
144 fec5da06 Panagiotis Kanavos
145 fec5da06 Panagiotis Kanavos
            return
146 fec5da06 Panagiotis Kanavos
                //If the target is directly below the root, it will have exactly 
147 fec5da06 Panagiotis Kanavos
                //one segment more than the root            
148 fec5da06 Panagiotis Kanavos
                target.Segments.Length == root.Segments.Length + 1
149 fec5da06 Panagiotis Kanavos
                //Ensure that the candidate target is indeed below the root
150 fec5da06 Panagiotis Kanavos
                && target.IsAtOrBelow(root);
151 fec5da06 Panagiotis Kanavos
        }
152 fec5da06 Panagiotis Kanavos
153 fec5da06 Panagiotis Kanavos
        public static bool IsAtOrBelow(this string targetPath, string rootPath)
154 fec5da06 Panagiotis Kanavos
        {
155 fec5da06 Panagiotis Kanavos
            Contract.Requires(!String.IsNullOrWhiteSpace(targetPath));
156 fec5da06 Panagiotis Kanavos
            Contract.Requires(!String.IsNullOrWhiteSpace(rootPath));
157 fec5da06 Panagiotis Kanavos
158 fec5da06 Panagiotis Kanavos
            var targetSegments = targetPath.Split('\\');
159 fec5da06 Panagiotis Kanavos
            var rootSegments = rootPath.Split('\\');
160 fec5da06 Panagiotis Kanavos
161 fec5da06 Panagiotis Kanavos
            return InnerAtOrBelow(targetSegments, rootSegments);
162 fec5da06 Panagiotis Kanavos
        }
163 fec5da06 Panagiotis Kanavos
164 fec5da06 Panagiotis Kanavos
        public static bool IsAtOrDirectlyBelow(this string targetPath, string rootPath)
165 fec5da06 Panagiotis Kanavos
        {
166 fec5da06 Panagiotis Kanavos
            Contract.Requires(!String.IsNullOrWhiteSpace(targetPath));
167 fec5da06 Panagiotis Kanavos
            Contract.Requires(!String.IsNullOrWhiteSpace(rootPath));
168 fec5da06 Panagiotis Kanavos
169 fec5da06 Panagiotis Kanavos
            var targetSegments = targetPath.Split('\\');
170 fec5da06 Panagiotis Kanavos
            var rootSegments = rootPath.Split('\\');
171 fec5da06 Panagiotis Kanavos
172 fec5da06 Panagiotis Kanavos
            return
173 fec5da06 Panagiotis Kanavos
                //If the target is directly below the root, it will have exactly 
174 fec5da06 Panagiotis Kanavos
                //one segment more than the root            
175 fec5da06 Panagiotis Kanavos
                targetSegments.Length == rootSegments.Length + 1
176 fec5da06 Panagiotis Kanavos
                //Ensure that the candidate target is indeed below the root
177 fec5da06 Panagiotis Kanavos
                && InnerAtOrBelow(targetSegments, rootSegments);
178 fec5da06 Panagiotis Kanavos
        }
179 b9f5b594 Panagiotis Kanavos
    }
180 b9f5b594 Panagiotis Kanavos
}