130 lines
5.3 KiB
C#
130 lines
5.3 KiB
C#
using AsyncEvent;
|
|
using FileTime.Core.Models;
|
|
using FileTime.Core.Providers;
|
|
|
|
namespace FileTime.Core.Timeline
|
|
{
|
|
public class TimeContainer : IContainer
|
|
{
|
|
private readonly IContainer? _parent;
|
|
private readonly PointInTime _pointInTime;
|
|
|
|
public bool IsLoaded => true;
|
|
|
|
public AsyncEventHandler Refreshed { get; } = new AsyncEventHandler();
|
|
|
|
public string Name { get; }
|
|
|
|
public string? FullName { get; }
|
|
|
|
public bool IsHidden => false;
|
|
|
|
public SupportsDelete CanDelete => SupportsDelete.True;
|
|
|
|
public bool CanRename => true;
|
|
|
|
public IContentProvider Provider { get; }
|
|
public IContentProvider VirtualProvider { get; }
|
|
public IReadOnlyList<Exception> Exceptions { get; } = new List<Exception>().AsReadOnly();
|
|
|
|
public bool SupportsDirectoryLevelSoftDelete => false;
|
|
|
|
public bool IsDisposed { get; private set; }
|
|
|
|
public TimeContainer(string name, IContainer parent, IContentProvider contentProvider, IContentProvider virtualContentProvider, PointInTime pointInTime)
|
|
{
|
|
_parent = parent;
|
|
_pointInTime = pointInTime;
|
|
|
|
Name = name;
|
|
Provider = contentProvider;
|
|
VirtualProvider = virtualContentProvider;
|
|
FullName = parent?.FullName == null ? Name : parent.FullName + Constants.SeparatorChar + Name;
|
|
}
|
|
|
|
public async Task<IContainer> Clone() => new TimeContainer(Name, await _parent!.Clone(), Provider, VirtualProvider, _pointInTime);
|
|
|
|
public Task<IContainer> CreateContainer(string name) => Task.FromResult((IContainer)new TimeContainer(name, this, Provider, VirtualProvider, _pointInTime));
|
|
|
|
public Task<IElement> CreateElement(string name) => Task.FromResult((IElement)new TimeElement(name, this, Provider, VirtualProvider));
|
|
|
|
public Task Delete(bool hardDelete = false) => Task.CompletedTask;
|
|
|
|
public async Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false)
|
|
{
|
|
var paths = path.Split(Constants.SeparatorChar);
|
|
|
|
var item = (await GetItems())!.FirstOrDefault(i => i.Name == paths[0]);
|
|
|
|
if (paths.Length == 1)
|
|
{
|
|
return item;
|
|
}
|
|
|
|
if (item is IContainer container)
|
|
{
|
|
return await container.GetByPath(string.Join(Constants.SeparatorChar, paths.Skip(1)), acceptDeepestMatch);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default) =>
|
|
Task.FromResult(
|
|
(IReadOnlyList<IContainer>?)_pointInTime
|
|
.Differences
|
|
.Where(d =>
|
|
d.Type == DifferenceItemType.Container
|
|
&& GetParentPath(d.AbsolutePath.Path) == FullName)
|
|
.Select(MapContainer)
|
|
.ToList()
|
|
.AsReadOnly()
|
|
);
|
|
|
|
public Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default) =>
|
|
Task.FromResult(
|
|
(IReadOnlyList<IElement>?)_pointInTime
|
|
.Differences
|
|
.Where(d =>
|
|
d.Type == DifferenceItemType.Element
|
|
&& GetParentPath(d.AbsolutePath.Path) == FullName)
|
|
.Select(MapElement)
|
|
.ToList()
|
|
.AsReadOnly()
|
|
);
|
|
|
|
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
|
{
|
|
var containers = (await GetContainers(token))!;
|
|
var elements = (await GetElements(token))!;
|
|
|
|
return containers.Cast<IItem>().Concat(elements).ToList().AsReadOnly();
|
|
}
|
|
|
|
public IContainer? GetParent() => _parent;
|
|
|
|
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
|
|
|
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
|
|
|
public Task Rename(string newName) => Task.CompletedTask;
|
|
|
|
private static string GetParentPath(string path) => string.Join(Constants.SeparatorChar, path.Split(Constants.SeparatorChar).Take(-1));
|
|
|
|
private IContainer MapContainer(Difference containerDiff)
|
|
{
|
|
if (containerDiff.Type != DifferenceItemType.Container) throw new ArgumentException($"{nameof(containerDiff)}'s {nameof(Difference.Type)} property is not {DifferenceItemType.Container}.");
|
|
return new TimeContainer(containerDiff.Name, this, Provider, containerDiff.AbsolutePath.VirtualContentProvider ?? containerDiff.AbsolutePath.ContentProvider, _pointInTime);
|
|
}
|
|
|
|
private IElement MapElement(Difference elementDiff)
|
|
{
|
|
if (elementDiff.Type != DifferenceItemType.Container) throw new ArgumentException($"{elementDiff}'s {nameof(Difference.Type)} property is not {DifferenceItemType.Element}.");
|
|
return new TimeElement(elementDiff.Name, this, Provider, elementDiff.AbsolutePath.VirtualContentProvider ?? elementDiff.AbsolutePath.ContentProvider);
|
|
}
|
|
public Task<bool> CanOpen() => Task.FromResult(true);
|
|
|
|
public void Dispose() => IsDisposed = true;
|
|
public void Unload() { }
|
|
}
|
|
} |