+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Pithos.Client.WPF.SelectiveSynch;
+using Pithos.Interfaces;
+using Pithos.Network;
+
+namespace Pithos.Client.WPF.Utils
+{
+ public static class SelectiveExtensions
+ {
+ public static List<DirectoryRecord> LocalFolders(string accountName, string accountPath,string storageUrl)
+ {
+ var storageUri = storageUrl.EndsWith("/")
+ ? new Uri(storageUrl)
+ : new Uri(storageUrl + "/");
+
+ var cacheFolder = Path.Combine(accountPath, FolderConstants.CacheFolder);
+
+ var dir = new DirectoryInfo(accountPath);
+ var orderedItems = from directory in dir.EnumerateDirectories("*", SearchOption.AllDirectories)
+ where !directory.FullName.StartsWith(cacheFolder,StringComparison.InvariantCultureIgnoreCase)
+ orderby directory.FullName
+ let relativeUrl=directory.WithProperCapitalization().AsRelativeUrlTo(accountPath)
+ let dirUri = new Uri(storageUri, relativeUrl)
+ select new DirectoryRecord { DisplayName = directory.Name,Uri=dirUri};
+
+
+ return orderedItems.ToList();
+
+/*
+ //Order the items to ensure that children always come after their parents
+ var lookups = new Dictionary<string, DirectoryRecord>();
+
+ //RootNodes contains only the root nodes
+ var rootNodes = new List<DirectoryRecord>();
+
+ foreach (var newNode in orderedItems)
+ {
+ AddNode(rootNodes, lookups, newNode);
+ }
+ return rootNodes;
+*/
+ }
+ public static List<DirectoryRecord> ToTree(this IEnumerable<ObjectInfo> enumerable)
+ {
+ //Order the items to ensure that children always come after their parents
+ var orderedItems = enumerable.OrderBy(o => o.Uri.ToString());
+ //Each item is stored in lookups
+ var lookups = new Dictionary<string, DirectoryRecord>();
+
+ //RootNodes contains only the root nodes
+ var rootNodes = new List<DirectoryRecord>();
+
+ foreach (var item in orderedItems)
+ {
+ var path = item.Uri.ToString();
+ //Calculate the parent path
+ var parentPath = GetParentPath(path);
+ var parentName = GetParentPath(item.Name);
+ DirectoryRecord parent;
+
+
+ //First ensure that the parent items exist
+
+ var parts = item.Name.Split('/');
+
+ if (item.IsDirectory)
+ {
+ AddParentNodes(lookups, rootNodes, parts, item);
+
+ //Store each item using its current path
+ var newNode = new DirectoryRecord { DisplayName = parts.Last(), ObjectInfo = item };
+ AddNode(rootNodes, lookups, newNode);
+ }
+ else
+ {
+ //Dont't add files
+ //But check to ensure that we DO have it's parent on record
+ //If it exist
+ if (lookups.TryGetValue(parentPath, out parent))
+ {
+ //Just continue
+ continue;
+ }
+ //If the item is directly below its parent container, there is no path to add
+ if (String.IsNullOrWhiteSpace(parentName))
+ continue;
+ //Otherwise we need to add it, because it is missing from the list
+ //Store each item using its current path
+ //Since this is not a directory, we won't add the item itself
+ AddParentNodes(lookups, rootNodes, parts, item);
+ }
+ }
+ return rootNodes;
+ }
+
+ private static void AddParentNodes(Dictionary<string, DirectoryRecord> lookups, List<DirectoryRecord> rootNodes, string[] parts, ObjectInfo item)
+ {
+ for (int i = 0; i < parts.Length - 1; i++)
+ {
+ var nodeName = String.Join("/", parts, 0, i + 1);
+ var storageUri = GetStorageUri(item);
+ var nodeKey = String.Format("{0}/{1}/{2}/{3}", storageUri, item.Account, item.Container, nodeName);
+ //If the node was already addeds, skip
+ if (lookups.ContainsKey(nodeKey))
+ continue;
+ var newNode = new DirectoryRecord
+ {
+ DisplayName = parts[i],
+ ObjectInfo = new ObjectInfo
+ {
+ Account = item.Account,
+ Container = item.Container,
+ Name = nodeName,
+ StorageUri = item.StorageUri,
+ Content_Type = "application/directory"
+ }
+ };
+ AddNode(rootNodes, lookups, newNode);
+ }
+ }
+
+ private static string GetStorageUri(ObjectInfo item)
+ {
+ var storageParts = item.StorageUri.ToString().Split('/');
+ var accountUri = String.Join("/", storageParts, 0, storageParts.Length - 1);
+ return accountUri;
+ }
+
+ private static void AddNode(List<DirectoryRecord> rootNodes, Dictionary<string, DirectoryRecord> lookups, DirectoryRecord newNode)
+ {
+ DirectoryRecord parent;
+ var path = newNode.Uri.ToString();
+ var parentPath = GetParentPath(path);
+ lookups[path] = newNode;
+
+ //If the record is a directory, we need to add it no matter what
+
+ //If it is a file, we need to check that its parent node exists
+ //If the parent node doesn't exist, we need to add a node for it.
+ //We need to add nodes for all parents recursively,in case they don't exist
+
+ //Does a parent item exist?
+ if (lookups.TryGetValue(parentPath, out parent))
+ {
+ //If so, add the current item under its parent
+ parent.Directories.Add(newNode);
+ parent.Directories.Sort((x, y) => String.CompareOrdinal(x.Uri.ToString(), y.Uri.ToString()));
+ }
+ else
+ //Otherwise add it to the list of root nodes
+ rootNodes.Add(newNode);
+ }
+
+ private static string GetParentPath(string path)
+ {
+ var lastIndex = path.LastIndexOf("/", StringComparison.Ordinal);
+ if (lastIndex < 0)
+ return null;
+ var parentPath = path.Substring(0, lastIndex);
+ return parentPath;
+ }
+
+ }
+}