package sk.stuba.fiit.perconik.utilities.io; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.LinkOption; import java.nio.file.Path; import java.util.Arrays; import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.google.common.base.Function; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.propagate; public final class PathFunctions { private PathFunctions() {} private static <T extends Path> Function<T, T> castWhole(final Function<? extends Path, ? extends Path> function) { // only for stateless internal singletons shared across all types @SuppressWarnings("unchecked") Function<T, T> result = (Function<T, T>) function; return result; } private static <T extends Path, R> Function<T, R> castInput(final Function<? extends Path, R> function) { // only for stateless internal singletons shared across all types @SuppressWarnings("unchecked") Function<T, R> result = (Function<T, R>) function; return result; } public static <T extends Path> Function<T, T> normalize() { return castWhole(NormalizeFunction.INSTANCE); } public static <T extends Path> Function<T, T> relativize(final T path) { return castWhole(new RelativizeFunction(path)); } public static <T extends Path> Function<T, T> resolve(final T path) { return castWhole(new ResolveFunction(path)); } public static <T extends Path> Function<T, T> resolveSibling(final T path) { return castWhole(new ResolveSiblingFunction(path)); } enum NormalizeFunction implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { return path.normalize(); } // TODO add toString } static final class RelativizeFunction implements Function<Path, Path>, Serializable { private static final long serialVersionUID = 0L; final Path path; public RelativizeFunction(final Path path) { this.path = checkNotNull(path); } public Path apply(@Nullable final Path path) { return path != null ? path.relativize(this.path) : null; } // TODO add equals, hashCode, toString } static final class ResolveFunction implements Function<Path, Path>, Serializable { private static final long serialVersionUID = 0L; final Path path; public ResolveFunction(final Path path) { this.path = checkNotNull(path); } public Path apply(@Nullable final Path path) { return path != null ? path.resolve(this.path) : null; } // TODO add equals, hashCode, toString } static final class ResolveSiblingFunction implements Function<Path, Path>, Serializable { private static final long serialVersionUID = 0L; final Path path; public ResolveSiblingFunction(final Path path) { this.path = checkNotNull(path); } public Path apply(@Nullable final Path path) { return path != null ? path.resolveSibling(this.path) : null; } // TODO add equals, hashCode, toString } public static <T extends Path> Function<T, T> name(final int index) { return castWhole(new NameFunction(index)); } public static <T extends Path> Function<T, Integer> nameCount() { return castInput(NameCountFunction.INSTANCE); } static final class NameFunction implements Function<Path, Path>, Serializable { private static final long serialVersionUID = 0L; private final int index; NameFunction(final int index) { checkArgument(index >= 0); this.index = index; } public Path apply(@Nullable final Path path) { return path != null ? path.getName(this.index) : null; } // TODO add equals, hashCode, toString } enum NameCountFunction implements Function<Path, Integer> { INSTANCE; public Integer apply(@Nonnull final Path path) { return path.getNameCount(); } // TODO add toString } public static <T extends Path> Function<T, T> root() { return castWhole(RootFunction.INSTANCE); } public static <T extends Path> Function<T, T> parent() { return castWhole(ParentFunction.INSTANCE); } public static <T extends Path> Function<T, T> fileName() { return castWhole(FileNameFunction.INSTANCE); } public static <T extends Path> Function<T, FileSystem> fileSystem() { return castInput(FileSystemFunction.INSTANCE); } enum RootFunction implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { return path.getRoot(); } // TODO add toString } enum ParentFunction implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { return path.getParent(); } // TODO add toString } enum FileNameFunction implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { return path.getFileName(); } // TODO add toString } enum FileSystemFunction implements Function<Path, FileSystem> { INSTANCE; public FileSystem apply(@Nonnull final Path path) { return path.getFileSystem(); } // TODO add toString } public static <T extends Path> Function<T, T> toAbsolutePath() { return castWhole(ToAbsolutePathFunction.INSTANCE); } public static <T extends Path> Function<T, T> toRealPath() { return castWhole(ToRealPathFunction.Default.INSTANCE); } public static <T extends Path> Function<T, T> toRealPath(final LinkOption ... options) { return castWhole(new ToRealPathFunction(options)); } public static <T extends Path> Function<T, File> toFile() { return castInput(ToFileFunction.INSTANCE); } public static <T extends Path> Function<T, URI> toUri() { return castInput(ToUriFunction.INSTANCE); } enum ToAbsolutePathFunction implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { return path.toAbsolutePath(); } // TODO add toString } static final class ToRealPathFunction implements Function<Path, Path>, Serializable { private static final long serialVersionUID = 0L; private final LinkOption[] options; ToRealPathFunction(final LinkOption ... options) { this.options = Arrays.copyOf(options, options.length); } public Path apply(@Nonnull final Path path) { try { return path.toRealPath(this.options); } catch (IOException e) { throw propagate(e); } } enum Default implements Function<Path, Path> { INSTANCE; public Path apply(@Nonnull final Path path) { try { return path.toRealPath(); } catch (IOException e) { throw propagate(e); } } // TODO add toString } // TODO add equals, hashCode, toString } enum ToFileFunction implements Function<Path, File> { INSTANCE; public File apply(@Nonnull final Path path) { return path.toFile(); } // TODO add toString } enum ToUriFunction implements Function<Path, URI> { INSTANCE; public URI apply(@Nonnull final Path path) { return path.toUri(); } // TODO add toString } }