NodeParser
using Relativity.DataTransfer.Nodes.Internal;
using Relativity.DataTransfer.Nodes.Internal.Helpers;
using Relativity.DataTransfer.Nodes.Internal.Utilities;
using System;
using System.Collections.Generic;
using System.Text;
namespace Relativity.DataTransfer.Nodes.PathConversion
{
public class NodeParser : INodeBuilder, INodeParser, IPathHolder, IContextHolder
{
private readonly IPathCharactersValidator _pathCharactersValidator;
private readonly IPathAdjuster _pathAdjuster;
private string _path;
private INodeContext _context;
private readonly Dictionary<Type, Func<INode>> _parserActions;
internal NodeParser(IPathCharactersValidator pathCharactersValidator, IPathAdjuster pathAdjuster)
{
_pathCharactersValidator = pathCharactersValidator;
_pathAdjuster = pathAdjuster;
_parserActions = new Dictionary<Type, Func<INode>> {
{
typeof(IDrive),
ParseDrive
},
{
typeof(IDirectory),
ParseDirectory
},
{
typeof(DirectoryNode),
ParseDirectory
},
{
typeof(IFile),
ParseFile
},
{
typeof(FileNode),
ParseFile
}
};
if (FileSystemType.IsWindowsBased) {
_parserActions.Add(typeof(UncDrive), ParseDrive);
_parserActions.Add(typeof(LocalDrive), ParseDrive);
_parserActions.Add(typeof(RemoteDrive), ParseDrive);
} else
_parserActions.Add(typeof(LinuxDrive), ParseDrive);
}
public static INodeBuilder Node()
{
return FileSystemType.IsWindowsBased ? new NodeParser(new WindowsPathCharactersValidator(), new WindowsPathAdjuster(new CanonicalFormConverterFactory())) : new NodeParser(new LinuxPathCharactersValidator(), new LinuxPathAdjuster());
}
public IPathHolder WithContext(INodeContext context)
{
if (context == null)
throw new ArgumentNullException();
_context = context;
return this;
}
public INodeParser WithPath(string path)
{
_pathCharactersValidator.Validate(path);
_path = _pathAdjuster.Adjust(path);
return this;
}
public T Parse<T>() where T : INode
{
if (!_parserActions.ContainsKey(typeof(T)))
throw new InvalidOperationException($"""{typeof(T)}""");
return (T)_parserActions[typeof(T)]();
}
public bool TryParse<T>(out T node) where T : INode
{
node = default(T);
try {
node = Parse<T>();
return true;
} catch {
return false;
}
}
private IDrive ParseDrive()
{
return ResolveDriveNode(new StringBuilder(_path));
}
private IDrive ResolveDriveNode(StringBuilder stringBuilder)
{
return FileSystemType.IsWindowsBased ? WindowsDriveNodeResolver.Resolve(_path, _context, stringBuilder) : LinuxDriveNodeResolver.Resolve();
}
private IDirectory ParseDirectory()
{
StringBuilder stringBuilder = new StringBuilder(_path);
IDrive drive = ResolveDriveNode(stringBuilder);
if (_path.Equals(drive.AbsolutePath))
throw new InvalidPathException("Provided path is a drive (" + _path + ")");
INode parentNode = drive;
IDirectory directory = null;
while (stringBuilder.Length > 0) {
string name = stringBuilder.CutOffBy(PathConstants.DirectorySeparatorAsChar);
directory = new DirectoryNode(name, parentNode, DateTime.Now);
parentNode = directory;
}
return directory;
}
public IFile ParseFile()
{
IFile file = null;
StringBuilder stringBuilder = new StringBuilder(_path);
INode node = ResolveDriveNode(stringBuilder);
if (_path.Equals(node.AbsolutePath))
throw new InvalidPathException("Provided path is a drive (" + _path + ")");
INode parentNode = node;
while (file == null) {
string name = stringBuilder.CutOffBy(PathConstants.DirectorySeparatorAsChar);
if (stringBuilder.Length > 0)
parentNode = new DirectoryNode(name, parentNode, DateTime.Now);
else
file = new FileNode(name, parentNode, DateTime.Now, -1);
}
return file;
}
}
}