public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            VirtualFile file = owner.Value <VirtualFile>();

            if (file != null)
            {
                if (key == EntityKeys.PathKey)
                {
                    return(owner.Create(key, file.Parent.FullName));
                }

                if (file.HasPropertyValueEntity(MapFileAccessKey(key)))
                {
                    return(owner.PropertyValueEntity(MapFileAccessKey(key), file, key));
                }
            }

            VirtualDirectory directory = owner.Value <VirtualDirectory>();

            if (directory != null)
            {
                if (key == EntityKeys.PathKey)
                {
                    return(owner.Create(key, directory.FullName));
                }

                if (directory.HasPropertyValueEntity(MapFileAccessKey(key)))
                {
                    return(owner.PropertyValueEntity(MapFileAccessKey(key), directory, key));
                }
            }

            switch (key)
            {
            case EntityKeys.NewlineKey:
                return(owner.Create(key, Environment.NewLine));

            case EntityKeys.ActiveDirectoryKey:
                return(owner.Create(key, fileSystem.CurrentDirectory.FullName));

            case EntityKeys.IsRootedKey:
                bool isRooted = fileSystem.IsRooted(owner.Value <string>());
                return(owner.Create(key, isRooted.ToString(CultureInfo.InvariantCulture), isRooted));

            case EntityKeys.InternalDirectoryKey:
                string path = owner.HasValue <string>() &&
                              fileSystem.DirectoryExists(owner.Value <string>())
                                      ? owner.Value <string>()
                                      : owner.Path;
                return(owner.Create(key, fileSystem.GetDirectory(path, createNew: false)));

            case EntityKeys.InternalTempDirectoryKey:
                return(owner.Create(key, TempDirectory));

            case EntityKeys.ChunkStartKey:
                return(owner.Create(key, owner.Value <DataChunk>().Start));

            case EntityKeys.ChunkEndKey:
                return(owner.Create(key, owner.Value <DataChunk>().End));

            case EntityKeys.CountKey:
                return(owner.Create(key, owner.Count.ToString(CultureInfo.InvariantCulture), owner.Count));

            default:
                throw new ContentProviderException(key, owner);
            }
        }
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            VirtualFile file = owner.Value <VirtualFile>();

            if (file != null)
            {
                if (key == EntityKeys.PathKey)
                {
                    return(owner.Create(key, file.Parent.FullName));
                }

                if (file.HasPropertyValueEntity(MapFileAccessKey(key)))
                {
                    return(owner.PropertyValueEntity(MapFileAccessKey(key), file, key));
                }
            }

            VirtualDirectory directory = owner.Value <VirtualDirectory>();

            if (directory != null)
            {
                if (key == EntityKeys.PathKey)
                {
                    return(owner.Create(key, directory.FullName));
                }

                if (directory.HasPropertyValueEntity(MapFileAccessKey(key)))
                {
                    return(owner.PropertyValueEntity(MapFileAccessKey(key), directory, key));
                }
            }

            switch (key)
            {
            case EntityKeys.NewlineKey:
                return(owner.Create(key, Environment.NewLine));

            case EntityKeys.ActiveDirectoryKey:
                return(owner.Create(key, fileSystem.CurrentDirectory.FullName));

            case EntityKeys.IsRootedKey:
                bool isRooted = fileSystem.IsRooted(owner.Value <string>());
                return(owner.Create(key, isRooted.ToString(CultureInfo.InvariantCulture), isRooted));

            case EntityKeys.InternalDirectoryKey:
                string path = owner.HasValue <string>() &&
                              fileSystem.DirectoryExists(owner.Value <string>())
                                      ? owner.Value <string>()
                                      : owner.Path;
                return(owner.Create(key, fileSystem.GetDirectory(path, createNew: false)));

            case EntityKeys.InternalTempDirectoryKey:
                return(owner.Create(key, TempDirectory));

            case EntityKeys.ChunkStartKey:
                return(owner.Create(key, owner.Value <DataChunk>().Start));

            case EntityKeys.ChunkEndKey:
                return(owner.Create(key, owner.Value <DataChunk>().End));

            case EntityKeys.CountKey:
                return(owner.Create(key, owner.Count.ToString(CultureInfo.InvariantCulture), owner.Count));

            case EntityKeys.IncrementKey:
                return(IncrementValue());

            case EntityKeys.DecrementKey:
                return(DecrementValue());

            case EntityKeys.NegateKey:
                if (bool.TryParse(owner.Value <string>(), out bool value))
                {
                    return(owner.Create(key, (!value).ToString(CultureInfo.InvariantCulture), !value));
                }
                throw new ContentProviderException(key, owner);

            case EntityKeys.OriginKey:
                return(owner.Origin);

            case EntityKeys.ThrowIfMultidimensionalKey:
                if (owner.Value <string>()?.Contains(",") == true)
                {
                    throw new MultidimensionalArrayNotSupportedException();
                }
                return(owner);

            default:
                throw new ContentProviderException(key, owner);

                Entity IncrementValue()
                {
                    string number = owner.Value <string>();

                    if (number != null)
                    {
                        if (int.TryParse(number, out int result))
                        {
                            result++;
                            return(owner.Create(key, result.ToString(CultureInfo.InvariantCulture), result));
                        }
                    }

                    return(owner.Create(key, number));
                }

                Entity DecrementValue()
                {
                    string number = owner.Value <string>();

                    if (number != null)
                    {
                        if (int.TryParse(number, out int result))
                        {
                            result--;
                            return(owner.Create(key, result.ToString(CultureInfo.InvariantCulture), result));
                        }
                    }

                    return(owner.Create(key, number));
                }
            }
        }