2 using System.Collections.Generic;
\r
5 using Pithos.Interfaces;
\r
9 static class Extensions
\r
11 public static List<ObjectRecord> ToTree(this IEnumerable<ObjectInfo> enumerable)
\r
13 //Order the items to ensure that children always come after their parents
\r
14 var orderedItems = enumerable.OrderBy(o => o.Uri.ToString());
\r
15 //Each item is stored in lookups
\r
16 var lookups = new Dictionary<string, ObjectRecord>();
\r
18 //RootNodes contains only the root nodes
\r
19 var rootNodes = new List<ObjectRecord>();
\r
21 foreach (var item in orderedItems)
\r
23 var path = item.Uri.ToString();
\r
24 //Calculate the parent path
\r
25 var parentPath = GetParentPath(path);
\r
26 var parentName = GetParentPath(item.Name.ToString());
\r
27 ObjectRecord parent;
\r
30 //First ensure that the parent items exist
\r
32 //We don't want to unescape here
\r
33 var parts = item.Name.ToString().Split('/');
\r
35 if (item.IsDirectory)
\r
37 AddParentNodes(lookups, rootNodes, parts, item);
\r
39 //Store each item using its current path
\r
40 var newNode = new ObjectRecord { DisplayName = parts.Last(), ObjectInfo = item };
\r
41 AddNode(rootNodes, lookups, newNode);
\r
46 //But check to ensure that we DO have it's parent on record
\r
48 if (lookups.TryGetValue(parentPath, out parent))
\r
53 //If the item is directly below its parent container, there is no path to add
\r
54 if (String.IsNullOrWhiteSpace(parentName))
\r
56 //Otherwise we need to add it, because it is missing from the list
\r
57 //Store each item using its current path
\r
58 //Since this is not a directory, we won't add the item itself
\r
59 AddParentNodes(lookups, rootNodes, parts, item);
\r
64 private static void AddNode(List<ObjectRecord> rootNodes, Dictionary<string, ObjectRecord> lookups, ObjectRecord newNode)
\r
66 ObjectRecord parent;
\r
67 var path = newNode.Uri.ToString();
\r
68 var parentPath = GetParentPath(path);
\r
69 lookups[path] = newNode;
\r
71 //If the record is a directory, we need to add it no matter what
\r
73 //If it is a file, we need to check that its parent node exists
\r
74 //If the parent node doesn't exist, we need to add a node for it.
\r
75 //We need to add nodes for all parents recursively,in case they don't exist
\r
77 //Does a parent item exist?
\r
78 if (lookups.TryGetValue(parentPath, out parent))
\r
80 //If so, add the current item under its parent
\r
81 parent.Directories.Add(newNode);
\r
82 parent.Directories.Sort((x, y) => String.CompareOrdinal(x.Uri.ToString(), y.Uri.ToString()));
\r
85 //Otherwise add it to the list of root nodes
\r
86 rootNodes.Add(newNode);
\r
89 private static string GetParentPath(string path)
\r
91 var lastIndex = path.LastIndexOf("/", StringComparison.Ordinal);
\r
94 var parentPath = path.Substring(0, lastIndex);
\r
98 private static void AddParentNodes(Dictionary<string, ObjectRecord> lookups, List<ObjectRecord> rootNodes, string[] parts, ObjectInfo item)
\r
100 for (int i = 0; i < parts.Length - 1; i++)
\r
102 //The parts come from the ObjectInfo URI, therefore they should already be escaped
\r
103 var nodeName = String.Join("/", parts, 0, i + 1);
\r
104 var storageUri = GetStorageUri(item);
\r
105 var nodeKey = String.Format("{0}/{1}/{2}/{3}", storageUri, item.Account, item.Container, nodeName);
\r
106 //If the node was already addeds, skip
\r
107 if (lookups.ContainsKey(nodeKey))
\r
109 var newNode = new ObjectRecord
\r
111 DisplayName = parts[i],
\r
112 ObjectInfo = new ObjectInfo
\r
114 Account = item.Account,
\r
115 Container = item.Container,
\r
116 Name = new Uri(nodeName, UriKind.Relative),
\r
117 StorageUri = item.StorageUri,
\r
118 Content_Type = "application/directory"
\r
121 AddNode(rootNodes, lookups, newNode);
\r
125 private static string GetStorageUri(ObjectInfo item)
\r
127 var storageParts = item.StorageUri.ToString().Split('/');
\r
128 var accountUri = String.Join("/", storageParts, 0, storageParts.Length - 1);
\r