2 using System.Collections;
3 using System.Collections.Generic;
5 using System.Linq.Expressions;
7 using System.Text.RegularExpressions;
8 using Pithos.Client.WPF.SelectiveSynch;
10 using Pithos.Interfaces;
12 namespace Pithos.Client.WPF.Utils
14 public static class EnumerableExtensions
16 public static IEnumerable<T> Slice<T>(this IEnumerable<T> collection, int start, int end)
21 if (collection == null)
22 throw new ArgumentNullException("collection");
24 // Optimise item count for ICollection interfaces.
25 if (collection is ICollection<T>)
26 count = ((ICollection<T>)collection).Count;
27 else if (collection is ICollection)
28 count = ((ICollection)collection).Count;
31 count = collection.Count();
34 // Get start/end indexes, negative numbers start at the end of the collection.
41 foreach (var item in collection)
53 public static IEnumerable<Node<T>> ToTree<TSource,T>(this IEnumerable<TSource> enumerable,Func<TSource,string> pathFunc,Func<TSource,T> valueFunc,string delimiter="/")
55 var orderedItems=enumerable.OrderBy(pathFunc);
56 var lookups = new Dictionary<string,Node<T>>();
57 var nodes = new List<Node<T>>();
58 foreach (var item in orderedItems)
60 var path = pathFunc(item);
61 var value = valueFunc(item);
62 var newNode = new Node<T> { Path = path,Data=value };
63 lookups[path] = newNode;
65 var lastIndex = path.LastIndexOf(delimiter, StringComparison.Ordinal);
66 var upTo = lastIndex < 0 ? path.Length - 1 : lastIndex;
67 var parentPath = path.Substring(0, upTo);
70 if (lookups.TryGetValue(parentPath, out parent))
72 parent.Children.Add(newNode);
73 parent.Children.Sort((x,y)=>String.CompareOrdinal(x.Path, y.Path));
82 public static List<DirectoryRecord> ToTree(this IEnumerable<ObjectInfo> enumerable)
84 //Order the items to ensure that children always come after their parents
85 var orderedItems=enumerable.OrderBy(o=>o.Uri.ToString());
86 //Each item is stored in lookups
87 var lookups = new Dictionary<string,DirectoryRecord>();
89 //RootNodes contains only the root nodes
90 var rootNodes = new List<DirectoryRecord>();
92 foreach (var item in orderedItems)
94 var path = item.Uri.ToString();
95 //Calculate the parent path
96 var parentPath = GetParentPath(path);
97 var parentName = GetParentPath(item.Name);
98 DirectoryRecord parent;
101 //First ensure that the parent items exist
103 var parts = item.Name.Split('/');
106 if (!item.IsDirectory)
108 //But check to ensure that we DO have it's parent on record
110 if (lookups.TryGetValue(parentPath, out parent))
115 //If the item is directly below its parent container, there is no path to add
116 if (String.IsNullOrWhiteSpace(parentName))
118 //Otherwise we need to add it, because it is missing from the list
119 //Store each item using its current path
120 //Since this is not a directory, we won't add the item itself
121 AddParentNodes(lookups, rootNodes, parts, item);
125 AddParentNodes(lookups, rootNodes, parts, item);
127 //Store each item using its current path
128 var newNode = new DirectoryRecord {DisplayName = parts.Last(), ObjectInfo = item};
129 AddNode(rootNodes, lookups, newNode);
136 private static void AddParentNodes(Dictionary<string, DirectoryRecord> lookups, List<DirectoryRecord> rootNodes, string[] parts, ObjectInfo item)
138 for (int i = 0; i < parts.Length - 1; i++)
140 var nodeName = String.Join("/", parts, 0, i + 1);
141 var storageUri = GetStorageUri(item);
142 var nodeKey = String.Format("{0}/{1}/{2}/{3}", storageUri, item.Account,item.Container, nodeName);
143 //If the node was already addeds, skip
144 if (lookups.ContainsKey(nodeKey))
146 var newNode = new DirectoryRecord
148 DisplayName = parts[i],
149 ObjectInfo = new ObjectInfo
151 Account = item.Account,
152 Container = item.Container,
154 StorageUri=item.StorageUri,
155 Content_Type = "application/directory"
158 AddNode(rootNodes, lookups, newNode);
162 private static string GetStorageUri(ObjectInfo item)
164 var storageParts = item.StorageUri.ToString().Split('/');
165 var accountUri = String.Join("/", storageParts, 0, storageParts.Length - 1);
169 private static void AddNode(List<DirectoryRecord> rootNodes, Dictionary<string, DirectoryRecord> lookups, DirectoryRecord newNode)
171 DirectoryRecord parent;
172 var path = newNode.ObjectInfo.Uri.ToString();
173 var parentPath = GetParentPath(path);
174 lookups[path] = newNode;
176 //If the record is a directory, we need to add it no matter what
178 //If it is a file, we need to check that its parent node exists
179 //If the parent node doesn't exist, we need to add a node for it.
180 //We need to add nodes for all parents recursively,in case they don't exist
182 //Does a parent item exist?
183 if (lookups.TryGetValue(parentPath, out parent))
185 //If so, add the current item under its parent
186 parent.Directories.Add(newNode);
187 parent.Directories.Sort((x, y) => String.CompareOrdinal(x.Uri.ToString(), y.Uri.ToString()));
190 //Otherwise add it to the list of root nodes
191 rootNodes.Add(newNode);
194 private static string GetParentPath(string path)
196 var lastIndex = path.LastIndexOf("/", StringComparison.Ordinal);
199 var parentPath = path.Substring(0, lastIndex);
203 static readonly Regex PascalCaseRegex = new Regex("[a-z][A-Z]", RegexOptions.Compiled);
204 public static string Name(this Enum value)
206 var name = Enum.GetName(value.GetType(), value);
207 return PascalCaseRegex.Replace(name, m => m.Value[0] + " " + char.ToLower(m.Value[1]));