All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.goeuro.sync4j.fs.FileSystemProvider Maven / Gradle / Ivy

There is a newer version: 0.14
Show newest version
package com.goeuro.sync4j.fs;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.regex.Pattern;

import static com.goeuro.sync4j.fs.LocalFileSystem.defaultLocalFileSystem;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableCollection;
import static java.util.Collections.unmodifiableList;

public interface FileSystemProvider {

    @Nonnull
     FileSystem provideFor(@Nonnull T path) throws IllegalArgumentException;

    @Nonnull
     FileSystem provideFor(@Nonnull URI uri) throws IllegalArgumentException;

    @Nonnull
     FileSystem provideFor(@Nonnull String plain) throws IllegalArgumentException;

    @Nonnull
    static Builder fileSystemProvider() {
        return new Builder();
    }

    @Immutable
    class Default implements FileSystemProvider {

        private static final Pattern STARTS_WITH_SCHEME = Pattern.compile("^[a-z]+:");

        @Nonnull
        private final Collection> fileSystems;
        @Nonnull
        private final Optional> fallback;

        public Default(@Nonnull Collection> fileSystems, @Nonnull Optional> fallback) {
            this.fallback = fallback;
            this.fileSystems = fileSystems;
        }

        @Nonnull
        @Override
        public  FileSystem provideFor(@Nonnull T path) throws IllegalArgumentException {
            for (final FileSystem fileSystem : fileSystems()) {
                if (fileSystem.couldHandle(path)) {
                    // noinspection unchecked
                    return (FileSystem) fileSystem;
                }
            }
            //noinspection unchecked
            return fallback
                .filter(fileSystem -> fileSystem.couldHandle(path))
                .map(fileSystem -> (FileSystem) fileSystem)
                .orElseThrow(() -> new IllegalArgumentException("There is no fileSystem that could handle: " + path));
        }

        @Nonnull
        @Override
        public  FileSystem provideFor(@Nonnull URI uri) throws IllegalArgumentException {
            for (final FileSystem fileSystem : fileSystems()) {
                if (fileSystem.couldHandle(uri)) {
                    // noinspection unchecked
                    return (FileSystem) fileSystem;
                }
            }
            //noinspection unchecked
            return fallback
                .filter(fileSystem -> fileSystem.couldHandle(uri))
                .map(fileSystem -> (FileSystem) fileSystem)
                .orElseThrow(() -> new IllegalArgumentException("There is no fileSystem that could handle: " + uri));
        }

        @Nonnull
        @Override
        public  FileSystem provideFor(@Nonnull String plain) {
            //noinspection unchecked
            return toUri(plain)
                .>map(this::provideFor)
                .orElseGet(() -> fallback
                    .map(fileSystem -> (FileSystem) fileSystem)
                    .orElseThrow(() -> new IllegalArgumentException("There is no fileSystem that could handle: " + plain))
                );
        }

        @Nonnull
        protected Optional toUri(@Nonnull String plain) {
            if (!STARTS_WITH_SCHEME.matcher(plain).find()) {
                return Optional.empty();
            }
            try {
                return Optional.of(new URI(plain));
            } catch (final URISyntaxException ignored) {
                return Optional.empty();
            }
        }

        @Nonnull
        protected Collection> fileSystems() {
            return fileSystems;
        }

        @Nonnull
        protected Optional> fallback() {
            return fallback;
        }
    }

    class Builder {

        @Nonnull
        protected static final List> DEFAULTS = loadDefaults();

        @Nonnull
        private static List> loadDefaults() {
            final List> result = new ArrayList<>();
            for (final FileSystem candidate : ServiceLoader.load(FileSystem.class)) {
                result.add(candidate);
            }
            return unmodifiableList(result);
        }

        @Nonnull
        private final List> fileSystems = new ArrayList<>();
        @Nonnull
        private Optional> fallback = Optional.of(defaultLocalFileSystem());

        @Nonnull
        public Builder withDefaults() {
            fileSystems.addAll(DEFAULTS);
            return this;
        }

        @Nonnull
        public Builder with(@Nonnull Iterable> fileSystems) {
            fileSystems.forEach(this.fileSystems::add);
            return this;
        }

        @Nonnull
        public Builder with(@Nonnull FileSystem... fileSystems) {
            return with(asList(fileSystems));
        }

        @Nonnull
        public Builder withFallback(@Nullable FileSystem fallback) {
            this.fallback = Optional.ofNullable(fallback);
            return this;
        }

        @Nonnull
        public FileSystemProvider build() {
            return new Default(
                unmodifiableCollection(fileSystems),
                fallback
            );
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy