Adding StorageFolder poco object, and support for folders at the container level.
Implements: blueprint storage-folder-support Change-Id: I8cf14854c3eabf83c385b6fb780853defd6d6842
This commit is contained in:
@@ -92,6 +92,8 @@
|
|||||||
<Compile Include="OpenstackClientManagerTests.cs" />
|
<Compile Include="OpenstackClientManagerTests.cs" />
|
||||||
<Compile Include="OpenstackServiceClientManagerTests.cs" />
|
<Compile Include="OpenstackServiceClientManagerTests.cs" />
|
||||||
<Compile Include="Storage\StorageServiceClientDefinitionTests.cs" />
|
<Compile Include="Storage\StorageServiceClientDefinitionTests.cs" />
|
||||||
|
<Compile Include="Storage\StorageFolderTests.cs" />
|
||||||
|
<Compile Include="Storage\StorageFolderPayloadConverterTests.cs" />
|
||||||
<Compile Include="TestOpenstackRegionResolver.cs" />
|
<Compile Include="TestOpenstackRegionResolver.cs" />
|
||||||
<Compile Include="TestOpenstackServiceEndpointResolver.cs" />
|
<Compile Include="TestOpenstackServiceEndpointResolver.cs" />
|
||||||
<Compile Include="ObjectExtentionsTests.cs" />
|
<Compile Include="ObjectExtentionsTests.cs" />
|
||||||
|
|||||||
@@ -253,6 +253,111 @@ namespace Openstack.Test.Storage
|
|||||||
Assert.AreEqual(1, container.Objects.ToList().Count());
|
Assert.AreEqual(1, container.Objects.ToList().Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanParseContainerWithValidJsonPayloadWithNestedFoldersAndObjects()
|
||||||
|
{
|
||||||
|
var containerName = "TestContainer";
|
||||||
|
var validObjectJson = @"[
|
||||||
|
{
|
||||||
|
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||||
|
""last_modified"": ""2014-03-27T20:57:11.150910"",
|
||||||
|
""bytes"": 0,
|
||||||
|
""name"": ""a/"",
|
||||||
|
""content_type"": ""application/octet-stream""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||||
|
""last_modified"": ""2014-03-27T20:57:36.676350"",
|
||||||
|
""bytes"": 0,
|
||||||
|
""name"": ""a/b/"",
|
||||||
|
""content_type"": ""application/octet-stream""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""437b930db84b8079c2dd804a71936b5f"",
|
||||||
|
""last_modified"": ""2014-03-27T20:58:36.676620"",
|
||||||
|
""bytes"": 9,
|
||||||
|
""name"": ""a/b/b"",
|
||||||
|
""content_type"": ""text/plain;charset=UTF-8""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""437b930db84b8079c2dd804a71936b5f"",
|
||||||
|
""last_modified"": ""2014-03-27T20:58:43.935540"",
|
||||||
|
""bytes"": 9,
|
||||||
|
""name"": ""a/b/c"",
|
||||||
|
""content_type"": ""text/plain;charset=UTF-8""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""437b930db84b8079c2dd804a71936b5f"",
|
||||||
|
""last_modified"": ""2014-03-27T20:58:54.142580"",
|
||||||
|
""bytes"": 9,
|
||||||
|
""name"": ""a/b/c/object3"",
|
||||||
|
""content_type"": ""text/plain;charset=UTF-8""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""437b930db84b8079c2dd804a71936b5f"",
|
||||||
|
""last_modified"": ""2014-03-27T20:58:25.771530"",
|
||||||
|
""bytes"": 9,
|
||||||
|
""name"": ""a/object2"",
|
||||||
|
""content_type"": ""text/plain;charset=UTF-8""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||||
|
""last_modified"": ""2014-03-27T20:57:47.122360"",
|
||||||
|
""bytes"": 0,
|
||||||
|
""name"": ""a/x/"",
|
||||||
|
""content_type"": ""application/octet-stream""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""hash"": ""437b930db84b8079c2dd804a71936b5f"",
|
||||||
|
""last_modified"": ""2014-03-27T20:58:15.696360"",
|
||||||
|
""bytes"": 9,
|
||||||
|
""name"": ""object1"",
|
||||||
|
""content_type"": ""text/plain;charset=UTF-8""
|
||||||
|
}
|
||||||
|
]";
|
||||||
|
|
||||||
|
var converter = new StorageContainerPayloadConverter();
|
||||||
|
var headers = new HttpHeadersAbstraction
|
||||||
|
{
|
||||||
|
{"X-Container-Bytes-Used", "45"},
|
||||||
|
{"X-Container-Object-Count", "8"}
|
||||||
|
};
|
||||||
|
|
||||||
|
var container = converter.Convert(containerName, headers, validObjectJson);
|
||||||
|
Assert.IsNotNull(container);
|
||||||
|
Assert.AreEqual(containerName, container.Name);
|
||||||
|
Assert.AreEqual(45, container.TotalBytesUsed);
|
||||||
|
Assert.AreEqual(8, container.TotalObjectCount);
|
||||||
|
Assert.AreEqual(8, container.Objects.ToList().Count());
|
||||||
|
Assert.IsTrue(container.Objects.ToList().Any(o => o.Name == "object1"));
|
||||||
|
|
||||||
|
var folders = container.Folders.ToList();
|
||||||
|
Assert.AreEqual(1, folders.Count());
|
||||||
|
|
||||||
|
var aNode = folders.First();
|
||||||
|
Assert.AreEqual("a", aNode.Name);
|
||||||
|
Assert.AreEqual(2, aNode.Folders.Count);
|
||||||
|
Assert.AreEqual(1, aNode.Objects.Count);
|
||||||
|
Assert.IsTrue(aNode.Objects.Any(f => f.Name == "a/object2"));
|
||||||
|
|
||||||
|
var xNode = aNode.Folders.First(f => f.Name == "x");
|
||||||
|
Assert.AreEqual(0, xNode.Folders.Count);
|
||||||
|
Assert.AreEqual(0, xNode.Objects.Count);
|
||||||
|
|
||||||
|
var bNode = aNode.Folders.First(f => f.Name == "b");
|
||||||
|
Assert.AreEqual(1, bNode.Folders.Count);
|
||||||
|
Assert.AreEqual(2, bNode.Objects.Count);
|
||||||
|
Assert.IsTrue(bNode.Folders.Any(f => f.Name == "c"));
|
||||||
|
Assert.IsTrue(bNode.Objects.Any(f => f.Name == "a/b/c"));
|
||||||
|
Assert.IsTrue(bNode.Objects.Any(f => f.Name == "a/b/b"));
|
||||||
|
|
||||||
|
var cNode = bNode.Folders.First(f => f.Name == "c");
|
||||||
|
Assert.AreEqual(0, cNode.Folders.Count);
|
||||||
|
Assert.AreEqual(1, cNode.Objects.Count);
|
||||||
|
Assert.IsTrue(cNode.Objects.Any(f => f.Name == "a/b/c/object3"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[ExpectedException(typeof(HttpParseException))]
|
[ExpectedException(typeof(HttpParseException))]
|
||||||
public void CannotParseContainerWithMissingBytesUsedHeader()
|
public void CannotParseContainerWithMissingBytesUsedHeader()
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
// /* ============================================================================
|
||||||
|
// Copyright 2014 Hewlett Packard
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// ============================================================================ */
|
||||||
|
|
||||||
|
namespace Openstack.Test.Storage
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Openstack.Storage;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class StorageFolderPayloadConverterTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddFolderWithNestedFolders()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/b/c/d/","a") };
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1,folders.Count);
|
||||||
|
Assert.AreEqual("a",folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("b", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("d", folders[0].Folders.First().Folders.First().Folders.First().Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddFolderWithNestedFoldersAndDuplicateNames()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/c/c/c/", "a") };
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Folders.First().Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddSingleFolder()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/", "a") };
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(0, folders[0].Folders.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
|
||||||
|
[ExpectedException(typeof(ArgumentNullException))]
|
||||||
|
public void CanAddFolderWithNullObjectList()
|
||||||
|
{
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
converter.Convert(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddNestedFoldersWhenRootExists()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/", "a"), new StorageObject("a/b/c/d/", "a") };
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("b", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("d", folders[0].Folders.First().Folders.First().Folders.First().Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddNestedFoldersWhenRootExistsWithObjectsAtLeaf()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/b/c/d/foo", "a"), new StorageObject("a/b/c/d/bar", "a") };
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("b", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
|
||||||
|
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||||
|
Assert.AreEqual("d", leaf.Name);
|
||||||
|
Assert.AreEqual(2,leaf.Objects.Count);
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddNestedFoldersWhenRootExistsWithObjectsAtLeafAndRoot()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/b/c/d/foo", "a"), new StorageObject("a/b/c/d/bar", "a"), new StorageObject("xyz", "a") };
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("b", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
|
||||||
|
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||||
|
Assert.AreEqual("d", leaf.Name);
|
||||||
|
Assert.AreEqual(2, leaf.Objects.Count);
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddNestedFoldersWhenRootExistsWithObjectsAtLeafAndLongNameAtRoot()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/b/c/d/foo", "a"), new StorageObject("a/b/c/d/bar", "a"), new StorageObject("thiswillsorttothetopofthelist", "a") };
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
Assert.AreEqual("a", folders[0].Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.Count);
|
||||||
|
Assert.AreEqual("b", folders[0].Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.Count);
|
||||||
|
Assert.AreEqual("c", folders[0].Folders.First().Folders.First().Name);
|
||||||
|
Assert.AreEqual(1, folders[0].Folders.First().Folders.First().Folders.Count);
|
||||||
|
|
||||||
|
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||||
|
Assert.AreEqual("d", leaf.Name);
|
||||||
|
Assert.AreEqual(2, leaf.Objects.Count);
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||||
|
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanAddNestedFoldersWhenRootExistsWithObjectsAtManyLevels()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>() { new StorageObject("a/b/c/d/foo", "a"),
|
||||||
|
new StorageObject("a/b/bar", "a"),
|
||||||
|
new StorageObject("a/b/c/beans", "a"),
|
||||||
|
new StorageObject("a/string", "a"),
|
||||||
|
new StorageObject("a/b/c/d/", "a") ,
|
||||||
|
new StorageObject("a/b/c/", "a") ,
|
||||||
|
new StorageObject("a/", "a")
|
||||||
|
};
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var folders = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
var aNode = folders[0];
|
||||||
|
var bNode = folders[0].Folders.First();
|
||||||
|
var cNode = folders[0].Folders.First().Folders.First();
|
||||||
|
var dNode = folders[0].Folders.First().Folders.First().Folders.First();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, folders.Count);
|
||||||
|
|
||||||
|
Assert.AreEqual("a", aNode.Name);
|
||||||
|
Assert.AreEqual(1, aNode.Folders.Count);
|
||||||
|
Assert.AreEqual(1, aNode.Objects.Count);
|
||||||
|
Assert.IsTrue(aNode.Objects.Any(o => o.Name == "a/string"));
|
||||||
|
|
||||||
|
Assert.AreEqual("b", bNode.Name);
|
||||||
|
Assert.AreEqual("a/b", bNode.FullName);
|
||||||
|
Assert.AreEqual(1, bNode.Folders.Count);
|
||||||
|
Assert.AreEqual(1, bNode.Objects.Count);
|
||||||
|
Assert.IsTrue(bNode.Objects.Any(o => o.Name == "a/b/bar"));
|
||||||
|
|
||||||
|
Assert.AreEqual("c", cNode.Name);
|
||||||
|
Assert.AreEqual("a/b/c", cNode.FullName);
|
||||||
|
Assert.AreEqual(1, cNode.Folders.Count);
|
||||||
|
Assert.AreEqual(1, cNode.Objects.Count);
|
||||||
|
Assert.IsTrue(cNode.Objects.Any(o => o.Name == "a/b/c/beans"));
|
||||||
|
|
||||||
|
Assert.AreEqual("d", dNode.Name);
|
||||||
|
Assert.AreEqual("a/b/c/d", dNode.FullName);
|
||||||
|
Assert.AreEqual(1, dNode.Objects.Count);
|
||||||
|
Assert.IsTrue(dNode.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanConvertFolders()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>()
|
||||||
|
{
|
||||||
|
new StorageObject("a", "a"),
|
||||||
|
new StorageObject("a/", "a"),
|
||||||
|
new StorageObject("b//", "a"),
|
||||||
|
new StorageObject("//a/", "a"),
|
||||||
|
new StorageObject("a/b/", "a", DateTime.Now, "12345", 100, "application/directory")
|
||||||
|
};
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var resp = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, resp.Count);
|
||||||
|
|
||||||
|
var aNode = resp.First();
|
||||||
|
Assert.AreEqual("a", aNode.Name);
|
||||||
|
Assert.AreEqual(1, aNode.Folders.Count);
|
||||||
|
Assert.AreEqual(0, aNode.Objects.Count);
|
||||||
|
|
||||||
|
var bNode = aNode.Folders.First();
|
||||||
|
Assert.AreEqual("b", bNode.Name);
|
||||||
|
Assert.AreEqual("a/b", bNode.FullName);
|
||||||
|
Assert.AreEqual(0, bNode.Folders.Count);
|
||||||
|
Assert.AreEqual(0, bNode.Objects.Count);
|
||||||
|
|
||||||
|
Assert.AreEqual(5, objects.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanConvertFoldersWithNoInputObjects()
|
||||||
|
{
|
||||||
|
var objects = new List<StorageObject>();
|
||||||
|
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var resp = converter.Convert(objects).ToList();
|
||||||
|
|
||||||
|
Assert.AreEqual(0, resp.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
[ExpectedException(typeof(ArgumentNullException))]
|
||||||
|
public void CannotConvertFoldersWithNullObjectList()
|
||||||
|
{
|
||||||
|
var converter = new StorageFolderPayloadConverter();
|
||||||
|
var resp = converter.Convert(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
148
Openstack/Openstack.Test/Storage/StorageFolderTests.cs
Normal file
148
Openstack/Openstack.Test/Storage/StorageFolderTests.cs
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
// /* ============================================================================
|
||||||
|
// Copyright 2014 Hewlett Packard
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// ============================================================================ */
|
||||||
|
|
||||||
|
namespace Openstack.Test.Storage
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using Openstack.Storage;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class StorageFolderTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void CanCreateFolder()
|
||||||
|
{
|
||||||
|
var folder = new StorageFolder("MyFolder", new List<StorageFolder>());
|
||||||
|
Assert.AreEqual("MyFolder", folder.FullName);
|
||||||
|
Assert.AreEqual("MyFolder", folder.Name);
|
||||||
|
Assert.AreEqual(0,folder.Folders.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanCreateFolderWithLeadingSlashes()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folder = new StorageFolder("//MyFolder", new List<StorageFolder>());
|
||||||
|
Assert.AreEqual(expectedFolderName, folder.FullName);
|
||||||
|
Assert.AreEqual(expectedFolderName, folder.Name);
|
||||||
|
Assert.AreEqual(0, folder.Folders.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanCreateFolderWithTrailingSlashes()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folder = new StorageFolder("MyFolder//", new List<StorageFolder>());
|
||||||
|
Assert.AreEqual(expectedFolderName, folder.FullName);
|
||||||
|
Assert.AreEqual(expectedFolderName, folder.Name);
|
||||||
|
Assert.AreEqual(0, folder.Folders.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanCreateFolderWithMultipleFoldersInName()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folder = new StorageFolder("//Some/Folder/MyFolder", new List<StorageFolder>());
|
||||||
|
Assert.AreEqual("Some/Folder/MyFolder", folder.FullName);
|
||||||
|
Assert.AreEqual(expectedFolderName, folder.Name);
|
||||||
|
Assert.AreEqual(0, folder.Folders.Count());
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithNoSlashes()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "myFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("myFolder");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithLeadingSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "myFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("/myFolder");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithTrailingSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "myFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("myFolder/");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithTrailingAndLeadingSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "myFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("/myFolder/");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithJustSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = string.Empty;
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("/");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithDoubleLeadingSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("//MyFolder");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithDoubleTrailingSlash()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("MyFolder//");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithDoubleTrailingAndLeadingSlashes()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("//MyFolder//");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithMultipleFolders()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("Folder1/Folder2/Folder3/MyFolder");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CanExtractFolderNameWithMultipleFoldersAndSlashes()
|
||||||
|
{
|
||||||
|
var expectedFolderName = "MyFolder";
|
||||||
|
var folderName = StorageFolder.ExtractFolderName("Folder1//Folder2/Folder3//MyFolder/");
|
||||||
|
Assert.AreEqual(expectedFolderName, folderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,6 +90,7 @@
|
|||||||
<Compile Include="ServiceRegistrar.cs" />
|
<Compile Include="ServiceRegistrar.cs" />
|
||||||
<Compile Include="Storage\ContainerNameValidator.cs" />
|
<Compile Include="Storage\ContainerNameValidator.cs" />
|
||||||
<Compile Include="Storage\IStorageAccountPayloadConverter.cs" />
|
<Compile Include="Storage\IStorageAccountPayloadConverter.cs" />
|
||||||
|
<Compile Include="Storage\IStorageFolderPayloadConverter.cs" />
|
||||||
<Compile Include="Storage\IStorageServiceClient.cs" />
|
<Compile Include="Storage\IStorageServiceClient.cs" />
|
||||||
<Compile Include="Storage\IStorageContainerPayloadConverter.cs" />
|
<Compile Include="Storage\IStorageContainerPayloadConverter.cs" />
|
||||||
<Compile Include="Storage\IStorageObjectPayloadConverter.cs" />
|
<Compile Include="Storage\IStorageObjectPayloadConverter.cs" />
|
||||||
@@ -97,6 +98,8 @@
|
|||||||
<Compile Include="Storage\IStorageServicePocoClientFactory.cs" />
|
<Compile Include="Storage\IStorageServicePocoClientFactory.cs" />
|
||||||
<Compile Include="Storage\IStorageServiceRestClient.cs" />
|
<Compile Include="Storage\IStorageServiceRestClient.cs" />
|
||||||
<Compile Include="Storage\IStorageServiceRestClientFactory.cs" />
|
<Compile Include="Storage\IStorageServiceRestClientFactory.cs" />
|
||||||
|
<Compile Include="Storage\StorageFolder.cs" />
|
||||||
|
<Compile Include="Storage\StorageFolderPayloadConverter.cs" />
|
||||||
<Compile Include="Storage\StorageServiceClient.cs" />
|
<Compile Include="Storage\StorageServiceClient.cs" />
|
||||||
<Compile Include="Storage\StorageServiceClientContext.cs" />
|
<Compile Include="Storage\StorageServiceClientContext.cs" />
|
||||||
<Compile Include="Storage\StorageServiceClientDefinition.cs" />
|
<Compile Include="Storage\StorageServiceClientDefinition.cs" />
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace Openstack
|
|||||||
//Converters
|
//Converters
|
||||||
manager.RegisterServiceInstance(typeof(IStorageContainerPayloadConverter), new StorageContainerPayloadConverter());
|
manager.RegisterServiceInstance(typeof(IStorageContainerPayloadConverter), new StorageContainerPayloadConverter());
|
||||||
manager.RegisterServiceInstance(typeof(IStorageObjectPayloadConverter), new StorageObjectPayloadConverter());
|
manager.RegisterServiceInstance(typeof(IStorageObjectPayloadConverter), new StorageObjectPayloadConverter());
|
||||||
|
manager.RegisterServiceInstance(typeof(IStorageFolderPayloadConverter), new StorageFolderPayloadConverter());
|
||||||
manager.RegisterServiceInstance(typeof(IStorageAccountPayloadConverter), new StorageAccountPayloadConverter());
|
manager.RegisterServiceInstance(typeof(IStorageAccountPayloadConverter), new StorageAccountPayloadConverter());
|
||||||
manager.RegisterServiceInstance(typeof(IAccessTokenPayloadConverter), new AccessTokenPayloadConverter());
|
manager.RegisterServiceInstance(typeof(IAccessTokenPayloadConverter), new AccessTokenPayloadConverter());
|
||||||
manager.RegisterServiceInstance(typeof(IOpenstackServiceCatalogPayloadConverter), new OpenstackServiceCatalogPayloadConverter());
|
manager.RegisterServiceInstance(typeof(IOpenstackServiceCatalogPayloadConverter), new OpenstackServiceCatalogPayloadConverter());
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// /* ============================================================================
|
||||||
|
// Copyright 2014 Hewlett Packard
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// ============================================================================ */
|
||||||
|
|
||||||
|
namespace Openstack.Storage
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public interface IStorageFolderPayloadConverter
|
||||||
|
{
|
||||||
|
IEnumerable<StorageFolder> Convert(IEnumerable<StorageObject> objects);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,6 +45,11 @@ namespace Openstack.Storage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<StorageObject> Objects { get; private set; }
|
public IEnumerable<StorageObject> Objects { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of storage folders that are in the container.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<StorageFolder> Folders { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the metadata associated with the storage container.
|
/// Gets the metadata associated with the storage container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -79,17 +84,33 @@ namespace Openstack.Storage
|
|||||||
/// <param name="objects">A list of storage objects that are in the container.</param>
|
/// <param name="objects">A list of storage objects that are in the container.</param>
|
||||||
/// <param name="metadata">Metadata associated with the storage container.</param>
|
/// <param name="metadata">Metadata associated with the storage container.</param>
|
||||||
internal StorageContainer(string name, long totalBytes, int totalObjects, IDictionary<string,string> metadata, IEnumerable<StorageObject> objects)
|
internal StorageContainer(string name, long totalBytes, int totalObjects, IDictionary<string,string> metadata, IEnumerable<StorageObject> objects)
|
||||||
|
: this(name, totalBytes,totalObjects, metadata, objects, new List<StorageFolder>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the StorageContainer class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the storage container.</param>
|
||||||
|
/// <param name="totalBytes">The total number of bytes used in the container.</param>
|
||||||
|
/// <param name="totalObjects">The total number of objects in the container.</param>
|
||||||
|
/// <param name="objects">A list of storage objects that are in the container.</param>
|
||||||
|
/// <param name="folders">A list of storage folders that are in the container.</param>
|
||||||
|
/// <param name="metadata">Metadata associated with the storage container.</param>
|
||||||
|
internal StorageContainer(string name, long totalBytes, int totalObjects, IDictionary<string, string> metadata, IEnumerable<StorageObject> objects, IEnumerable<StorageFolder> folders)
|
||||||
{
|
{
|
||||||
name.AssertIsNotNullOrEmpty("name");
|
name.AssertIsNotNullOrEmpty("name");
|
||||||
totalBytes.AssertIsNotNull("totalBytes");
|
totalBytes.AssertIsNotNull("totalBytes");
|
||||||
totalObjects.AssertIsNotNull("totalObjects");
|
totalObjects.AssertIsNotNull("totalObjects");
|
||||||
metadata.AssertIsNotNull("metadata");
|
metadata.AssertIsNotNull("metadata");
|
||||||
objects.AssertIsNotNull("objects");
|
objects.AssertIsNotNull("objects");
|
||||||
|
folders.AssertIsNotNull("folders");
|
||||||
|
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.TotalBytesUsed = totalBytes;
|
this.TotalBytesUsed = totalBytes;
|
||||||
this.TotalObjectCount = totalObjects;
|
this.TotalObjectCount = totalObjects;
|
||||||
this.Objects = objects.ToList();
|
this.Objects = objects.ToList();
|
||||||
|
this.Folders = folders.ToList();
|
||||||
this.Metadata = metadata;
|
this.Metadata = metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,14 +97,17 @@ namespace Openstack.Storage
|
|||||||
payload.AssertIsNotNull("payload");
|
payload.AssertIsNotNull("payload");
|
||||||
|
|
||||||
var objectConverter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
var objectConverter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||||
|
var folderConverter = ServiceLocator.Instance.Locate<IStorageFolderPayloadConverter>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var totalBytes = long.Parse(headers["X-Container-Bytes-Used"].First());
|
var totalBytes = long.Parse(headers["X-Container-Bytes-Used"].First());
|
||||||
var totalObjects = int.Parse(headers["X-Container-Object-Count"].First());
|
var totalObjects = int.Parse(headers["X-Container-Object-Count"].First());
|
||||||
|
var metadata = headers.Where(kvp => kvp.Key.StartsWith("X-Container-Meta")).ToDictionary(header => header.Key.Substring(17, header.Key.Length - 17), header => header.Value.First());
|
||||||
var objects = objectConverter.Convert(name, payload);
|
var objects = objectConverter.Convert(name, payload);
|
||||||
|
var folders = folderConverter.Convert(objects);
|
||||||
|
|
||||||
return new StorageContainer(name, totalBytes, totalObjects, objects);
|
return new StorageContainer(name, totalBytes, totalObjects, metadata, objects, folders);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
56
Openstack/Openstack/Storage/StorageFolder.cs
Normal file
56
Openstack/Openstack/Storage/StorageFolder.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// /* ============================================================================
|
||||||
|
// Copyright 2014 Hewlett Packard
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// ============================================================================ */
|
||||||
|
|
||||||
|
namespace Openstack.Storage
|
||||||
|
{
|
||||||
|
using System.Linq;
|
||||||
|
using Openstack.Common;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class StorageFolder
|
||||||
|
{
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public string FullName { get; private set; }
|
||||||
|
|
||||||
|
public ICollection<StorageFolder> Folders { get; private set; }
|
||||||
|
|
||||||
|
public ICollection<StorageObject> Objects { get; private set; }
|
||||||
|
|
||||||
|
public StorageFolder(string fullName, IEnumerable<StorageFolder> folders) : this(fullName, folders, new List<StorageObject>())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public StorageFolder(string fullName, IEnumerable<StorageFolder> folders, IEnumerable<StorageObject> objects )
|
||||||
|
{
|
||||||
|
fullName.AssertIsNotNullOrEmpty("fullName", "Cannot create a storage folder with a null or empty full name.");
|
||||||
|
folders.AssertIsNotNull("folders", "Cannot create a storage folder with a null folders collection.");
|
||||||
|
objects.AssertIsNotNull("objects", "Cannot create a storage folder with a null objects collection.");
|
||||||
|
|
||||||
|
this.FullName = fullName.Trim('/');
|
||||||
|
this.Name = ExtractFolderName(this.FullName);
|
||||||
|
this.Folders = folders.ToList();
|
||||||
|
this.Objects = objects.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ExtractFolderName(string fullFolderName)
|
||||||
|
{
|
||||||
|
var fullName = fullFolderName.Trim('/');
|
||||||
|
var lastIndex = fullName.LastIndexOf('/');
|
||||||
|
lastIndex++;
|
||||||
|
return fullName.Substring(lastIndex, fullName.Length - lastIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
Openstack/Openstack/Storage/StorageFolderPayloadConverter.cs
Normal file
88
Openstack/Openstack/Storage/StorageFolderPayloadConverter.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// /* ============================================================================
|
||||||
|
// Copyright 2014 Hewlett Packard
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
// ============================================================================ */
|
||||||
|
|
||||||
|
namespace Openstack.Storage
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Openstack.Common;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
internal class StorageFolderPayloadConverter : IStorageFolderPayloadConverter
|
||||||
|
{
|
||||||
|
internal const string consecutiveSlashRegex = @"/{2,}";
|
||||||
|
|
||||||
|
public IEnumerable<StorageFolder> Convert(IEnumerable<StorageObject> objects)
|
||||||
|
{
|
||||||
|
objects.AssertIsNotNull("objects", "Cannot build folders with a null object collection.");
|
||||||
|
|
||||||
|
var folders = new List<StorageFolder>();
|
||||||
|
|
||||||
|
var sortedObjectList = objects.OrderByDescending(o => o.Name.Length).ToList();
|
||||||
|
|
||||||
|
foreach (var obj in sortedObjectList)
|
||||||
|
{
|
||||||
|
//if the name has any consecutive slashes in the name, skip it.
|
||||||
|
if (Regex.IsMatch(obj.Name, consecutiveSlashRegex))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//split the input using a forward slash as the folder delimiter, and separate the object name (if we have one) and the folder path.
|
||||||
|
var folderParts = obj.Name.TrimStart('/').Split('/');
|
||||||
|
var objectName = folderParts.Last(); //this will be string.empty if the object name ends in a "/" indicating that it's a folder.
|
||||||
|
folderParts = folderParts.Take(folderParts.Length - 1).ToArray();
|
||||||
|
|
||||||
|
//if there are no folders in the object's name, skip it.
|
||||||
|
if (folderParts.Count() <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentRoot = folders.FirstOrDefault(f => string.Compare(f.Name, folderParts[0], StringComparison.InvariantCulture) == 0);
|
||||||
|
if (currentRoot == null)
|
||||||
|
{
|
||||||
|
//if the root folder does not exist, create it.
|
||||||
|
currentRoot = new StorageFolder(folderParts[0], new List<StorageFolder>());
|
||||||
|
folders.Add(currentRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
//go through the rest of the folder path (if any) and add nested folders (if needed).
|
||||||
|
var currentPath = folderParts[0];
|
||||||
|
foreach (var part in folderParts.Skip(1))
|
||||||
|
{
|
||||||
|
currentPath += "/" + part;
|
||||||
|
var newRoot = currentRoot.Folders.FirstOrDefault(f => string.Compare(f.Name, part, StringComparison.InvariantCulture) == 0);
|
||||||
|
if (newRoot == null)
|
||||||
|
{
|
||||||
|
newRoot = new StorageFolder(currentPath, new List<StorageFolder>());
|
||||||
|
currentRoot.Folders.Add(newRoot);
|
||||||
|
}
|
||||||
|
currentRoot = newRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if this object is not a folder (e.g. the name does not end in a /), then add this object to the current folder.
|
||||||
|
if (!string.IsNullOrEmpty(objectName))
|
||||||
|
{
|
||||||
|
currentRoot.Objects.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return folders;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user