#region /* ----------------------------------------------------------------------- * * * Copyright 2011-2012 GRNET S.A. All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and * documentation are those of the authors and should not be * interpreted as representing official policies, either expressed * or implied, of GRNET S.A. * * ----------------------------------------------------------------------- */ #endregion using System.Collections.Concurrent; using System.Diagnostics.Contracts; using Pithos.Interfaces; namespace Pithos.Core.Agents { using System; using System.Collections.Generic; using System.Linq; using System.Text; /// /// Extension methods for collections /// public static class CollectionExtensions { /// /// Remove the first message in a queue that matches the predicate /// /// The condition to match /// Removes the first message that matches the predicate by dequeing all /// messages and re-enqueing all except the first matching message public static void RemoveFirst(this ConcurrentQueue queue, Func predicate) { //Can this work? Dequeue all items //and then enqueue everything except the filtered items //Possible problems: //* A matching item may be dequeued between one TryDequeue and the next var temp = new Queue(); TMessage message; var alreadyFound = false; while (queue.TryDequeue(out message)) { if (!predicate(message) || alreadyFound) temp.Enqueue(message); else { alreadyFound = true; } } queue.AddFromEnumerable(temp); } public static IEnumerable FilterBelow(this IEnumerable infos,List filterUris ) { if (filterUris == null) return infos; if (filterUris.Count == 0) return infos; //Allow all objects whose Uris start with any of the filters var filteredUris = from info in infos where filterUris.Any(f => info.Uri.IsAtOrBelow(f)) select info; return filteredUris; } public static IEnumerable FilterDirectlyBelow(this IEnumerable infos,List filterUris ) { if (filterUris == null) return infos; if (filterUris.Count == 0) return infos; //Allow all objects whose Uris start with any of the filters var filteredUris = from info in infos where filterUris.Any(f => info.Uri.IsAtOrDirectlyBelow(f)) select info; return filteredUris; } public static bool IsAtOrBelow(this Uri target,Uri root) { Contract.Requires(root != null); Contract.Requires(target != null); var targetSegments = target.Segments; var rootSegments = root.Segments; return InnerAtOrBelow(targetSegments, rootSegments); } private static bool InnerAtOrBelow(string[] targetSegments, string[] rootSegments) { //If the uri is shorter than the root, no point in comparing if (targetSegments.Length < rootSegments.Length) return false; //If the uri is below the root, it should match the root's segments one by one //If there is any root segment that doesn't match its corresponding target segment, //the target is not below the root var mismatch = rootSegments .Where((t, i) => !String.Equals(targetSegments[i], t)) .Any(); return !mismatch; } public static bool IsAtOrDirectlyBelow(this Uri target,Uri root) { Contract.Requires(root!=null); Contract.Requires(target!=null); return //If the target is directly below the root, it will have exactly //one segment more than the root target.Segments.Length == root.Segments.Length + 1 //Ensure that the candidate target is indeed below the root && target.IsAtOrBelow(root); } public static bool IsAtOrBelow(this string targetPath, string rootPath) { Contract.Requires(!String.IsNullOrWhiteSpace(targetPath)); Contract.Requires(!String.IsNullOrWhiteSpace(rootPath)); var targetSegments = targetPath.Split('\\'); var rootSegments = rootPath.Split('\\'); return InnerAtOrBelow(targetSegments, rootSegments); } public static bool IsAtOrDirectlyBelow(this string targetPath, string rootPath) { Contract.Requires(!String.IsNullOrWhiteSpace(targetPath)); Contract.Requires(!String.IsNullOrWhiteSpace(rootPath)); var targetSegments = targetPath.Split('\\'); var rootSegments = rootPath.Split('\\'); return //If the target is directly below the root, it will have exactly //one segment more than the root targetSegments.Length == rootSegments.Length + 1 //Ensure that the candidate target is indeed below the root && InnerAtOrBelow(targetSegments, rootSegments); } } }