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

io.neba.core.util.ResourcePaths Maven / Gradle / Ivy

Go to download

Contains the entire NEBA core implementation, i.e. the framework that interprets the NEBA API annotations and provides implementations for the service and lifecycle callback interfaces provided in the NEBA API. This package must not export anything as its implementation details are entirely private.

There is a newer version: 5.2.3
Show newest version
package io.neba.core.util;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.Collections.singletonList;
import static java.util.regex.Pattern.compile;

/**
 * A factory for {@link ResourcePath paths}.
 */
public class ResourcePaths {
    private static final String MATCH_NAME = "placeholder";
    private static final Pattern PLACEHOLDER = compile("\\$\\{(?<" + MATCH_NAME + ">[^}|\\s]+)}");

    /**
     * @param path must not be null.
     * @return never null.
     */
    public static ResourcePath path(String path) {
        if (path == null) {
            throw new IllegalArgumentException("Method argument path must not be null");
        }

        if (PLACEHOLDER.matcher(path).find()) {
            return new PathWithPlaceholders(path);
        }
        return new PathWithoutPlaceholders(path);
    }

    /**
     * Represents a path consisting of segments that may represent placeholders of the form
     * ${name} which can be resolved via {@link ResourcePath#resolve(Function)}.
     *
     * @author Olaf Otto
     */
    public interface ResourcePath {
        default boolean hasPlaceholders() {
            return false;
        }

        /**
         * @param resolver must not be null.
         * @return a path with resolved segments, never null.
         */
        ResourcePath resolve(Function resolver);

        String getPath();
    }

    private static class PathWithPlaceholders implements ResourcePath {
        private final List segments;

        private PathWithPlaceholders(String path) {
            this(segments(path));
        }

        private PathWithPlaceholders(List segments) {
            this.segments = segments;
        }

        public ResourcePath resolve(Function placeholderResolver) {
            if (placeholderResolver == null) {
                throw new IllegalArgumentException("Method argument placeholderResolver must not be null");
            }

            return new PathWithoutPlaceholders(
                    this.segments
                            .stream()
                            .map(s -> s.isPlaceholder() ? new Value(placeholderResolver.apply(s.value)) : s)
                            .map(Value::getValue)
                            .reduce("", String::concat));
        }

        @Override
        public String getPath() {
            return this.segments.stream().map(Value::getValue).reduce("", String::concat);
        }

        @Override
        public String toString() {
            return getPath();
        }

        public boolean hasPlaceholders() {
            return true;
        }

        private static class Value {
            private final String value;

            private Value(String value) {
                this.value = value;
            }

            public String getValue() {
                return this.value;
            }

            public boolean isPlaceholder() {
                return false;
            }
        }

        private static class Placeholder extends Value {
            private Placeholder(String value) {
                super(value);
            }

            @Override
            public String getValue() {
                return "${" + super.getValue() + '}';
            }

            @Override
            public boolean isPlaceholder() {
                return true;
            }
        }

        private static List segments(String path) {
            final Matcher matcher = PLACEHOLDER.matcher(path);
            if (!matcher.find()) {
                return singletonList(new Value(path));
            }
            List segments = new ArrayList<>(4);
            int last = 0;
            do {
                if (matcher.start() != 0) {
                    segments.add(new Value(path.substring(last, matcher.start())));
                }
                segments.add(new Placeholder(matcher.group(MATCH_NAME)));
                last = matcher.end();
            } while (matcher.find());

            if (last != path.length()) {
                segments.add(new Value(path.substring(last)));
            }
            return segments;

        }
    }

    private static class PathWithoutPlaceholders implements ResourcePath {
        private final String path;

        private PathWithoutPlaceholders(String path) {
            this.path = path;
        }

        @Override
        public ResourcePath resolve(Function resolver) {
            return this;
        }

        @Override
        public String toString() {
            return this.path;
        }

        @Override
        public String getPath() {
            return path;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy