using System.Linq;
using System.Linq.Expressions;
using System.Text;
+using System.Text.RegularExpressions;
using Pithos.Client.WPF.SelectiveSynch;
+using Pithos.Core;
using Pithos.Interfaces;
namespace Pithos.Client.WPF.Utils
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>();
- var nodes = new List<DirectoryRecord>();
+
+ //RootNodes contains only the root nodes
+ var rootNodes = new List<DirectoryRecord>();
+
foreach (var item in orderedItems)
{
var path = item.Uri.ToString();
- var newNode = new DirectoryRecord{ DisplayName=item.Name.Split('/').Last(),ObjectInfo=item};
- lookups[path] = newNode;
+ //Calculate the parent path
+ var parentPath = GetParentPath(path);
+ var parentName = GetParentPath(item.Name);
+ DirectoryRecord parent;
- var lastIndex = path.LastIndexOf("/", StringComparison.Ordinal);
- var upTo = lastIndex < 0 ? path.Length - 1 : lastIndex;
- var parentPath = path.Substring(0, upTo);
-
- DirectoryRecord parent;
- if (lookups.TryGetValue(parentPath, out parent))
+
+ //First ensure that the parent items exist
+
+ var parts = item.Name.Split('/');
+
+ //Dont't add files
+ if (!item.IsDirectory)
{
- parent.Directories.Add(newNode);
- parent.Directories.Sort((x,y)=>String.CompareOrdinal(x.Uri.ToString(), y.Uri.ToString()));
+ //But check to ensure that we DO have it's parent on record
+ //It 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);
}
else
- nodes.Add(newNode);
+ {
+ 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);
+ }
+
}
- return nodes;
+ 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.ObjectInfo.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;
+ }
+
+ static readonly Regex PascalCaseRegex = new Regex("[a-z][A-Z]", RegexOptions.Compiled);
+ public static string Name(this Enum value)
+ {
+ var name = Enum.GetName(value.GetType(), value);
+ return PascalCaseRegex.Replace(name, m => m.Value[0] + " " + char.ToLower(m.Value[1]));
}
}
}