org.springframework.util.MultiValueMap

Here are the examples of the java api org.springframework.util.MultiValueMap taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

1603 Examples 7

19 Source : TestPropertyMapper.java
with Apache License 2.0
from yuanmabiji

/**
 * Test {@link PropertyMapper} implementation.
 */
clreplaced TestPropertyMapper implements PropertyMapper {

    private MultiValueMap<String, PropertyMapping> fromSource = new LinkedMultiValueMap<>();

    private MultiValueMap<ConfigurationPropertyName, PropertyMapping> fromConfig = new LinkedMultiValueMap<>();

    public void addFromPropertySource(String from, String... to) {
        for (String configurationPropertyName : to) {
            this.fromSource.add(from, new PropertyMapping(from, ConfigurationPropertyName.of(configurationPropertyName)));
        }
    }

    public void addFromConfigurationProperty(ConfigurationPropertyName from, String... to) {
        for (String propertySourceName : to) {
            this.fromConfig.add(from, new PropertyMapping(propertySourceName, from));
        }
    }

    @Override
    public PropertyMapping[] map(String propertySourceName) {
        return this.fromSource.getOrDefault(propertySourceName, Collections.emptyList()).toArray(new PropertyMapping[0]);
    }

    @Override
    public PropertyMapping[] map(ConfigurationPropertyName configurationPropertyName) {
        return this.fromConfig.getOrDefault(configurationPropertyName, Collections.emptyList()).toArray(new PropertyMapping[0]);
    }
}

19 Source : ConfigurationPropertyNameAliases.java
with Apache License 2.0
from yuanmabiji

/**
 * Maintains a mapping of {@link ConfigurationPropertyName} aliases.
 *
 * @author Phillip Webb
 * @author Madhura Bhave
 * @since 2.0.0
 * @see ConfigurationPropertySource#withAliases(ConfigurationPropertyNameAliases)
 */
public final clreplaced ConfigurationPropertyNameAliases implements Iterable<ConfigurationPropertyName> {

    private final MultiValueMap<ConfigurationPropertyName, ConfigurationPropertyName> aliases = new LinkedMultiValueMap<>();

    public ConfigurationPropertyNameAliases() {
    }

    public ConfigurationPropertyNameAliases(String name, String... aliases) {
        addAliases(name, aliases);
    }

    public ConfigurationPropertyNameAliases(ConfigurationPropertyName name, ConfigurationPropertyName... aliases) {
        addAliases(name, aliases);
    }

    public void addAliases(String name, String... aliases) {
        replacedert.notNull(name, "Name must not be null");
        replacedert.notNull(aliases, "Aliases must not be null");
        addAliases(ConfigurationPropertyName.of(name), Arrays.stream(aliases).map(ConfigurationPropertyName::of).toArray(ConfigurationPropertyName[]::new));
    }

    public void addAliases(ConfigurationPropertyName name, ConfigurationPropertyName... aliases) {
        replacedert.notNull(name, "Name must not be null");
        replacedert.notNull(aliases, "Aliases must not be null");
        this.aliases.addAll(name, Arrays.asList(aliases));
    }

    public List<ConfigurationPropertyName> getAliases(ConfigurationPropertyName name) {
        return this.aliases.getOrDefault(name, Collections.emptyList());
    }

    public ConfigurationPropertyName getNameForAlias(ConfigurationPropertyName alias) {
        return this.aliases.entrySet().stream().filter((e) -> e.getValue().contains(alias)).map(Map.Entry::getKey).findFirst().orElse(null);
    }

    @Override
    public Iterator<ConfigurationPropertyName> iterator() {
        return this.aliases.keySet().iterator();
    }
}

19 Source : MapUtil.java
with GNU General Public License v3.0
from wehotel

public static MultiValueMap<String, String> toMultiValueMap(Map<String, Object> params) {
    MultiValueMap<String, String> mvmap = new LinkedMultiValueMap<>();
    if (params.isEmpty()) {
        return mvmap;
    }
    for (Entry<String, Object> entry : params.entrySet()) {
        Object val = entry.getValue();
        List<String> list = new ArrayList<>();
        if (val instanceof List) {
            List<Object> vals = (List<Object>) val;
            for (Object value : vals) {
                if (value != null) {
                    list.add(value.toString());
                }
            }
        } else {
            if (val != null) {
                list.add(val.toString());
            }
        }
        if (list.size() > 0) {
            mvmap.put(entry.getKey(), list);
        }
    }
    return mvmap;
}

19 Source : FlashMap.java
with MIT License
from Vip-Augus

/**
 * A FlashMap provides a way for one request to store attributes intended for
 * use in another. This is most commonly needed when redirecting from one URL
 * to another -- e.g. the Post/Redirect/Get pattern. A FlashMap is saved before
 * the redirect (typically in the session) and is made available after the
 * redirect and removed immediately.
 *
 * <p>A FlashMap can be set up with a request path and request parameters to
 * help identify the target request. Without this information, a FlashMap is
 * made available to the next request, which may or may not be the intended
 * recipient. On a redirect, the target URL is known and a FlashMap can be
 * updated with that information. This is done automatically when the
 * {@code org.springframework.web.servlet.view.RedirectView} is used.
 *
 * <p>Note: annotated controllers will usually not use FlashMap directly.
 * See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes}
 * for an overview of using flash attributes in annotated controllers.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @see FlashMapManager
 */
@SuppressWarnings("serial")
public final clreplaced FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {

    @Nullable
    private String targetRequestPath;

    private final MultiValueMap<String, String> targetRequestParams = new LinkedMultiValueMap<>(4);

    private long expirationTime = -1;

    /**
     * Provide a URL path to help identify the target request for this FlashMap.
     * <p>The path may be absolute (e.g. "/application/resource") or relative to the
     * current request (e.g. "../resource").
     */
    public void setTargetRequestPath(@Nullable String path) {
        this.targetRequestPath = path;
    }

    /**
     * Return the target URL path (or {@code null} if none specified).
     */
    @Nullable
    public String getTargetRequestPath() {
        return this.targetRequestPath;
    }

    /**
     * Provide request parameters identifying the request for this FlashMap.
     * @param params a Map with the names and values of expected parameters
     */
    public FlashMap addTargetRequestParams(@Nullable MultiValueMap<String, String> params) {
        if (params != null) {
            params.forEach((key, values) -> {
                for (String value : values) {
                    addTargetRequestParam(key, value);
                }
            });
        }
        return this;
    }

    /**
     * Provide a request parameter identifying the request for this FlashMap.
     * @param name the expected parameter name (skipped if empty)
     * @param value the expected value (skipped if empty)
     */
    public FlashMap addTargetRequestParam(String name, String value) {
        if (StringUtils.hasText(name) && StringUtils.hasText(value)) {
            this.targetRequestParams.add(name, value);
        }
        return this;
    }

    /**
     * Return the parameters identifying the target request, or an empty map.
     */
    public MultiValueMap<String, String> getTargetRequestParams() {
        return this.targetRequestParams;
    }

    /**
     * Start the expiration period for this instance.
     * @param timeToLive the number of seconds before expiration
     */
    public void startExpirationPeriod(int timeToLive) {
        this.expirationTime = System.currentTimeMillis() + timeToLive * 1000;
    }

    /**
     * Set the expiration time for the FlashMap. This is provided for serialization
     * purposes but can also be used instead {@link #startExpirationPeriod(int)}.
     * @since 4.2
     */
    public void setExpirationTime(long expirationTime) {
        this.expirationTime = expirationTime;
    }

    /**
     * Return the expiration time for the FlashMap or -1 if the expiration
     * period has not started.
     * @since 4.2
     */
    public long getExpirationTime() {
        return this.expirationTime;
    }

    /**
     * Return whether this instance has expired depending on the amount of
     * elapsed time since the call to {@link #startExpirationPeriod}.
     */
    public boolean isExpired() {
        return (this.expirationTime != -1 && System.currentTimeMillis() > this.expirationTime);
    }

    /**
     * Compare two FlashMaps and prefer the one that specifies a target URL
     * path or has more target URL parameters. Before comparing FlashMap
     * instances ensure that they match a given request.
     */
    @Override
    public int compareTo(FlashMap other) {
        int thisUrlPath = (this.targetRequestPath != null ? 1 : 0);
        int otherUrlPath = (other.targetRequestPath != null ? 1 : 0);
        if (thisUrlPath != otherUrlPath) {
            return otherUrlPath - thisUrlPath;
        } else {
            return other.targetRequestParams.size() - this.targetRequestParams.size();
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof FlashMap)) {
            return false;
        }
        FlashMap otherFlashMap = (FlashMap) other;
        return (super.equals(otherFlashMap) && ObjectUtils.nullSafeEquals(this.targetRequestPath, otherFlashMap.targetRequestPath) && this.targetRequestParams.equals(otherFlashMap.targetRequestParams));
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.targetRequestPath);
        result = 31 * result + this.targetRequestParams.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "FlashMap [attributes=" + super.toString() + ", targetRequestPath=" + this.targetRequestPath + ", targetRequestParams=" + this.targetRequestParams + "]";
    }
}

19 Source : MockMultipartHttpServletRequest.java
with MIT License
from Vip-Augus

/**
 * Mock implementation of the
 * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
 *
 * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
 *
 * <p>Useful for testing application controllers that access multipart uploads.
 * {@link MockMultipartFile} can be used to populate these mock requests with files.
 *
 * @author Juergen Hoeller
 * @author Eric Crampton
 * @author Arjen Poutsma
 * @since 2.0
 * @see MockMultipartFile
 */
public clreplaced MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {

    private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<>();

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with a default
     * {@link MockServletContext}.
     * @see #MockMultipartHttpServletRequest(ServletContext)
     */
    public MockMultipartHttpServletRequest() {
        this(null);
    }

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
     * @param servletContext the ServletContext that the request runs in
     * (may be {@code null} to use a default {@link MockServletContext})
     */
    public MockMultipartHttpServletRequest(@Nullable ServletContext servletContext) {
        super(servletContext);
        setMethod("POST");
        setContentType("multipart/form-data");
    }

    /**
     * Add a file to this request. The parameter name from the multipart
     * form is taken from the {@link MultipartFile#getName()}.
     * @param file multipart file to be added
     */
    public void addFile(MultipartFile file) {
        replacedert.notNull(file, "MultipartFile must not be null");
        this.multipartFiles.add(file.getName(), file);
    }

    @Override
    public Iterator<String> getFileNames() {
        return this.multipartFiles.keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return this.multipartFiles.getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return this.multipartFiles.toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return new LinkedMultiValueMap<>(this.multipartFiles);
    }

    @Override
    public String getMultipartContentType(String paramOrFileName) {
        MultipartFile file = getFile(paramOrFileName);
        if (file != null) {
            return file.getContentType();
        } else {
            return null;
        }
    }

    @Override
    public HttpMethod getRequestMethod() {
        return HttpMethod.resolve(getMethod());
    }

    @Override
    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, Collections.list(getHeaders(headerName)));
        }
        return headers;
    }

    @Override
    public HttpHeaders getMultipartHeaders(String paramOrFileName) {
        String contentType = getMultipartContentType(paramOrFileName);
        if (contentType != null) {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", contentType);
            return headers;
        } else {
            return null;
        }
    }
}

19 Source : PathElement.java
with MIT License
from Vip-Augus

/**
 * Common supertype for the Ast nodes created to represent a path pattern.
 *
 * @author Andy Clement
 * @since 5.0
 */
abstract clreplaced PathElement {

    // Score related
    protected static final int WILDCARD_WEIGHT = 100;

    protected static final int CAPTURE_VARIABLE_WEIGHT = 1;

    protected static final MultiValueMap<String, String> NO_PARAMETERS = new LinkedMultiValueMap<>();

    // Position in the pattern where this path element starts
    protected final int pos;

    // The separator used in this path pattern
    protected final char separator;

    // The next path element in the chain
    @Nullable
    protected PathElement next;

    // The previous path element in the chain
    @Nullable
    protected PathElement prev;

    /**
     * Create a new path element.
     * @param pos the position where this path element starts in the pattern data
     * @param separator the separator in use in the path pattern
     */
    PathElement(int pos, char separator) {
        this.pos = pos;
        this.separator = separator;
    }

    /**
     * Attempt to match this path element.
     * @param candidatePos the current position within the candidate path
     * @param matchingContext encapsulates context for the match including the candidate
     * @return {@code true} if it matches, otherwise {@code false}
     */
    public abstract boolean matches(int candidatePos, MatchingContext matchingContext);

    /**
     * Return the length of the path element where captures are considered to be one character long.
     * @return the normalized length
     */
    public abstract int getNormalizedLength();

    public abstract char[] getChars();

    /**
     * Return the number of variables captured by the path element.
     */
    public int getCaptureCount() {
        return 0;
    }

    /**
     * Return the number of wildcard elements (*, ?) in the path element.
     */
    public int getWildcardCount() {
        return 0;
    }

    /**
     * Return the score for this PathElement, combined score is used to compare parsed patterns.
     */
    public int getScore() {
        return 0;
    }

    /**
     * Return if the there are no more PathElements in the pattern.
     * @return {@code true} if the there are no more elements
     */
    protected final boolean isNoMorePattern() {
        return this.next == null;
    }
}

19 Source : OpaqueUriComponents.java
with MIT License
from Vip-Augus

/**
 * Extension of {@link UriComponents} for opaque URIs.
 *
 * @author Arjen Poutsma
 * @author Phillip Webb
 * @since 3.2
 * @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical vs Opaque URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced OpaqueUriComponents extends UriComponents {

    private static final MultiValueMap<String, String> QUERY_PARAMS_NONE = new LinkedMultiValueMap<>();

    @Nullable
    private final String ssp;

    OpaqueUriComponents(@Nullable String scheme, @Nullable String schemeSpecificPart, @Nullable String fragment) {
        super(scheme, fragment);
        this.ssp = schemeSpecificPart;
    }

    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return this.ssp;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return null;
    }

    @Override
    @Nullable
    public String getHost() {
        return null;
    }

    @Override
    public int getPort() {
        return -1;
    }

    @Override
    @Nullable
    public String getPath() {
        return null;
    }

    @Override
    public List<String> getPathSegments() {
        return Collections.emptyList();
    }

    @Override
    @Nullable
    public String getQuery() {
        return null;
    }

    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return QUERY_PARAMS_NONE;
    }

    @Override
    public UriComponents encode(Charset charset) {
        return this;
    }

    @Override
    protected UriComponents expandInternal(UriTemplateVariables uriVariables) {
        String expandedScheme = expandUriComponent(getScheme(), uriVariables);
        String expandedSsp = expandUriComponent(getSchemeSpecificPart(), uriVariables);
        String expandedFragment = expandUriComponent(getFragment(), uriVariables);
        return new OpaqueUriComponents(expandedScheme, expandedSsp, expandedFragment);
    }

    @Override
    public UriComponents normalize() {
        return this;
    }

    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme());
            uriBuilder.append(':');
        }
        if (this.ssp != null) {
            uriBuilder.append(this.ssp);
        }
        if (getFragment() != null) {
            uriBuilder.append('#');
            uriBuilder.append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            return new URI(getScheme(), this.ssp, getFragment());
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getSchemeSpecificPart() != null) {
            builder.schemeSpecificPart(getSchemeSpecificPart());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof OpaqueUriComponents)) {
            return false;
        }
        OpaqueUriComponents otherComp = (OpaqueUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(this.ssp, otherComp.ssp) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.ssp);
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }
}

19 Source : HierarchicalUriComponents.java
with MIT License
from Vip-Augus

/**
 * Extension of {@link UriComponents} for hierarchical URIs.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @author Rossen Stoyanchev
 * @author Phillip Webb
 * @since 3.1.3
 * @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced HierarchicalUriComponents extends UriComponents {

    private static final char PATH_DELIMITER = '/';

    private static final String PATH_DELIMITER_STRING = "/";

    private static final MultiValueMap<String, String> EMPTY_QUERY_PARAMS = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>());

    /**
     * Represents an empty path.
     */
    static final PathComponent NULL_PATH_COMPONENT = new PathComponent() {

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

        @Override
        public List<String> getPathSegments() {
            return Collections.emptyList();
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            return this;
        }

        @Override
        public void verify() {
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            return this;
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        }

        @Override
        public boolean equals(Object other) {
            return (this == other);
        }

        @Override
        public int hashCode() {
            return getClreplaced().hashCode();
        }
    };

    @Nullable
    private final String userInfo;

    @Nullable
    private final String host;

    @Nullable
    private final String port;

    private final PathComponent path;

    private final MultiValueMap<String, String> queryParams;

    private final EncodeState encodeState;

    @Nullable
    private UnaryOperator<String> variableEncoder;

    /**
     * Package-private constructor. All arguments are optional, and can be {@code null}.
     * @param scheme the scheme
     * @param userInfo the user info
     * @param host the host
     * @param port the port
     * @param path the path
     * @param query the query parameters
     * @param fragment the fragment
     * @param encoded whether the components are already encoded
     */
    HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, @Nullable PathComponent path, @Nullable MultiValueMap<String, String> query, boolean encoded) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path != null ? path : NULL_PATH_COMPONENT;
        this.queryParams = query != null ? CollectionUtils.unmodifiableMultiValueMap(query) : EMPTY_QUERY_PARAMS;
        this.encodeState = encoded ? EncodeState.FULLY_ENCODED : EncodeState.RAW;
        // Check for illegal characters..
        if (encoded) {
            verify();
        }
    }

    private HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, PathComponent path, MultiValueMap<String, String> queryParams, EncodeState encodeState, @Nullable UnaryOperator<String> variableEncoder) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path;
        this.queryParams = queryParams;
        this.encodeState = encodeState;
        this.variableEncoder = variableEncoder;
    }

    // Component getters
    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return null;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return this.userInfo;
    }

    @Override
    @Nullable
    public String getHost() {
        return this.host;
    }

    @Override
    public int getPort() {
        if (this.port == null) {
            return -1;
        } else if (this.port.contains("{")) {
            throw new IllegalStateException("The port contains a URI variable but has not been expanded yet: " + this.port);
        }
        return Integer.parseInt(this.port);
    }

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

    @Override
    public List<String> getPathSegments() {
        return this.path.getPathSegments();
    }

    @Override
    @Nullable
    public String getQuery() {
        if (!this.queryParams.isEmpty()) {
            StringBuilder queryBuilder = new StringBuilder();
            this.queryParams.forEach((name, values) -> {
                if (CollectionUtils.isEmpty(values)) {
                    if (queryBuilder.length() != 0) {
                        queryBuilder.append('&');
                    }
                    queryBuilder.append(name);
                } else {
                    for (Object value : values) {
                        if (queryBuilder.length() != 0) {
                            queryBuilder.append('&');
                        }
                        queryBuilder.append(name);
                        if (value != null) {
                            queryBuilder.append('=').append(value.toString());
                        }
                    }
                }
            });
            return queryBuilder.toString();
        } else {
            return null;
        }
    }

    /**
     * Return the map of query parameters. Empty if no query has been set.
     */
    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return this.queryParams;
    }

    // Encoding
    /**
     * Identical to {@link #encode()} but skipping over URI variable placeholders.
     * Also {@link #variableEncoder} is initialized with the given charset for
     * use later when URI variables are expanded.
     */
    HierarchicalUriComponents encodeTemplate(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        // Remember the charset to encode URI variables later..
        this.variableEncoder = value -> encodeUriComponent(value, charset, Type.URI);
        UriTemplateEncoder encoder = new UriTemplateEncoder(charset);
        String schemeTo = (getScheme() != null ? encoder.apply(getScheme(), Type.SCHEME) : null);
        String fragmentTo = (getFragment() != null ? encoder.apply(getFragment(), Type.FRAGMENT) : null);
        String userInfoTo = (getUserInfo() != null ? encoder.apply(getUserInfo(), Type.USER_INFO) : null);
        String hostTo = (getHost() != null ? encoder.apply(getHost(), getHostType()) : null);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.TEMPLATE_ENCODED, this.variableEncoder);
    }

    @Override
    public HierarchicalUriComponents encode(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        String scheme = getScheme();
        String fragment = getFragment();
        String schemeTo = (scheme != null ? encodeUriComponent(scheme, charset, Type.SCHEME) : null);
        String fragmentTo = (fragment != null ? encodeUriComponent(fragment, charset, Type.FRAGMENT) : null);
        String userInfoTo = (this.userInfo != null ? encodeUriComponent(this.userInfo, charset, Type.USER_INFO) : null);
        String hostTo = (this.host != null ? encodeUriComponent(this.host, charset, getHostType()) : null);
        BiFunction<String, Type, String> encoder = (s, type) -> encodeUriComponent(s, charset, type);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.FULLY_ENCODED, null);
    }

    private MultiValueMap<String, String> encodeQueryParams(BiFunction<String, Type, String> encoder) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        this.queryParams.forEach((key, values) -> {
            String name = encoder.apply(key, Type.QUERY_PARAM);
            List<String> encodedValues = new ArrayList<>(values.size());
            for (String value : values) {
                encodedValues.add(value != null ? encoder.apply(value, Type.QUERY_PARAM) : null);
            }
            result.put(name, encodedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param encoding the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, String encoding, Type type) {
        return encodeUriComponent(source, Charset.forName(encoding), type);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param charset the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, Charset charset, Type type) {
        if (!StringUtils.hasLength(source)) {
            return source;
        }
        replacedert.notNull(charset, "Charset must not be null");
        replacedert.notNull(type, "Type must not be null");
        byte[] bytes = source.getBytes(charset);
        ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
        boolean changed = false;
        for (byte b : bytes) {
            if (b < 0) {
                b += 256;
            }
            if (type.isAllowed(b)) {
                bos.write(b);
            } else {
                bos.write('%');
                char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
                char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
                bos.write(hex1);
                bos.write(hex2);
                changed = true;
            }
        }
        return (changed ? new String(bos.toByteArray(), charset) : source);
    }

    private Type getHostType() {
        return (this.host != null && this.host.startsWith("[") ? Type.HOST_IPV6 : Type.HOST_IPV4);
    }

    // Verifying
    /**
     * Check if any of the URI components contain any illegal characters.
     * @throws IllegalArgumentException if any component has illegal characters
     */
    private void verify() {
        verifyUriComponent(getScheme(), Type.SCHEME);
        verifyUriComponent(this.userInfo, Type.USER_INFO);
        verifyUriComponent(this.host, getHostType());
        this.path.verify();
        this.queryParams.forEach((key, values) -> {
            verifyUriComponent(key, Type.QUERY_PARAM);
            for (String value : values) {
                verifyUriComponent(value, Type.QUERY_PARAM);
            }
        });
        verifyUriComponent(getFragment(), Type.FRAGMENT);
    }

    private static void verifyUriComponent(@Nullable String source, Type type) {
        if (source == null) {
            return;
        }
        int length = source.length();
        for (int i = 0; i < length; i++) {
            char ch = source.charAt(i);
            if (ch == '%') {
                if ((i + 2) < length) {
                    char hex1 = source.charAt(i + 1);
                    char hex2 = source.charAt(i + 2);
                    int u = Character.digit(hex1, 16);
                    int l = Character.digit(hex2, 16);
                    if (u == -1 || l == -1) {
                        throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                    }
                    i += 2;
                } else {
                    throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                }
            } else if (!type.isAllowed(ch)) {
                throw new IllegalArgumentException("Invalid character '" + ch + "' for " + type.name() + " in \"" + source + "\"");
            }
        }
    }

    // Expanding
    @Override
    protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
        replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
        // Array-based vars rely on the below order..
        String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
        String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
        String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
        String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
        PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
        MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
        String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
    }

    private MultiValueMap<String, String> expandQueryParams(UriTemplateVariables variables) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables);
        this.queryParams.forEach((key, values) -> {
            String name = expandUriComponent(key, queryVariables, this.variableEncoder);
            List<String> expandedValues = new ArrayList<>(values.size());
            for (String value : values) {
                expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder));
            }
            result.put(name, expandedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    @Override
    public UriComponents normalize() {
        String normalizedPath = StringUtils.cleanPath(getPath());
        FullPathComponent path = new FullPathComponent(normalizedPath);
        return new HierarchicalUriComponents(getScheme(), getFragment(), this.userInfo, this.host, this.port, path, this.queryParams, this.encodeState, this.variableEncoder);
    }

    // Other functionality
    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme()).append(':');
        }
        if (this.userInfo != null || this.host != null) {
            uriBuilder.append("//");
            if (this.userInfo != null) {
                uriBuilder.append(this.userInfo).append('@');
            }
            if (this.host != null) {
                uriBuilder.append(this.host);
            }
            if (getPort() != -1) {
                uriBuilder.append(':').append(this.port);
            }
        }
        String path = getPath();
        if (StringUtils.hasLength(path)) {
            if (uriBuilder.length() != 0 && path.charAt(0) != PATH_DELIMITER) {
                uriBuilder.append(PATH_DELIMITER);
            }
            uriBuilder.append(path);
        }
        String query = getQuery();
        if (query != null) {
            uriBuilder.append('?').append(query);
        }
        if (getFragment() != null) {
            uriBuilder.append('#').append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            if (this.encodeState.isEncoded()) {
                return new URI(toUriString());
            } else {
                String path = getPath();
                if (StringUtils.hasLength(path) && path.charAt(0) != PATH_DELIMITER) {
                    // Only prefix the path delimiter if something exists before it
                    if (getScheme() != null || getUserInfo() != null || getHost() != null || getPort() != -1) {
                        path = PATH_DELIMITER + path;
                    }
                }
                return new URI(getScheme(), getUserInfo(), getHost(), getPort(), path, getQuery(), getFragment());
            }
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getUserInfo() != null) {
            builder.userInfo(getUserInfo());
        }
        if (getHost() != null) {
            builder.host(getHost());
        }
        // Avoid parsing the port, may have URI variable..
        if (this.port != null) {
            builder.port(this.port);
        }
        this.path.copyToUriComponentsBuilder(builder);
        if (!getQueryParams().isEmpty()) {
            builder.queryParams(getQueryParams());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof HierarchicalUriComponents)) {
            return false;
        }
        HierarchicalUriComponents otherComp = (HierarchicalUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(getUserInfo(), otherComp.getUserInfo()) && ObjectUtils.nullSafeEquals(getHost(), otherComp.getHost()) && getPort() == otherComp.getPort() && this.path.equals(otherComp.path) && this.queryParams.equals(otherComp.queryParams) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.userInfo);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.host);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.port);
        result = 31 * result + this.path.hashCode();
        result = 31 * result + this.queryParams.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }

    // Nested types
    /**
     * Enumeration used to identify the allowed characters per URI component.
     * <p>Contains methods to indicate whether a given character is valid in a specific URI component.
     * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
     */
    enum Type {

        SCHEME {

            @Override
            public boolean isAllowed(int c) {
                return isAlpha(c) || isDigit(c) || '+' == c || '-' == c || '.' == c;
            }
        }
        ,
        AUTHORITY {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
            }
        }
        ,
        USER_INFO {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c;
            }
        }
        ,
        HOST_IPV4 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c);
            }
        }
        ,
        HOST_IPV6 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || '[' == c || ']' == c || ':' == c;
            }
        }
        ,
        PORT {

            @Override
            public boolean isAllowed(int c) {
                return isDigit(c);
            }
        }
        ,
        PATH {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c;
            }
        }
        ,
        PATH_SEGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c);
            }
        }
        ,
        QUERY {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        QUERY_PARAM {

            @Override
            public boolean isAllowed(int c) {
                if ('=' == c || '&' == c) {
                    return false;
                } else {
                    return isPchar(c) || '/' == c || '?' == c;
                }
            }
        }
        ,
        FRAGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        URI {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c);
            }
        }
        ;

        /**
         * Indicates whether the given character is allowed in this URI component.
         * @return {@code true} if the character is allowed; {@code false} otherwise
         */
        public abstract boolean isAllowed(int c);

        /**
         * Indicates whether the given character is in the {@code ALPHA} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isAlpha(int c) {
            return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
        }

        /**
         * Indicates whether the given character is in the {@code DIGIT} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isDigit(int c) {
            return (c >= '0' && c <= '9');
        }

        /**
         * Indicates whether the given character is in the {@code gen-delims} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isGenericDelimiter(int c) {
            return (':' == c || '/' == c || '?' == c || '#' == c || '[' == c || ']' == c || '@' == c);
        }

        /**
         * Indicates whether the given character is in the {@code sub-delims} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isSubDelimiter(int c) {
            return ('!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c || ',' == c || ';' == c || '=' == c);
        }

        /**
         * Indicates whether the given character is in the {@code reserved} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isReserved(int c) {
            return (isGenericDelimiter(c) || isSubDelimiter(c));
        }

        /**
         * Indicates whether the given character is in the {@code unreserved} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isUnreserved(int c) {
            return (isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c);
        }

        /**
         * Indicates whether the given character is in the {@code pchar} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isPchar(int c) {
            return (isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c);
        }
    }

    private enum EncodeState {

        /**
         * Not encoded.
         */
        RAW,
        /**
         * URI vars expanded first and then each URI component encoded by
         * quoting only illegal characters within that URI component.
         */
        FULLY_ENCODED,
        /**
         * URI template encoded first by quoting illegal characters only, and
         * then URI vars encoded more strictly when expanded, by quoting both
         * illegal chars and chars with reserved meaning.
         */
        TEMPLATE_ENCODED;

        public boolean isEncoded() {
            return this.equals(FULLY_ENCODED) || this.equals(TEMPLATE_ENCODED);
        }
    }

    private static clreplaced UriTemplateEncoder implements BiFunction<String, Type, String> {

        private final Charset charset;

        private final StringBuilder currentLiteral = new StringBuilder();

        private final StringBuilder currentVariable = new StringBuilder();

        private final StringBuilder output = new StringBuilder();

        public UriTemplateEncoder(Charset charset) {
            this.charset = charset;
        }

        @Override
        public String apply(String source, Type type) {
            // Only URI variable (nothing to encode)..
            if (source.length() > 1 && source.charAt(0) == '{' && source.charAt(source.length() - 1) == '}') {
                return source;
            }
            // Only literal (encode full source)..
            if (source.indexOf('{') == -1) {
                return encodeUriComponent(source, this.charset, type);
            }
            // Mixed literal parts and URI variables, maybe (encode literal parts only)..
            int level = 0;
            clear(this.currentLiteral);
            clear(this.currentVariable);
            clear(this.output);
            for (char c : source.toCharArray()) {
                if (c == '{') {
                    level++;
                    if (level == 1) {
                        encodeAndAppendCurrentLiteral(type);
                    }
                }
                if (c == '}' && level > 0) {
                    level--;
                    this.currentVariable.append('}');
                    if (level == 0) {
                        this.output.append(this.currentVariable);
                        clear(this.currentVariable);
                    }
                } else if (level > 0) {
                    this.currentVariable.append(c);
                } else {
                    this.currentLiteral.append(c);
                }
            }
            if (level > 0) {
                this.currentLiteral.append(this.currentVariable);
            }
            encodeAndAppendCurrentLiteral(type);
            return this.output.toString();
        }

        private void encodeAndAppendCurrentLiteral(Type type) {
            this.output.append(encodeUriComponent(this.currentLiteral.toString(), this.charset, type));
            clear(this.currentLiteral);
        }

        private void clear(StringBuilder sb) {
            sb.delete(0, sb.length());
        }
    }

    /**
     * Defines the contract for path (segments).
     */
    interface PathComponent extends Serializable {

        String getPath();

        List<String> getPathSegments();

        PathComponent encode(BiFunction<String, Type, String> encoder);

        void verify();

        PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder);

        void copyToUriComponentsBuilder(UriComponentsBuilder builder);
    }

    /**
     * Represents a path backed by a String.
     */
    static final clreplaced FullPathComponent implements PathComponent {

        private final String path;

        public FullPathComponent(@Nullable String path) {
            this.path = (path != null ? path : "");
        }

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

        @Override
        public List<String> getPathSegments() {
            String[] segments = StringUtils.tokenizeToStringArray(getPath(), PATH_DELIMITER_STRING);
            return Collections.unmodifiableList(Arrays.asList(segments));
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            String encodedPath = encoder.apply(getPath(), Type.PATH);
            return new FullPathComponent(encodedPath);
        }

        @Override
        public void verify() {
            verifyUriComponent(getPath(), Type.PATH);
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            String expandedPath = expandUriComponent(getPath(), uriVariables, encoder);
            return new FullPathComponent(expandedPath);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.path(getPath());
        }

        @Override
        public boolean equals(Object other) {
            return (this == other || (other instanceof FullPathComponent && getPath().equals(((FullPathComponent) other).getPath())));
        }

        @Override
        public int hashCode() {
            return getPath().hashCode();
        }
    }

    /**
     * Represents a path backed by a String list (i.e. path segments).
     */
    static final clreplaced PathSegmentComponent implements PathComponent {

        private final List<String> pathSegments;

        public PathSegmentComponent(List<String> pathSegments) {
            replacedert.notNull(pathSegments, "List must not be null");
            this.pathSegments = Collections.unmodifiableList(new ArrayList<>(pathSegments));
        }

        @Override
        public String getPath() {
            String delimiter = String.valueOf(PATH_DELIMITER);
            StringJoiner pathBuilder = new StringJoiner(delimiter, delimiter, "");
            for (String pathSegment : this.pathSegments) {
                pathBuilder.add(pathSegment);
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            return this.pathSegments;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> encodedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String encodedPathSegment = encoder.apply(pathSegment, Type.PATH_SEGMENT);
                encodedPathSegments.add(encodedPathSegment);
            }
            return new PathSegmentComponent(encodedPathSegments);
        }

        @Override
        public void verify() {
            for (String pathSegment : getPathSegments()) {
                verifyUriComponent(pathSegment, Type.PATH_SEGMENT);
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> expandedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String expandedPathSegment = expandUriComponent(pathSegment, uriVariables, encoder);
                expandedPathSegments.add(expandedPathSegment);
            }
            return new PathSegmentComponent(expandedPathSegments);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.pathSegment(StringUtils.toStringArray(getPathSegments()));
        }

        @Override
        public boolean equals(Object other) {
            return (this == other || (other instanceof PathSegmentComponent && getPathSegments().equals(((PathSegmentComponent) other).getPathSegments())));
        }

        @Override
        public int hashCode() {
            return getPathSegments().hashCode();
        }
    }

    /**
     * Represents a collection of PathComponents.
     */
    static final clreplaced PathComponentComposite implements PathComponent {

        private final List<PathComponent> pathComponents;

        public PathComponentComposite(List<PathComponent> pathComponents) {
            replacedert.notNull(pathComponents, "PathComponent List must not be null");
            this.pathComponents = pathComponents;
        }

        @Override
        public String getPath() {
            StringBuilder pathBuilder = new StringBuilder();
            for (PathComponent pathComponent : this.pathComponents) {
                pathBuilder.append(pathComponent.getPath());
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            List<String> result = new ArrayList<>();
            for (PathComponent pathComponent : this.pathComponents) {
                result.addAll(pathComponent.getPathSegments());
            }
            return result;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<PathComponent> encodedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                encodedComponents.add(pathComponent.encode(encoder));
            }
            return new PathComponentComposite(encodedComponents);
        }

        @Override
        public void verify() {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.verify();
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<PathComponent> expandedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                expandedComponents.add(pathComponent.expand(uriVariables, encoder));
            }
            return new PathComponentComposite(expandedComponents);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.copyToUriComponentsBuilder(builder);
            }
        }
    }

    private static clreplaced QueryUriTemplateVariables implements UriTemplateVariables {

        private final UriTemplateVariables delegate;

        public QueryUriTemplateVariables(UriTemplateVariables delegate) {
            this.delegate = delegate;
        }

        @Override
        public Object getValue(@Nullable String name) {
            Object value = this.delegate.getValue(name);
            if (ObjectUtils.isArray(value)) {
                value = StringUtils.arrayToCommaDelimitedString(ObjectUtils.toObjectArray(value));
            }
            return value;
        }
    }
}

19 Source : HierarchicalUriComponents.java
with MIT License
from Vip-Augus

private MultiValueMap<String, String> expandQueryParams(UriTemplateVariables variables) {
    int size = this.queryParams.size();
    MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
    UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables);
    this.queryParams.forEach((key, values) -> {
        String name = expandUriComponent(key, queryVariables, this.variableEncoder);
        List<String> expandedValues = new ArrayList<>(values.size());
        for (String value : values) {
            expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder));
        }
        result.put(name, expandedValues);
    });
    return CollectionUtils.unmodifiableMultiValueMap(result);
}

19 Source : HierarchicalUriComponents.java
with MIT License
from Vip-Augus

// Expanding
@Override
protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
    replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
    // Array-based vars rely on the below order..
    String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
    String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
    String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
    String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
    PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
    MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
    String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
    return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
}

19 Source : HierarchicalUriComponents.java
with MIT License
from Vip-Augus

// Encoding
/**
 * Identical to {@link #encode()} but skipping over URI variable placeholders.
 * Also {@link #variableEncoder} is initialized with the given charset for
 * use later when URI variables are expanded.
 */
HierarchicalUriComponents encodeTemplate(Charset charset) {
    if (this.encodeState.isEncoded()) {
        return this;
    }
    // Remember the charset to encode URI variables later..
    this.variableEncoder = value -> encodeUriComponent(value, charset, Type.URI);
    UriTemplateEncoder encoder = new UriTemplateEncoder(charset);
    String schemeTo = (getScheme() != null ? encoder.apply(getScheme(), Type.SCHEME) : null);
    String fragmentTo = (getFragment() != null ? encoder.apply(getFragment(), Type.FRAGMENT) : null);
    String userInfoTo = (getUserInfo() != null ? encoder.apply(getUserInfo(), Type.USER_INFO) : null);
    String hostTo = (getHost() != null ? encoder.apply(getHost(), getHostType()) : null);
    PathComponent pathTo = this.path.encode(encoder);
    MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
    return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.TEMPLATE_ENCODED, this.variableEncoder);
}

19 Source : HierarchicalUriComponents.java
with MIT License
from Vip-Augus

private MultiValueMap<String, String> encodeQueryParams(BiFunction<String, Type, String> encoder) {
    int size = this.queryParams.size();
    MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
    this.queryParams.forEach((key, values) -> {
        String name = encoder.apply(key, Type.QUERY_PARAM);
        List<String> encodedValues = new ArrayList<>(values.size());
        for (String value : values) {
            encodedValues.add(value != null ? encoder.apply(value, Type.QUERY_PARAM) : null);
        }
        result.put(name, encodedValues);
    });
    return CollectionUtils.unmodifiableMultiValueMap(result);
}

19 Source : AbstractMultipartHttpServletRequest.java
with MIT License
from Vip-Augus

/**
 * Abstract base implementation of the MultipartHttpServletRequest interface.
 * Provides management of pre-generated MultipartFile instances.
 *
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @since 06.10.2003
 */
public abstract clreplaced AbstractMultipartHttpServletRequest extends HttpServletRequestWrapper implements MultipartHttpServletRequest {

    @Nullable
    private MultiValueMap<String, MultipartFile> multipartFiles;

    /**
     * Wrap the given HttpServletRequest in a MultipartHttpServletRequest.
     * @param request the request to wrap
     */
    protected AbstractMultipartHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public HttpServletRequest getRequest() {
        return (HttpServletRequest) super.getRequest();
    }

    @Override
    public HttpMethod getRequestMethod() {
        return HttpMethod.resolve(getRequest().getMethod());
    }

    @Override
    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, Collections.list(getHeaders(headerName)));
        }
        return headers;
    }

    @Override
    public Iterator<String> getFileNames() {
        return getMultipartFiles().keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return getMultipartFiles().getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return getMultipartFiles().toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return getMultipartFiles();
    }

    /**
     * Determine whether the underlying multipart request has been resolved.
     * @return {@code true} when eagerly initialized or lazily triggered,
     * {@code false} in case of a lazy-resolution request that got aborted
     * before any parameters or multipart files have been accessed
     * @since 4.3.15
     * @see #getMultipartFiles()
     */
    public boolean isResolved() {
        return (this.multipartFiles != null);
    }

    /**
     * Set a Map with parameter names as keys and list of MultipartFile objects as values.
     * To be invoked by subclreplacedes on initialization.
     */
    protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
        this.multipartFiles = new LinkedMultiValueMap<>(Collections.unmodifiableMap(multipartFiles));
    }

    /**
     * Obtain the MultipartFile Map for retrieval,
     * lazily initializing it if necessary.
     * @see #initializeMultipart()
     */
    protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
        if (this.multipartFiles == null) {
            initializeMultipart();
        }
        return this.multipartFiles;
    }

    /**
     * Lazily initialize the multipart request, if possible.
     * Only called if not already eagerly initialized.
     */
    protected void initializeMultipart() {
        throw new IllegalStateException("Multipart request not initialized");
    }
}

19 Source : DefaultPathContainer.java
with MIT License
from Vip-Augus

private static MultiValueMap<String, String> parsePathParams(String input, Charset charset) {
    MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
    int begin = 1;
    while (begin < input.length()) {
        int end = input.indexOf(';', begin);
        String param = (end != -1 ? input.substring(begin, end) : input.substring(begin));
        parsePathParamValues(param, charset, result);
        if (end == -1) {
            break;
        }
        begin = end + 1;
    }
    return result;
}

19 Source : MediaTypeFactory.java
with MIT License
from Vip-Augus

/**
 * A factory delegate for resolving {@link MediaType} objects
 * from {@link Resource} handles or filenames.
 *
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @since 5.0
 */
public final clreplaced MediaTypeFactory {

    private static final String MIME_TYPES_FILE_NAME = "/org/springframework/http/mime.types";

    private static final MultiValueMap<String, MediaType> fileExtensionToMediaTypes = parseMimeTypes();

    private MediaTypeFactory() {
    }

    /**
     * Parse the {@code mime.types} file found in the resources. Format is:
     * <code>
     * # comments begin with a '#'<br>
     * # the format is <mime type> <space separated file extensions><br>
     * # for example:<br>
     * text/plain    txt text<br>
     * # this would map file.txt and file.text to<br>
     * # the mime type "text/plain"<br>
     * </code>
     * @return a multi-value map, mapping media types to file extensions.
     */
    private static MultiValueMap<String, MediaType> parseMimeTypes() {
        InputStream is = MediaTypeFactory.clreplaced.getResourcereplacedtream(MIME_TYPES_FILE_NAME);
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.US_ASCII))) {
            MultiValueMap<String, MediaType> result = new LinkedMultiValueMap<>();
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.isEmpty() || line.charAt(0) == '#') {
                    continue;
                }
                String[] tokens = StringUtils.tokenizeToStringArray(line, " \t\n\r\f");
                MediaType mediaType = MediaType.parseMediaType(tokens[0]);
                for (int i = 1; i < tokens.length; i++) {
                    String fileExtension = tokens[i].toLowerCase(Locale.ENGLISH);
                    result.add(fileExtension, mediaType);
                }
            }
            return result;
        } catch (IOException ex) {
            throw new IllegalStateException("Could not load '" + MIME_TYPES_FILE_NAME + "'", ex);
        }
    }

    /**
     * Determine a media type for the given resource, if possible.
     * @param resource the resource to introspect
     * @return the corresponding media type, or {@code null} if none found
     */
    public static Optional<MediaType> getMediaType(@Nullable Resource resource) {
        return Optional.ofNullable(resource).map(Resource::getFilename).flatMap(MediaTypeFactory::getMediaType);
    }

    /**
     * Determine a media type for the given file name, if possible.
     * @param filename the file name plus extension
     * @return the corresponding media type, or {@code null} if none found
     */
    public static Optional<MediaType> getMediaType(@Nullable String filename) {
        return getMediaTypes(filename).stream().findFirst();
    }

    /**
     * Determine the media types for the given file name, if possible.
     * @param filename the file name plus extension
     * @return the corresponding media types, or an empty list if none found
     */
    public static List<MediaType> getMediaTypes(@Nullable String filename) {
        return Optional.ofNullable(StringUtils.getFilenameExtension(filename)).map(s -> s.toLowerCase(Locale.ENGLISH)).map(fileExtensionToMediaTypes::get).orElse(Collections.emptyList());
    }
}

19 Source : JsonPathRequestMatchersIntegrationTests.java
with MIT License
from Vip-Augus

/**
 * Examples of defining expectations on JSON request content with
 * <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
 *
 * @author Rossen Stoyanchev
 * @author Sam Brannen
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchers
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchersTests
 */
public clreplaced JsonPathRequestMatchersIntegrationTests {

    private static final MultiValueMap<String, Person> people = new LinkedMultiValueMap<>();

    static {
        people.add("composers", new Person("Johann Sebastian Bach"));
        people.add("composers", new Person("Johannes Brahms"));
        people.add("composers", new Person("Edvard Grieg"));
        people.add("composers", new Person("Robert Schumann"));
        people.add("performers", new Person("Vladimir Ashkenazy"));
        people.add("performers", new Person("Yehudi Menuhin"));
    }

    private final RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new MappingJackson2HttpMessageConverter()));

    private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate);

    @Test
    public void exists() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0]").exists()).andExpect(jsonPath("$.composers[1]").exists()).andExpect(jsonPath("$.composers[2]").exists()).andExpect(jsonPath("$.composers[3]").exists()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void doesNotExist() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist()).andExpect(jsonPath("$.composers[?(@.name == 'Robert Schuuuuuuman')]").doesNotExist()).andExpect(jsonPath("$.composers[4]").doesNotExist()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void value() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach")).andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin")).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchers() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))).andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))).andExpect(jsonPath("$.composers[0].name", startsWith("Johann"))).andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy"))).andExpect(jsonPath("$.performers[1].name", containsString("di Me"))).andExpect(jsonPath("$.composers[1].name", isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))).andExpect(jsonPath("$.composers[:3].name", hasItem("Johannes Brahms"))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchersWithParameterizedJsonPaths() throws Exception {
        String composerName = "$.composers[%s].name";
        String performerName = "$.performers[%s].name";
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath(composerName, 0).value(startsWith("Johann"))).andExpect(jsonPath(performerName, 0).value(endsWith("Ashkenazy"))).andExpect(jsonPath(performerName, 1).value(containsString("di Me"))).andExpect(jsonPath(composerName, 1).value(isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isArray() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers").isArray()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isString() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").isString()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isNumber() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].someDouble").isNumber()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isBoolean() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].someBoolean").isBoolean()).andRespond(withSuccess());
        executeAndVerify();
    }

    private void executeAndVerify() throws URISyntaxException {
        this.restTemplate.put(new URI("/composers"), people);
        this.mockServer.verify();
    }
}

19 Source : AbstractSubscriptionRegistry.java
with MIT License
from Vip-Augus

/**
 * Abstract base clreplaced for implementations of {@link SubscriptionRegistry} that
 * looks up information in messages but delegates to abstract methods for the
 * actual storage and retrieval.
 *
 * @author Rossen Stoyanchev
 * @since 4.0
 */
public abstract clreplaced AbstractSubscriptionRegistry implements SubscriptionRegistry {

    private static final MultiValueMap<String, String> EMPTY_MAP = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>());

    protected final Log logger = SimpLogging.forLogName(getClreplaced());

    @Override
    public final void registerSubscription(Message<?> message) {
        MessageHeaders headers = message.getHeaders();
        SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(headers);
        if (!SimpMessageType.SUBSCRIBE.equals(messageType)) {
            throw new IllegalArgumentException("Expected SUBSCRIBE: " + message);
        }
        String sessionId = SimpMessageHeaderAccessor.getSessionId(headers);
        if (sessionId == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No sessionId in  " + message);
            }
            return;
        }
        String subscriptionId = SimpMessageHeaderAccessor.getSubscriptionId(headers);
        if (subscriptionId == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No subscriptionId in " + message);
            }
            return;
        }
        String destination = SimpMessageHeaderAccessor.getDestination(headers);
        if (destination == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No destination in " + message);
            }
            return;
        }
        addSubscriptionInternal(sessionId, subscriptionId, destination, message);
    }

    @Override
    public final void unregisterSubscription(Message<?> message) {
        MessageHeaders headers = message.getHeaders();
        SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(headers);
        if (!SimpMessageType.UNSUBSCRIBE.equals(messageType)) {
            throw new IllegalArgumentException("Expected UNSUBSCRIBE: " + message);
        }
        String sessionId = SimpMessageHeaderAccessor.getSessionId(headers);
        if (sessionId == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No sessionId in " + message);
            }
            return;
        }
        String subscriptionId = SimpMessageHeaderAccessor.getSubscriptionId(headers);
        if (subscriptionId == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No subscriptionId " + message);
            }
            return;
        }
        removeSubscriptionInternal(sessionId, subscriptionId, message);
    }

    @Override
    public final MultiValueMap<String, String> findSubscriptions(Message<?> message) {
        MessageHeaders headers = message.getHeaders();
        SimpMessageType type = SimpMessageHeaderAccessor.getMessageType(headers);
        if (!SimpMessageType.MESSAGE.equals(type)) {
            throw new IllegalArgumentException("Unexpected message type: " + type);
        }
        String destination = SimpMessageHeaderAccessor.getDestination(headers);
        if (destination == null) {
            if (logger.isErrorEnabled()) {
                logger.error("No destination in " + message);
            }
            return EMPTY_MAP;
        }
        return findSubscriptionsInternal(destination, message);
    }

    protected abstract void addSubscriptionInternal(String sessionId, String subscriptionId, String destination, Message<?> message);

    protected abstract void removeSubscriptionInternal(String sessionId, String subscriptionId, Message<?> message);

    protected abstract MultiValueMap<String, String> findSubscriptionsInternal(String destination, Message<?> message);
}

19 Source : CandidateComponentsIndex.java
with MIT License
from Vip-Augus

/**
 * Provide access to the candidates that are defined in {@code META-INF/spring.components}.
 *
 * <p>An arbitrary number of stereotypes can be registered (and queried) on the index: a
 * typical example is the fully qualified name of an annotation that flags the clreplaced for
 * a certain use case. The following call returns all the {@code @Component}
 * <b>candidate</b> types for the {@code com.example} package (and its sub-packages):
 * <pre clreplaced="code">
 * Set<String> candidates = index.getCandidateTypes(
 *         "com.example", "org.springframework.stereotype.Component");
 * </pre>
 *
 * <p>The {@code type} is usually the fully qualified name of a clreplaced, though this is
 * not a rule. Similarly, the {@code stereotype} is usually the fully qualified name of
 * a target type but it can be any marker really.
 *
 * @author Stephane Nicoll
 * @since 5.0
 */
public clreplaced CandidateComponentsIndex {

    private static final AntPathMatcher pathMatcher = new AntPathMatcher(".");

    private final MultiValueMap<String, Entry> index;

    CandidateComponentsIndex(List<Properties> content) {
        this.index = parseIndex(content);
    }

    /**
     * Return the candidate types that are replacedociated with the specified stereotype.
     * @param basePackage the package to check for candidates
     * @param stereotype the stereotype to use
     * @return the candidate types replacedociated with the specified {@code stereotype}
     * or an empty set if none has been found for the specified {@code basePackage}
     */
    public Set<String> getCandidateTypes(String basePackage, String stereotype) {
        List<Entry> candidates = this.index.get(stereotype);
        if (candidates != null) {
            return candidates.parallelStream().filter(t -> t.match(basePackage)).map(t -> t.type).collect(Collectors.toSet());
        }
        return Collections.emptySet();
    }

    private static MultiValueMap<String, Entry> parseIndex(List<Properties> content) {
        MultiValueMap<String, Entry> index = new LinkedMultiValueMap<>();
        for (Properties entry : content) {
            entry.forEach((type, values) -> {
                String[] stereotypes = ((String) values).split(",");
                for (String stereotype : stereotypes) {
                    index.add(stereotype, new Entry((String) type));
                }
            });
        }
        return index;
    }

    private static clreplaced Entry {

        private final String type;

        private final String packageName;

        Entry(String type) {
            this.type = type;
            this.packageName = ClreplacedUtils.getPackageName(type);
        }

        public boolean match(String basePackage) {
            if (pathMatcher.isPattern(basePackage)) {
                return pathMatcher.match(basePackage, this.packageName);
            } else {
                return this.type.startsWith(basePackage);
            }
        }
    }
}

19 Source : IntegrationSpecificationITCase.java
with Apache License 2.0
from syndesisio

@Test
public void shouldServeOpenApiSpecificationInJsonFormat() throws IOException, JSONException {
    final MultiValueMap<Object, Object> data = specification("/io/syndesis/server/runtime/test-swagger.json");
    final ResponseEnreplacedy<Integration> integrationResponse = post("/api/v1/apis/generator", data, Integration.clreplaced, tokenRule.validToken(), HttpStatus.OK, MULTIPART);
    final Integration integration = integrationResponse.getBody();
    final String integrationId = KeyGenerator.createKey();
    dataManager.create(integration.builder().id(integrationId).build());
    final ResponseEnreplacedy<ByteArrayResource> specificationResponse = get("/api/v1/integrations/" + integrationId + "/specification", ByteArrayResource.clreplaced);
    replacedertThat(specificationResponse.getHeaders().getContentType()).isEqualTo(MediaType.valueOf("application/vnd.oai.openapi+json"));
    final String givenJson = getResourceAsText("io/syndesis/server/runtime/test-swagger.json");
    final String receivedJson = new String(specificationResponse.getBody().getByteArray(), StandardCharsets.UTF_8);
    final JSONCompareResult compareResult = JSONCompare.compareJSON(givenJson, receivedJson, JSONCompareMode.NON_EXTENSIBLE);
    replacedertThat(compareResult.getFieldMissing()).isEmpty();
    replacedertThat(compareResult.getFieldFailures()).isEmpty();
    replacedertThat(compareResult.getFieldUnexpected()).as("Backend is allowed to add missing operationId fields, found other differences").hreplacedize(3).allSatisfy(failure -> "operationId".equals(failure.getActual()));
}

19 Source : BaseCredentialProviderTest.java
with Apache License 2.0
from syndesisio

public clreplaced BaseCredentialProviderTest {

    private static final MultiValueMap<String, String> NONE = new LinkedMultiValueMap<>();

    @Test
    public void shouldGenerateCallbackUrlWithoutParameters() {
        replacedertThat(BaseCredentialProvider.callbackUrlFor(URI.create("https://syndesis.io:8443/api/v1/"), NONE)).as("The computed callback URL is not as expected").isEqualTo("https://syndesis.io:8443/api/v1/credentials/callback");
    }

    @Test
    public void shouldGenerateCallbackUrlWithParameters() {
        final MultiValueMap<String, String> some = new LinkedMultiValueMap<>();
        some.set("param1", "value1");
        some.set("param2", "value2");
        replacedertThat(BaseCredentialProvider.callbackUrlFor(URI.create("https://syndesis.io/api/v1/"), some)).as("The computed callback URL is not as expected").isEqualTo("https://syndesis.io/api/v1/credentials/callback?param1=value1¶m2=value2");
    }
}

19 Source : BaseCredentialProvider.java
with Apache License 2.0
from syndesisio

abstract clreplaced BaseCredentialProvider implements CredentialProvider {

    protected static final MultiValueMap<String, String> EMPTY = new LinkedMultiValueMap<>();

    protected static String callbackUrlFor(final URI baseUrl, final MultiValueMap<String, String> additionalParams) {
        final String path = baseUrl.getPath();
        final String callbackPath = path + "credentials/callback";
        try {
            final URI base = new URI(baseUrl.getScheme(), null, baseUrl.getHost(), baseUrl.getPort(), callbackPath, null, null);
            return UriComponentsBuilder.fromUri(base).queryParams(additionalParams).build().toUriString();
        } catch (final URISyntaxException e) {
            throw new IllegalStateException("Unable to generate callback URI", e);
        }
    }

    protected static String descriptionFor(final String providerId) {
        return providerId;
    }

    protected static String iconFor(final String providerId) {
        return providerId;
    }

    protected static String labelFor(final String providerId) {
        return providerId;
    }
}

19 Source : Bug3599765.java
with GNU Lesser General Public License v2.1
from spotbugs

public clreplaced Bug3599765 {

    private final MultiValueMap<String, String> otherParams = new LinkedMultiValueMap<String, String>();

    @NoWarning("BC")
    public void setOtherParam(String name, List<String> values) {
        // triggers bug: Impossible
        List<String> otherP = otherParams.get(name);
        // cast from String to
        // java.util.List
        if (otherP == null) {
            otherParams.put(name, values);
        } else {
            otherP.addAll(values);
        }
    }
}

19 Source : FlashMap.java
with Apache License 2.0
from SourceHot

/**
 * A FlashMap provides a way for one request to store attributes intended for
 * use in another. This is most commonly needed when redirecting from one URL
 * to another -- e.g. the Post/Redirect/Get pattern. A FlashMap is saved before
 * the redirect (typically in the session) and is made available after the
 * redirect and removed immediately.
 *
 * <p>A FlashMap can be set up with a request path and request parameters to
 * help identify the target request. Without this information, a FlashMap is
 * made available to the next request, which may or may not be the intended
 * recipient. On a redirect, the target URL is known and a FlashMap can be
 * updated with that information. This is done automatically when the
 * {@code org.springframework.web.servlet.view.RedirectView} is used.
 *
 * <p>Note: annotated controllers will usually not use FlashMap directly.
 * See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes}
 * for an overview of using flash attributes in annotated controllers.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @see FlashMapManager
 */
@SuppressWarnings("serial")
public final clreplaced FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {

    @Nullable
    private String targetRequestPath;

    private final MultiValueMap<String, String> targetRequestParams = new LinkedMultiValueMap<>(4);

    private long expirationTime = -1;

    /**
     * Provide a URL path to help identify the target request for this FlashMap.
     * <p>The path may be absolute (e.g. "/application/resource") or relative to the
     * current request (e.g. "../resource").
     */
    public void setTargetRequestPath(@Nullable String path) {
        this.targetRequestPath = path;
    }

    /**
     * Return the target URL path (or {@code null} if none specified).
     */
    @Nullable
    public String getTargetRequestPath() {
        return this.targetRequestPath;
    }

    /**
     * Provide request parameters identifying the request for this FlashMap.
     * @param params a Map with the names and values of expected parameters
     */
    public FlashMap addTargetRequestParams(@Nullable MultiValueMap<String, String> params) {
        if (params != null) {
            params.forEach((key, values) -> {
                for (String value : values) {
                    addTargetRequestParam(key, value);
                }
            });
        }
        return this;
    }

    /**
     * Provide a request parameter identifying the request for this FlashMap.
     * @param name the expected parameter name (skipped if empty)
     * @param value the expected value (skipped if empty)
     */
    public FlashMap addTargetRequestParam(String name, String value) {
        if (StringUtils.hasText(name) && StringUtils.hasText(value)) {
            this.targetRequestParams.add(name, value);
        }
        return this;
    }

    /**
     * Return the parameters identifying the target request, or an empty map.
     */
    public MultiValueMap<String, String> getTargetRequestParams() {
        return this.targetRequestParams;
    }

    /**
     * Start the expiration period for this instance.
     * @param timeToLive the number of seconds before expiration
     */
    public void startExpirationPeriod(int timeToLive) {
        this.expirationTime = System.currentTimeMillis() + timeToLive * 1000;
    }

    /**
     * Set the expiration time for the FlashMap. This is provided for serialization
     * purposes but can also be used instead {@link #startExpirationPeriod(int)}.
     * @since 4.2
     */
    public void setExpirationTime(long expirationTime) {
        this.expirationTime = expirationTime;
    }

    /**
     * Return the expiration time for the FlashMap or -1 if the expiration
     * period has not started.
     * @since 4.2
     */
    public long getExpirationTime() {
        return this.expirationTime;
    }

    /**
     * Return whether this instance has expired depending on the amount of
     * elapsed time since the call to {@link #startExpirationPeriod}.
     */
    public boolean isExpired() {
        return (this.expirationTime != -1 && System.currentTimeMillis() > this.expirationTime);
    }

    /**
     * Compare two FlashMaps and prefer the one that specifies a target URL
     * path or has more target URL parameters. Before comparing FlashMap
     * instances ensure that they match a given request.
     */
    @Override
    public int compareTo(FlashMap other) {
        int thisUrlPath = (this.targetRequestPath != null ? 1 : 0);
        int otherUrlPath = (other.targetRequestPath != null ? 1 : 0);
        if (thisUrlPath != otherUrlPath) {
            return otherUrlPath - thisUrlPath;
        } else {
            return other.targetRequestParams.size() - this.targetRequestParams.size();
        }
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof FlashMap)) {
            return false;
        }
        FlashMap otherFlashMap = (FlashMap) other;
        return (super.equals(otherFlashMap) && ObjectUtils.nullSafeEquals(this.targetRequestPath, otherFlashMap.targetRequestPath) && this.targetRequestParams.equals(otherFlashMap.targetRequestParams));
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.targetRequestPath);
        result = 31 * result + this.targetRequestParams.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "FlashMap [attributes=" + super.toString() + ", targetRequestPath=" + this.targetRequestPath + ", targetRequestParams=" + this.targetRequestParams + "]";
    }
}

19 Source : MockMultipartHttpServletRequest.java
with Apache License 2.0
from SourceHot

/**
 * Mock implementation of the
 * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
 *
 * <p>As of Spring 5.0, this set of mocks is designed on a Servlet 4.0 baseline.
 *
 * <p>Useful for testing application controllers that access multipart uploads.
 * {@link MockMultipartFile} can be used to populate these mock requests with files.
 *
 * @author Juergen Hoeller
 * @author Eric Crampton
 * @author Arjen Poutsma
 * @since 2.0
 * @see MockMultipartFile
 */
public clreplaced MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {

    private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<>();

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with a default
     * {@link MockServletContext}.
     * @see #MockMultipartHttpServletRequest(ServletContext)
     */
    public MockMultipartHttpServletRequest() {
        this(null);
    }

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
     * @param servletContext the ServletContext that the request runs in
     * (may be {@code null} to use a default {@link MockServletContext})
     */
    public MockMultipartHttpServletRequest(@Nullable ServletContext servletContext) {
        super(servletContext);
        setMethod("POST");
        setContentType("multipart/form-data");
    }

    /**
     * Add a file to this request. The parameter name from the multipart
     * form is taken from the {@link MultipartFile#getName()}.
     * @param file multipart file to be added
     */
    public void addFile(MultipartFile file) {
        replacedert.notNull(file, "MultipartFile must not be null");
        this.multipartFiles.add(file.getName(), file);
    }

    @Override
    public Iterator<String> getFileNames() {
        return this.multipartFiles.keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return this.multipartFiles.getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return this.multipartFiles.toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return new LinkedMultiValueMap<>(this.multipartFiles);
    }

    @Override
    public String getMultipartContentType(String paramOrFileName) {
        MultipartFile file = getFile(paramOrFileName);
        if (file != null) {
            return file.getContentType();
        }
        try {
            Part part = getPart(paramOrFileName);
            if (part != null) {
                return part.getContentType();
            }
        } catch (ServletException | IOException ex) {
            // Should never happen (we're not actually parsing)
            throw new IllegalStateException(ex);
        }
        return null;
    }

    @Override
    public HttpMethod getRequestMethod() {
        return HttpMethod.resolve(getMethod());
    }

    @Override
    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, Collections.list(getHeaders(headerName)));
        }
        return headers;
    }

    @Override
    public HttpHeaders getMultipartHeaders(String paramOrFileName) {
        String contentType = getMultipartContentType(paramOrFileName);
        if (contentType != null) {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", contentType);
            return headers;
        } else {
            return null;
        }
    }
}

19 Source : OpaqueUriComponents.java
with Apache License 2.0
from SourceHot

/**
 * Extension of {@link UriComponents} for opaque URIs.
 *
 * @author Arjen Poutsma
 * @author Phillip Webb
 * @since 3.2
 * @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical vs Opaque URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced OpaqueUriComponents extends UriComponents {

    private static final MultiValueMap<String, String> QUERY_PARAMS_NONE = new LinkedMultiValueMap<>();

    @Nullable
    private final String ssp;

    OpaqueUriComponents(@Nullable String scheme, @Nullable String schemeSpecificPart, @Nullable String fragment) {
        super(scheme, fragment);
        this.ssp = schemeSpecificPart;
    }

    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return this.ssp;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return null;
    }

    @Override
    @Nullable
    public String getHost() {
        return null;
    }

    @Override
    public int getPort() {
        return -1;
    }

    @Override
    @Nullable
    public String getPath() {
        return null;
    }

    @Override
    public List<String> getPathSegments() {
        return Collections.emptyList();
    }

    @Override
    @Nullable
    public String getQuery() {
        return null;
    }

    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return QUERY_PARAMS_NONE;
    }

    @Override
    public UriComponents encode(Charset charset) {
        return this;
    }

    @Override
    protected UriComponents expandInternal(UriTemplateVariables uriVariables) {
        String expandedScheme = expandUriComponent(getScheme(), uriVariables);
        String expandedSsp = expandUriComponent(getSchemeSpecificPart(), uriVariables);
        String expandedFragment = expandUriComponent(getFragment(), uriVariables);
        return new OpaqueUriComponents(expandedScheme, expandedSsp, expandedFragment);
    }

    @Override
    public UriComponents normalize() {
        return this;
    }

    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme());
            uriBuilder.append(':');
        }
        if (this.ssp != null) {
            uriBuilder.append(this.ssp);
        }
        if (getFragment() != null) {
            uriBuilder.append('#');
            uriBuilder.append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            return new URI(getScheme(), this.ssp, getFragment());
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getSchemeSpecificPart() != null) {
            builder.schemeSpecificPart(getSchemeSpecificPart());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof OpaqueUriComponents)) {
            return false;
        }
        OpaqueUriComponents otherComp = (OpaqueUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(this.ssp, otherComp.ssp) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.ssp);
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }
}

19 Source : HierarchicalUriComponents.java
with Apache License 2.0
from SourceHot

/**
 * Extension of {@link UriComponents} for hierarchical URIs.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @author Rossen Stoyanchev
 * @author Phillip Webb
 * @since 3.1.3
 * @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced HierarchicalUriComponents extends UriComponents {

    private static final char PATH_DELIMITER = '/';

    private static final String PATH_DELIMITER_STRING = String.valueOf(PATH_DELIMITER);

    private static final MultiValueMap<String, String> EMPTY_QUERY_PARAMS = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>());

    /**
     * Represents an empty path.
     */
    static final PathComponent NULL_PATH_COMPONENT = new PathComponent() {

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

        @Override
        public List<String> getPathSegments() {
            return Collections.emptyList();
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            return this;
        }

        @Override
        public void verify() {
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            return this;
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        }

        @Override
        public boolean equals(@Nullable Object other) {
            return (this == other);
        }

        @Override
        public int hashCode() {
            return getClreplaced().hashCode();
        }
    };

    @Nullable
    private final String userInfo;

    @Nullable
    private final String host;

    @Nullable
    private final String port;

    private final PathComponent path;

    private final MultiValueMap<String, String> queryParams;

    private final EncodeState encodeState;

    @Nullable
    private UnaryOperator<String> variableEncoder;

    /**
     * Package-private constructor. All arguments are optional, and can be {@code null}.
     * @param scheme the scheme
     * @param userInfo the user info
     * @param host the host
     * @param port the port
     * @param path the path
     * @param query the query parameters
     * @param fragment the fragment
     * @param encoded whether the components are already encoded
     */
    HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, @Nullable PathComponent path, @Nullable MultiValueMap<String, String> query, boolean encoded) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path != null ? path : NULL_PATH_COMPONENT;
        this.queryParams = query != null ? CollectionUtils.unmodifiableMultiValueMap(query) : EMPTY_QUERY_PARAMS;
        this.encodeState = encoded ? EncodeState.FULLY_ENCODED : EncodeState.RAW;
        // Check for illegal characters..
        if (encoded) {
            verify();
        }
    }

    private HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, PathComponent path, MultiValueMap<String, String> queryParams, EncodeState encodeState, @Nullable UnaryOperator<String> variableEncoder) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path;
        this.queryParams = queryParams;
        this.encodeState = encodeState;
        this.variableEncoder = variableEncoder;
    }

    // Component getters
    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return null;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return this.userInfo;
    }

    @Override
    @Nullable
    public String getHost() {
        return this.host;
    }

    @Override
    public int getPort() {
        if (this.port == null) {
            return -1;
        } else if (this.port.contains("{")) {
            throw new IllegalStateException("The port contains a URI variable but has not been expanded yet: " + this.port);
        }
        return Integer.parseInt(this.port);
    }

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

    @Override
    public List<String> getPathSegments() {
        return this.path.getPathSegments();
    }

    @Override
    @Nullable
    public String getQuery() {
        if (!this.queryParams.isEmpty()) {
            StringBuilder queryBuilder = new StringBuilder();
            this.queryParams.forEach((name, values) -> {
                if (CollectionUtils.isEmpty(values)) {
                    if (queryBuilder.length() != 0) {
                        queryBuilder.append('&');
                    }
                    queryBuilder.append(name);
                } else {
                    for (Object value : values) {
                        if (queryBuilder.length() != 0) {
                            queryBuilder.append('&');
                        }
                        queryBuilder.append(name);
                        if (value != null) {
                            queryBuilder.append('=').append(value.toString());
                        }
                    }
                }
            });
            return queryBuilder.toString();
        } else {
            return null;
        }
    }

    /**
     * Return the map of query parameters. Empty if no query has been set.
     */
    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return this.queryParams;
    }

    // Encoding
    /**
     * Identical to {@link #encode()} but skipping over URI variable placeholders.
     * Also {@link #variableEncoder} is initialized with the given charset for
     * use later when URI variables are expanded.
     */
    HierarchicalUriComponents encodeTemplate(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        // Remember the charset to encode URI variables later..
        this.variableEncoder = value -> encodeUriComponent(value, charset, Type.URI);
        UriTemplateEncoder encoder = new UriTemplateEncoder(charset);
        String schemeTo = (getScheme() != null ? encoder.apply(getScheme(), Type.SCHEME) : null);
        String fragmentTo = (getFragment() != null ? encoder.apply(getFragment(), Type.FRAGMENT) : null);
        String userInfoTo = (getUserInfo() != null ? encoder.apply(getUserInfo(), Type.USER_INFO) : null);
        String hostTo = (getHost() != null ? encoder.apply(getHost(), getHostType()) : null);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.TEMPLATE_ENCODED, this.variableEncoder);
    }

    @Override
    public HierarchicalUriComponents encode(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        String scheme = getScheme();
        String fragment = getFragment();
        String schemeTo = (scheme != null ? encodeUriComponent(scheme, charset, Type.SCHEME) : null);
        String fragmentTo = (fragment != null ? encodeUriComponent(fragment, charset, Type.FRAGMENT) : null);
        String userInfoTo = (this.userInfo != null ? encodeUriComponent(this.userInfo, charset, Type.USER_INFO) : null);
        String hostTo = (this.host != null ? encodeUriComponent(this.host, charset, getHostType()) : null);
        BiFunction<String, Type, String> encoder = (s, type) -> encodeUriComponent(s, charset, type);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.FULLY_ENCODED, null);
    }

    private MultiValueMap<String, String> encodeQueryParams(BiFunction<String, Type, String> encoder) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        this.queryParams.forEach((key, values) -> {
            String name = encoder.apply(key, Type.QUERY_PARAM);
            List<String> encodedValues = new ArrayList<>(values.size());
            for (String value : values) {
                encodedValues.add(value != null ? encoder.apply(value, Type.QUERY_PARAM) : null);
            }
            result.put(name, encodedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param encoding the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, String encoding, Type type) {
        return encodeUriComponent(source, Charset.forName(encoding), type);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param charset the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, Charset charset, Type type) {
        if (!StringUtils.hasLength(source)) {
            return source;
        }
        replacedert.notNull(charset, "Charset must not be null");
        replacedert.notNull(type, "Type must not be null");
        byte[] bytes = source.getBytes(charset);
        boolean original = true;
        for (byte b : bytes) {
            if (b < 0) {
                b += 256;
            }
            if (!type.isAllowed(b)) {
                original = false;
                break;
            }
        }
        if (original) {
            return source;
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
        for (byte b : bytes) {
            if (b < 0) {
                b += 256;
            }
            if (type.isAllowed(b)) {
                bos.write(b);
            } else {
                bos.write('%');
                char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
                char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
                bos.write(hex1);
                bos.write(hex2);
            }
        }
        return new String(bos.toByteArray(), charset);
    }

    private Type getHostType() {
        return (this.host != null && this.host.startsWith("[") ? Type.HOST_IPV6 : Type.HOST_IPV4);
    }

    // Verifying
    /**
     * Check if any of the URI components contain any illegal characters.
     * @throws IllegalArgumentException if any component has illegal characters
     */
    private void verify() {
        verifyUriComponent(getScheme(), Type.SCHEME);
        verifyUriComponent(this.userInfo, Type.USER_INFO);
        verifyUriComponent(this.host, getHostType());
        this.path.verify();
        this.queryParams.forEach((key, values) -> {
            verifyUriComponent(key, Type.QUERY_PARAM);
            for (String value : values) {
                verifyUriComponent(value, Type.QUERY_PARAM);
            }
        });
        verifyUriComponent(getFragment(), Type.FRAGMENT);
    }

    private static void verifyUriComponent(@Nullable String source, Type type) {
        if (source == null) {
            return;
        }
        int length = source.length();
        for (int i = 0; i < length; i++) {
            char ch = source.charAt(i);
            if (ch == '%') {
                if ((i + 2) < length) {
                    char hex1 = source.charAt(i + 1);
                    char hex2 = source.charAt(i + 2);
                    int u = Character.digit(hex1, 16);
                    int l = Character.digit(hex2, 16);
                    if (u == -1 || l == -1) {
                        throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                    }
                    i += 2;
                } else {
                    throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                }
            } else if (!type.isAllowed(ch)) {
                throw new IllegalArgumentException("Invalid character '" + ch + "' for " + type.name() + " in \"" + source + "\"");
            }
        }
    }

    // Expanding
    @Override
    protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
        replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
        // Array-based vars rely on the order below...
        String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
        String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
        String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
        String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
        PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
        MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
        String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
    }

    private MultiValueMap<String, String> expandQueryParams(UriTemplateVariables variables) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables);
        this.queryParams.forEach((key, values) -> {
            String name = expandUriComponent(key, queryVariables, this.variableEncoder);
            List<String> expandedValues = new ArrayList<>(values.size());
            for (String value : values) {
                expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder));
            }
            result.put(name, expandedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    @Override
    public UriComponents normalize() {
        String normalizedPath = StringUtils.cleanPath(getPath());
        FullPathComponent path = new FullPathComponent(normalizedPath);
        return new HierarchicalUriComponents(getScheme(), getFragment(), this.userInfo, this.host, this.port, path, this.queryParams, this.encodeState, this.variableEncoder);
    }

    // Other functionality
    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme()).append(':');
        }
        if (this.userInfo != null || this.host != null) {
            uriBuilder.append("//");
            if (this.userInfo != null) {
                uriBuilder.append(this.userInfo).append('@');
            }
            if (this.host != null) {
                uriBuilder.append(this.host);
            }
            if (getPort() != -1) {
                uriBuilder.append(':').append(this.port);
            }
        }
        String path = getPath();
        if (StringUtils.hasLength(path)) {
            if (uriBuilder.length() != 0 && path.charAt(0) != PATH_DELIMITER) {
                uriBuilder.append(PATH_DELIMITER);
            }
            uriBuilder.append(path);
        }
        String query = getQuery();
        if (query != null) {
            uriBuilder.append('?').append(query);
        }
        if (getFragment() != null) {
            uriBuilder.append('#').append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            if (this.encodeState.isEncoded()) {
                return new URI(toUriString());
            } else {
                String path = getPath();
                if (StringUtils.hasLength(path) && path.charAt(0) != PATH_DELIMITER) {
                    // Only prefix the path delimiter if something exists before it
                    if (getScheme() != null || getUserInfo() != null || getHost() != null || getPort() != -1) {
                        path = PATH_DELIMITER + path;
                    }
                }
                return new URI(getScheme(), getUserInfo(), getHost(), getPort(), path, getQuery(), getFragment());
            }
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getUserInfo() != null) {
            builder.userInfo(getUserInfo());
        }
        if (getHost() != null) {
            builder.host(getHost());
        }
        // Avoid parsing the port, may have URI variable..
        if (this.port != null) {
            builder.port(this.port);
        }
        this.path.copyToUriComponentsBuilder(builder);
        if (!getQueryParams().isEmpty()) {
            builder.queryParams(getQueryParams());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof HierarchicalUriComponents)) {
            return false;
        }
        HierarchicalUriComponents otherComp = (HierarchicalUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(getUserInfo(), otherComp.getUserInfo()) && ObjectUtils.nullSafeEquals(getHost(), otherComp.getHost()) && getPort() == otherComp.getPort() && this.path.equals(otherComp.path) && this.queryParams.equals(otherComp.queryParams) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.userInfo);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.host);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.port);
        result = 31 * result + this.path.hashCode();
        result = 31 * result + this.queryParams.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }

    // Nested types
    /**
     * Enumeration used to identify the allowed characters per URI component.
     * <p>Contains methods to indicate whether a given character is valid in a specific URI component.
     * @see <a href="https://tools.ietf.org/html/rfc3986">RFC 3986</a>
     */
    enum Type {

        SCHEME {

            @Override
            public boolean isAllowed(int c) {
                return isAlpha(c) || isDigit(c) || '+' == c || '-' == c || '.' == c;
            }
        }
        ,
        AUTHORITY {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
            }
        }
        ,
        USER_INFO {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c;
            }
        }
        ,
        HOST_IPV4 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c);
            }
        }
        ,
        HOST_IPV6 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || '[' == c || ']' == c || ':' == c;
            }
        }
        ,
        PORT {

            @Override
            public boolean isAllowed(int c) {
                return isDigit(c);
            }
        }
        ,
        PATH {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c;
            }
        }
        ,
        PATH_SEGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c);
            }
        }
        ,
        QUERY {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        QUERY_PARAM {

            @Override
            public boolean isAllowed(int c) {
                if ('=' == c || '&' == c) {
                    return false;
                } else {
                    return isPchar(c) || '/' == c || '?' == c;
                }
            }
        }
        ,
        FRAGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        URI {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c);
            }
        }
        ;

        /**
         * Indicates whether the given character is allowed in this URI component.
         * @return {@code true} if the character is allowed; {@code false} otherwise
         */
        public abstract boolean isAllowed(int c);

        /**
         * Indicates whether the given character is in the {@code ALPHA} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isAlpha(int c) {
            return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
        }

        /**
         * Indicates whether the given character is in the {@code DIGIT} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isDigit(int c) {
            return (c >= '0' && c <= '9');
        }

        /**
         * Indicates whether the given character is in the {@code gen-delims} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isGenericDelimiter(int c) {
            return (':' == c || '/' == c || '?' == c || '#' == c || '[' == c || ']' == c || '@' == c);
        }

        /**
         * Indicates whether the given character is in the {@code sub-delims} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isSubDelimiter(int c) {
            return ('!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c || ',' == c || ';' == c || '=' == c);
        }

        /**
         * Indicates whether the given character is in the {@code reserved} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isReserved(int c) {
            return (isGenericDelimiter(c) || isSubDelimiter(c));
        }

        /**
         * Indicates whether the given character is in the {@code unreserved} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isUnreserved(int c) {
            return (isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c);
        }

        /**
         * Indicates whether the given character is in the {@code pchar} set.
         * @see <a href="https://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isPchar(int c) {
            return (isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c);
        }
    }

    private enum EncodeState {

        /**
         * Not encoded.
         */
        RAW,
        /**
         * URI vars expanded first and then each URI component encoded by
         * quoting only illegal characters within that URI component.
         */
        FULLY_ENCODED,
        /**
         * URI template encoded first by quoting illegal characters only, and
         * then URI vars encoded more strictly when expanded, by quoting both
         * illegal chars and chars with reserved meaning.
         */
        TEMPLATE_ENCODED;

        public boolean isEncoded() {
            return this.equals(FULLY_ENCODED) || this.equals(TEMPLATE_ENCODED);
        }
    }

    private static clreplaced UriTemplateEncoder implements BiFunction<String, Type, String> {

        private final Charset charset;

        private final StringBuilder currentLiteral = new StringBuilder();

        private final StringBuilder currentVariable = new StringBuilder();

        private final StringBuilder output = new StringBuilder();

        public UriTemplateEncoder(Charset charset) {
            this.charset = charset;
        }

        @Override
        public String apply(String source, Type type) {
            // Only URI variable (nothing to encode)..
            if (source.length() > 1 && source.charAt(0) == '{' && source.charAt(source.length() - 1) == '}') {
                return source;
            }
            // Only literal (encode full source)..
            if (source.indexOf('{') == -1) {
                return encodeUriComponent(source, this.charset, type);
            }
            // Mixed literal parts and URI variables, maybe (encode literal parts only)..
            int level = 0;
            clear(this.currentLiteral);
            clear(this.currentVariable);
            clear(this.output);
            for (char c : source.toCharArray()) {
                if (c == '{') {
                    level++;
                    if (level == 1) {
                        encodeAndAppendCurrentLiteral(type);
                    }
                }
                if (c == '}' && level > 0) {
                    level--;
                    this.currentVariable.append('}');
                    if (level == 0) {
                        this.output.append(this.currentVariable);
                        clear(this.currentVariable);
                    }
                } else if (level > 0) {
                    this.currentVariable.append(c);
                } else {
                    this.currentLiteral.append(c);
                }
            }
            if (level > 0) {
                this.currentLiteral.append(this.currentVariable);
            }
            encodeAndAppendCurrentLiteral(type);
            return this.output.toString();
        }

        private void encodeAndAppendCurrentLiteral(Type type) {
            this.output.append(encodeUriComponent(this.currentLiteral.toString(), this.charset, type));
            clear(this.currentLiteral);
        }

        private void clear(StringBuilder sb) {
            sb.delete(0, sb.length());
        }
    }

    /**
     * Defines the contract for path (segments).
     */
    interface PathComponent extends Serializable {

        String getPath();

        List<String> getPathSegments();

        PathComponent encode(BiFunction<String, Type, String> encoder);

        void verify();

        PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder);

        void copyToUriComponentsBuilder(UriComponentsBuilder builder);
    }

    /**
     * Represents a path backed by a String.
     */
    static final clreplaced FullPathComponent implements PathComponent {

        private final String path;

        public FullPathComponent(@Nullable String path) {
            this.path = (path != null ? path : "");
        }

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

        @Override
        public List<String> getPathSegments() {
            String[] segments = StringUtils.tokenizeToStringArray(getPath(), PATH_DELIMITER_STRING);
            return Collections.unmodifiableList(Arrays.asList(segments));
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            String encodedPath = encoder.apply(getPath(), Type.PATH);
            return new FullPathComponent(encodedPath);
        }

        @Override
        public void verify() {
            verifyUriComponent(getPath(), Type.PATH);
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            String expandedPath = expandUriComponent(getPath(), uriVariables, encoder);
            return new FullPathComponent(expandedPath);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.path(getPath());
        }

        @Override
        public boolean equals(@Nullable Object other) {
            return (this == other || (other instanceof FullPathComponent && getPath().equals(((FullPathComponent) other).getPath())));
        }

        @Override
        public int hashCode() {
            return getPath().hashCode();
        }
    }

    /**
     * Represents a path backed by a String list (i.e. path segments).
     */
    static final clreplaced PathSegmentComponent implements PathComponent {

        private final List<String> pathSegments;

        public PathSegmentComponent(List<String> pathSegments) {
            replacedert.notNull(pathSegments, "List must not be null");
            this.pathSegments = Collections.unmodifiableList(new ArrayList<>(pathSegments));
        }

        @Override
        public String getPath() {
            String delimiter = PATH_DELIMITER_STRING;
            StringJoiner pathBuilder = new StringJoiner(delimiter, delimiter, "");
            for (String pathSegment : this.pathSegments) {
                pathBuilder.add(pathSegment);
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            return this.pathSegments;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> encodedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String encodedPathSegment = encoder.apply(pathSegment, Type.PATH_SEGMENT);
                encodedPathSegments.add(encodedPathSegment);
            }
            return new PathSegmentComponent(encodedPathSegments);
        }

        @Override
        public void verify() {
            for (String pathSegment : getPathSegments()) {
                verifyUriComponent(pathSegment, Type.PATH_SEGMENT);
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> expandedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String expandedPathSegment = expandUriComponent(pathSegment, uriVariables, encoder);
                expandedPathSegments.add(expandedPathSegment);
            }
            return new PathSegmentComponent(expandedPathSegments);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.pathSegment(StringUtils.toStringArray(getPathSegments()));
        }

        @Override
        public boolean equals(@Nullable Object other) {
            return (this == other || (other instanceof PathSegmentComponent && getPathSegments().equals(((PathSegmentComponent) other).getPathSegments())));
        }

        @Override
        public int hashCode() {
            return getPathSegments().hashCode();
        }
    }

    /**
     * Represents a collection of PathComponents.
     */
    static final clreplaced PathComponentComposite implements PathComponent {

        private final List<PathComponent> pathComponents;

        public PathComponentComposite(List<PathComponent> pathComponents) {
            replacedert.notNull(pathComponents, "PathComponent List must not be null");
            this.pathComponents = pathComponents;
        }

        @Override
        public String getPath() {
            StringBuilder pathBuilder = new StringBuilder();
            for (PathComponent pathComponent : this.pathComponents) {
                pathBuilder.append(pathComponent.getPath());
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            List<String> result = new ArrayList<>();
            for (PathComponent pathComponent : this.pathComponents) {
                result.addAll(pathComponent.getPathSegments());
            }
            return result;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<PathComponent> encodedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                encodedComponents.add(pathComponent.encode(encoder));
            }
            return new PathComponentComposite(encodedComponents);
        }

        @Override
        public void verify() {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.verify();
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<PathComponent> expandedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                expandedComponents.add(pathComponent.expand(uriVariables, encoder));
            }
            return new PathComponentComposite(expandedComponents);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.copyToUriComponentsBuilder(builder);
            }
        }
    }

    private static clreplaced QueryUriTemplateVariables implements UriTemplateVariables {

        private final UriTemplateVariables delegate;

        public QueryUriTemplateVariables(UriTemplateVariables delegate) {
            this.delegate = delegate;
        }

        @Override
        public Object getValue(@Nullable String name) {
            Object value = this.delegate.getValue(name);
            if (ObjectUtils.isArray(value)) {
                value = StringUtils.arrayToCommaDelimitedString(ObjectUtils.toObjectArray(value));
            }
            return value;
        }
    }
}

19 Source : HierarchicalUriComponents.java
with Apache License 2.0
from SourceHot

// Expanding
@Override
protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
    replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
    // Array-based vars rely on the order below...
    String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
    String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
    String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
    String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
    PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
    MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
    String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
    return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
}

19 Source : JsonPathRequestMatchersIntegrationTests.java
with Apache License 2.0
from SourceHot

/**
 * Examples of defining expectations on JSON request content with
 * <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
 *
 * @author Rossen Stoyanchev
 * @author Sam Brannen
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchers
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchersTests
 */
public clreplaced JsonPathRequestMatchersIntegrationTests {

    private static final MultiValueMap<String, Person> people = new LinkedMultiValueMap<>();

    static {
        people.add("composers", new Person("Johann Sebastian Bach"));
        people.add("composers", new Person("Johannes Brahms"));
        people.add("composers", new Person("Edvard Grieg"));
        people.add("composers", new Person("Robert Schumann"));
        people.add("performers", new Person("Vladimir Ashkenazy"));
        people.add("performers", new Person("Yehudi Menuhin"));
    }

    private final RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new MappingJackson2HttpMessageConverter()));

    private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate);

    @Test
    public void exists() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0]").exists()).andExpect(jsonPath("$.composers[1]").exists()).andExpect(jsonPath("$.composers[2]").exists()).andExpect(jsonPath("$.composers[3]").exists()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void doesNotExist() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist()).andExpect(jsonPath("$.composers[?(@.name == 'Robert Schuuuuuuman')]").doesNotExist()).andExpect(jsonPath("$.composers[4]").doesNotExist()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void value() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach")).andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin")).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchers() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))).andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))).andExpect(jsonPath("$.composers[0].name", startsWith("Johann"))).andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy"))).andExpect(jsonPath("$.performers[1].name", containsString("di Me"))).andExpect(jsonPath("$.composers[1].name", is(in(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))).andExpect(jsonPath("$.composers[:3].name", hasItem("Johannes Brahms"))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchersWithParameterizedJsonPaths() throws Exception {
        String composerName = "$.composers[%s].name";
        String performerName = "$.performers[%s].name";
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath(composerName, 0).value(startsWith("Johann"))).andExpect(jsonPath(performerName, 0).value(endsWith("Ashkenazy"))).andExpect(jsonPath(performerName, 1).value(containsString("di Me"))).andExpect(jsonPath(composerName, 1).value(is(in(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isArray() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers").isArray()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isString() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].name").isString()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isNumber() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].someDouble").isNumber()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isBoolean() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json")).andExpect(jsonPath("$.composers[0].someBoolean").isBoolean()).andRespond(withSuccess());
        executeAndVerify();
    }

    private void executeAndVerify() throws URISyntaxException {
        this.restTemplate.put(new URI("/composers"), people);
        this.mockServer.verify();
    }
}

19 Source : ImporterExporterComponentConditional.java
with Apache License 2.0
from sofastack

private boolean isComponentEnable(ConditionContext context, AnnotatedTypeMetadata metadata) {
    boolean isImporter = metadata.isAnnotated(ConditionalOnImporterComponent.clreplaced.getName());
    MultiValueMap<String, Object> map = null;
    if (isImporter) {
        map = metadata.getAllAnnotationAttributes(ConditionalOnImporterComponent.clreplaced.getName());
    } else {
        map = metadata.getAllAnnotationAttributes(ConditionalOnExporterComponent.clreplaced.getName());
    }
    String importerExporterName = getFirstAnnotationValueFromMetadata(map, "value");
    MonitorComponent monitorComponent = getFirstAnnotationValueFromMetadata(map, "type");
    List<String> activeComponents = getActivatedComponentsFromConfiguration(context, isImporter, monitorComponent);
    boolean active = activeComponents.contains(importerExporterName);
    LOGGER.info("gateway {} {}:{} active:{}", monitorComponent.name().toLowerCase(), (isImporter ? "importer" : "exporter"), importerExporterName, active);
    return active;
}

19 Source : XsuaaOAuth2TokenServicePasswordTest.java
with Apache License 2.0
from SAP

private String valueOfParameter(String parameterKey, ArgumentCaptor<HttpEnreplacedy<MultiValueMap<String, String>>> requestEnreplacedyCaptor) {
    MultiValueMap<String, String> body = requestEnreplacedyCaptor.getValue().getBody();
    return body.getFirst(parameterKey);
}

19 Source : XsuaaOAuth2TokenService.java
with Apache License 2.0
from SAP

/**
 * Creates a copy of the given map or an new empty map of type MultiValueMap.
 *
 * @return a new @link{MultiValueMap} that contains all entries of the optional
 *         map.
 */
private MultiValueMap<String, String> copyIntoForm(Map<String, String> parameters) {
    MultiValueMap<String, String> formData = new LinkedMultiValueMap();
    if (parameters != null) {
        parameters.forEach(formData::add);
    }
    return formData;
}

19 Source : POSTMapper.java
with Mozilla Public License 2.0
from SafeExamBrowser

/**
 * A POST parameter mapper that wraps all parameter from a POST request given by a MultiValueMap<String, String> and
 * defines API specific convenience functions to access this parameter with given type and conversion of needed.
 */
public clreplaced POSTMapper {

    public static final POSTMapper EMPTY_MAP = new POSTMapper(null, null);

    protected final MultiValueMap<String, String> params;

    public POSTMapper(final MultiValueMap<String, String> params, final String uriQueryString) {
        super();
        this.params = params != null ? new LinkedMultiValueMap<>(params) : new LinkedMultiValueMap<>();
        if (uriQueryString != null) {
            handleEncodedURIParams(uriQueryString);
        }
    }

    // NOTE: this is a workaround since URI parameter are not automatically decoded in the HTTPServletRequest
    // while parameter from form-urlencoded body part are.
    // I also tried to set application property: server.tomcat.uri-encoding=UTF-8 bit with no effect.
    // TODO  Didn't found a better solution for now but if there is some time, we should find a better solution
    private void handleEncodedURIParams(final String uriQueryString) {
        final MultiValueMap<String, String> override = new LinkedMultiValueMap<>();
        this.params.entrySet().stream().forEach(entry -> {
            if (uriQueryString.contains(entry.getKey())) {
                override.put(entry.getKey(), entry.getValue().stream().map(val -> decode(val)).collect(Collectors.toList()));
            }
        });
        if (!override.isEmpty()) {
            this.params.putAll(override);
        }
    }

    private String decode(final String val) {
        try {
            return Utils.decodeFormURL_UTF_8(val);
        } catch (final Exception e) {
            return val;
        }
    }

    public String getString(final String name) {
        return this.params.getFirst(name);
    }

    public char[] getCharArray(final String name) {
        final String value = getString(name);
        if (value == null || value.length() <= 0) {
            return new char[] {};
        }
        return value.toCharArray();
    }

    public CharSequence getCharSequence(final String name) {
        return CharBuffer.wrap(getCharArray(name));
    }

    public Long getLong(final String name) {
        final String value = this.params.getFirst(name);
        if (StringUtils.isBlank(value)) {
            return null;
        }
        return Long.parseLong(value);
    }

    public Short getShort(final String name) {
        final String value = this.params.getFirst(name);
        if (StringUtils.isBlank(value)) {
            return null;
        }
        return Short.parseShort(value);
    }

    public Integer getInteger(final String name) {
        final String value = this.params.getFirst(name);
        if (value == null) {
            return null;
        }
        return Integer.parseInt(value);
    }

    public Locale getLocale(final String name) {
        final String value = this.params.getFirst(name);
        if (value == null) {
            return null;
        }
        return Locale.forLanguageTag(value);
    }

    public boolean getBoolean(final String name) {
        return BooleanUtils.toBoolean(this.params.getFirst(name));
    }

    public Boolean getBooleanObject(final String name) {
        return BooleanUtils.toBooleanObject(this.params.getFirst(name));
    }

    public Integer getBooleanAsInteger(final String name) {
        final Boolean booleanObject = getBooleanObject(name);
        if (booleanObject == null) {
            return null;
        }
        return BooleanUtils.toIntegerObject(booleanObject);
    }

    public DateTimeZone getDateTimeZone(final String name) {
        final String value = this.params.getFirst(name);
        if (value == null) {
            return null;
        }
        try {
            return DateTimeZone.forID(value);
        } catch (final Exception e) {
            return null;
        }
    }

    public Set<String> getStringSet(final String name) {
        final List<String> list = this.params.get(name);
        if (list == null) {
            return Collections.emptySet();
        }
        return Utils.immutableSetOf(list);
    }

    public <T extends Enum<T>> T getEnum(final String name, final Clreplaced<T> type, final T defaultValue) {
        final T result = getEnum(name, type);
        if (result == null) {
            return defaultValue;
        }
        return result;
    }

    public <T extends Enum<T>> T getEnum(final String name, final Clreplaced<T> type) {
        final String value = this.params.getFirst(name);
        if (value == null) {
            return null;
        }
        try {
            return Enum.valueOf(type, value);
        } catch (final Exception e) {
            return null;
        }
    }

    public DateTime getDateTime(final String name) {
        final String value = this.params.getFirst(name);
        if (value == null) {
            return null;
        }
        return Utils.toDateTime(value);
    }

    public List<Threshold> getThresholds() {
        final List<String> thresholdStrings = this.params.get(Domain.THRESHOLD.REFERENCE_NAME);
        if (thresholdStrings == null || thresholdStrings.isEmpty()) {
            return Collections.emptyList();
        }
        return thresholdStrings.stream().map(ts -> {
            try {
                final String[] split = StringUtils.split(ts, Constants.EMBEDDED_LIST_SEPARATOR);
                return new Threshold(Double.parseDouble(split[0]), split[1]);
            } catch (final Exception e) {
                return null;
            }
        }).collect(Collectors.toList());
    }

    @SuppressWarnings("unchecked")
    public <T extends POSTMapper> T putIfAbsent(final String name, final String value) {
        this.params.putIfAbsent(name, Arrays.asList(value));
        return (T) this;
    }
}

19 Source : GenerateWidgetViewEvent.java
with Apache License 2.0
from reportportal

/**
 * @author <a href="mailto:[email protected]">Ivan Budayeu</a>
 */
public clreplaced GenerateWidgetViewEvent {

    private final Long widgetId;

    private final MultiValueMap<String, String> params;

    public GenerateWidgetViewEvent(Long widgetId, MultiValueMap<String, String> params) {
        this.widgetId = widgetId;
        this.params = params;
    }

    public GenerateWidgetViewEvent(Long widgetId) {
        this.widgetId = widgetId;
        this.params = new LinkedMultiValueMap<>();
    }

    public Long getWidgetId() {
        return widgetId;
    }

    public MultiValueMap<String, String> getParams() {
        return params;
    }
}

19 Source : ArchivedCardRepositoryShould.java
with Mozilla Public License 2.0
from opfab

@Test
public void fetchArchivedCardsGroupRecipientIsAllowedToSee() {
    MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
    // Cards visible by someone from group "rte"
    Tuple2<CurrentUserWithPerimeters, MultiValueMap<String, String>> params = of(currentUser2, queryParams);
    StepVerifier.create(repository.findWithUserAndParams(params)).replacedertNext(page -> {
        replacedertThat(page.getTotalElements()).isEqualTo(7);
        replacedertThat(page.getTotalPages()).isEqualTo(1);
        // Check sort order
        replacedertTrue(checkIfPageIsSorted(page));
    }).expectComplete().verify();
}

19 Source : ArchivedCardRepositoryShould.java
with Mozilla Public License 2.0
from opfab

@Test
public void fetchArchivedCardsEnreplacedyRecipientIsAllowedToSee() {
    MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
    // Cards visible by someone from enreplacedy "someEnreplacedy"
    Tuple2<CurrentUserWithPerimeters, MultiValueMap<String, String>> params = of(currentUser4, queryParams);
    StepVerifier.create(repository.findWithUserAndParams(params)).expectNextCount(1).expectComplete().verify();
}

19 Source : ArchivedCardRepositoryShould.java
with Mozilla Public License 2.0
from opfab

@Test
public void fetchArchivedCardsGroupAndEnreplacedyRecipientAreAllowedToSee() {
    MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
    // Cards visible by someone from group "group1" and from enreplacedy "enreplacedy1"
    Tuple2<CurrentUserWithPerimeters, MultiValueMap<String, String>> params = of(currentUser5, queryParams);
    StepVerifier.create(repository.findWithUserAndParams(params)).expectNextCount(1).expectComplete().verify();
}

19 Source : ArchivedCardRepositoryShould.java
with Mozilla Public License 2.0
from opfab

@Test
public void fetchArchivedCardsUserRecipientWithNoGroupIsAllowedToSee() {
    MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
    // Cards visible by user3 (who has no groups at all)
    Tuple2<CurrentUserWithPerimeters, MultiValueMap<String, String>> params = of(currentUser3, queryParams);
    StepVerifier.create(repository.findWithUserAndParams(params)).expectNextCount(1).expectComplete().verify();
}

19 Source : ArchivedCardRepositoryShould.java
with Mozilla Public License 2.0
from opfab

@Test
public void fetchArchivedCardsUserRecipientIsAllowedToSee() {
    MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
    // Cards visible by user1
    Tuple2<CurrentUserWithPerimeters, MultiValueMap<String, String>> params = of(currentUser1, queryParams);
    StepVerifier.create(repository.findWithUserAndParams(params)).replacedertNext(page -> {
        replacedertThat(page.getTotalElements()).isEqualTo(13);
        replacedertThat(page.getTotalPages()).isEqualTo(1);
        // Check sort order
        replacedertTrue(checkIfPageIsSorted(page));
    }).expectComplete().verify();
}

19 Source : OpaqueUriComponents.java
with MIT License
from mindcarver

/**
 * Extension of {@link UriComponents} for opaque URIs.
 *
 * @author Arjen Poutsma
 * @author Phillip Webb
 * @since 3.2
 * @see <a href="http://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical vs Opaque URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced OpaqueUriComponents extends UriComponents {

    private static final MultiValueMap<String, String> QUERY_PARAMS_NONE = new LinkedMultiValueMap<>();

    @Nullable
    private final String ssp;

    OpaqueUriComponents(@Nullable String scheme, @Nullable String schemeSpecificPart, @Nullable String fragment) {
        super(scheme, fragment);
        this.ssp = schemeSpecificPart;
    }

    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return this.ssp;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return null;
    }

    @Override
    @Nullable
    public String getHost() {
        return null;
    }

    @Override
    public int getPort() {
        return -1;
    }

    @Override
    @Nullable
    public String getPath() {
        return null;
    }

    @Override
    public List<String> getPathSegments() {
        return Collections.emptyList();
    }

    @Override
    @Nullable
    public String getQuery() {
        return null;
    }

    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return QUERY_PARAMS_NONE;
    }

    @Override
    public UriComponents encode(Charset charset) {
        return this;
    }

    @Override
    protected UriComponents expandInternal(UriTemplateVariables uriVariables) {
        String expandedScheme = expandUriComponent(getScheme(), uriVariables);
        String expandedSsp = expandUriComponent(getSchemeSpecificPart(), uriVariables);
        String expandedFragment = expandUriComponent(getFragment(), uriVariables);
        return new OpaqueUriComponents(expandedScheme, expandedSsp, expandedFragment);
    }

    @Override
    public UriComponents normalize() {
        return this;
    }

    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme());
            uriBuilder.append(':');
        }
        if (this.ssp != null) {
            uriBuilder.append(this.ssp);
        }
        if (getFragment() != null) {
            uriBuilder.append('#');
            uriBuilder.append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            return new URI(getScheme(), this.ssp, getFragment());
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getSchemeSpecificPart() != null) {
            builder.schemeSpecificPart(getSchemeSpecificPart());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof OpaqueUriComponents)) {
            return false;
        }
        OpaqueUriComponents otherComp = (OpaqueUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(this.ssp, otherComp.ssp) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.ssp);
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }
}

19 Source : HierarchicalUriComponents.java
with MIT License
from mindcarver

/**
 * Extension of {@link UriComponents} for hierarchical URIs.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @author Rossen Stoyanchev
 * @author Phillip Webb
 * @since 3.1.3
 * @see <a href="http://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced HierarchicalUriComponents extends UriComponents {

    private static final char PATH_DELIMITER = '/';

    private static final String PATH_DELIMITER_STRING = "/";

    private static final MultiValueMap<String, String> EMPTY_QUERY_PARAMS = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>());

    /**
     * Represents an empty path.
     */
    static final PathComponent NULL_PATH_COMPONENT = new PathComponent() {

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

        @Override
        public List<String> getPathSegments() {
            return Collections.emptyList();
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            return this;
        }

        @Override
        public void verify() {
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            return this;
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        }

        @Override
        public boolean equals(Object other) {
            return (this == other);
        }

        @Override
        public int hashCode() {
            return getClreplaced().hashCode();
        }
    };

    @Nullable
    private final String userInfo;

    @Nullable
    private final String host;

    @Nullable
    private final String port;

    private final PathComponent path;

    private final MultiValueMap<String, String> queryParams;

    private final EncodeState encodeState;

    @Nullable
    private UnaryOperator<String> variableEncoder;

    /**
     * Package-private constructor. All arguments are optional, and can be {@code null}.
     * @param scheme the scheme
     * @param userInfo the user info
     * @param host the host
     * @param port the port
     * @param path the path
     * @param query the query parameters
     * @param fragment the fragment
     * @param encoded whether the components are already encoded
     */
    HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, @Nullable PathComponent path, @Nullable MultiValueMap<String, String> query, boolean encoded) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path != null ? path : NULL_PATH_COMPONENT;
        this.queryParams = query != null ? CollectionUtils.unmodifiableMultiValueMap(query) : EMPTY_QUERY_PARAMS;
        this.encodeState = encoded ? EncodeState.FULLY_ENCODED : EncodeState.RAW;
        // Check for illegal characters..
        if (encoded) {
            verify();
        }
    }

    private HierarchicalUriComponents(@Nullable String scheme, @Nullable String fragment, @Nullable String userInfo, @Nullable String host, @Nullable String port, PathComponent path, MultiValueMap<String, String> queryParams, EncodeState encodeState, @Nullable UnaryOperator<String> variableEncoder) {
        super(scheme, fragment);
        this.userInfo = userInfo;
        this.host = host;
        this.port = port;
        this.path = path;
        this.queryParams = queryParams;
        this.encodeState = encodeState;
        this.variableEncoder = variableEncoder;
    }

    // Component getters
    @Override
    @Nullable
    public String getSchemeSpecificPart() {
        return null;
    }

    @Override
    @Nullable
    public String getUserInfo() {
        return this.userInfo;
    }

    @Override
    @Nullable
    public String getHost() {
        return this.host;
    }

    @Override
    public int getPort() {
        if (this.port == null) {
            return -1;
        } else if (this.port.contains("{")) {
            throw new IllegalStateException("The port contains a URI variable but has not been expanded yet: " + this.port);
        }
        return Integer.parseInt(this.port);
    }

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

    @Override
    public List<String> getPathSegments() {
        return this.path.getPathSegments();
    }

    @Override
    @Nullable
    public String getQuery() {
        if (!this.queryParams.isEmpty()) {
            StringBuilder queryBuilder = new StringBuilder();
            this.queryParams.forEach((name, values) -> {
                if (CollectionUtils.isEmpty(values)) {
                    if (queryBuilder.length() != 0) {
                        queryBuilder.append('&');
                    }
                    queryBuilder.append(name);
                } else {
                    for (Object value : values) {
                        if (queryBuilder.length() != 0) {
                            queryBuilder.append('&');
                        }
                        queryBuilder.append(name);
                        if (value != null) {
                            queryBuilder.append('=').append(value.toString());
                        }
                    }
                }
            });
            return queryBuilder.toString();
        } else {
            return null;
        }
    }

    /**
     * Return the map of query parameters. Empty if no query has been set.
     */
    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return this.queryParams;
    }

    // Encoding
    /**
     * Identical to {@link #encode()} but skipping over URI variable placeholders.
     * Also {@link #variableEncoder} is initialized with the given charset for
     * use later when URI variables are expanded.
     */
    HierarchicalUriComponents encodeTemplate(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        // Remember the charset to encode URI variables later..
        this.variableEncoder = value -> encodeUriComponent(value, charset, Type.URI);
        UriTemplateEncoder encoder = new UriTemplateEncoder(charset);
        String schemeTo = (getScheme() != null ? encoder.apply(getScheme(), Type.SCHEME) : null);
        String fragmentTo = (getFragment() != null ? encoder.apply(getFragment(), Type.FRAGMENT) : null);
        String userInfoTo = (getUserInfo() != null ? encoder.apply(getUserInfo(), Type.USER_INFO) : null);
        String hostTo = (getHost() != null ? encoder.apply(getHost(), getHostType()) : null);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.TEMPLATE_ENCODED, this.variableEncoder);
    }

    @Override
    public HierarchicalUriComponents encode(Charset charset) {
        if (this.encodeState.isEncoded()) {
            return this;
        }
        String scheme = getScheme();
        String fragment = getFragment();
        String schemeTo = (scheme != null ? encodeUriComponent(scheme, charset, Type.SCHEME) : null);
        String fragmentTo = (fragment != null ? encodeUriComponent(fragment, charset, Type.FRAGMENT) : null);
        String userInfoTo = (this.userInfo != null ? encodeUriComponent(this.userInfo, charset, Type.USER_INFO) : null);
        String hostTo = (this.host != null ? encodeUriComponent(this.host, charset, getHostType()) : null);
        BiFunction<String, Type, String> encoder = (s, type) -> encodeUriComponent(s, charset, type);
        PathComponent pathTo = this.path.encode(encoder);
        MultiValueMap<String, String> queryParamsTo = encodeQueryParams(encoder);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, this.port, pathTo, queryParamsTo, EncodeState.FULLY_ENCODED, null);
    }

    private MultiValueMap<String, String> encodeQueryParams(BiFunction<String, Type, String> encoder) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        this.queryParams.forEach((key, values) -> {
            String name = encoder.apply(key, Type.QUERY_PARAM);
            List<String> encodedValues = new ArrayList<>(values.size());
            for (String value : values) {
                encodedValues.add(value != null ? encoder.apply(value, Type.QUERY_PARAM) : null);
            }
            result.put(name, encodedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param encoding the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, String encoding, Type type) {
        return encodeUriComponent(source, Charset.forName(encoding), type);
    }

    /**
     * Encode the given source into an encoded String using the rules specified
     * by the given component and with the given options.
     * @param source the source String
     * @param charset the encoding of the source String
     * @param type the URI component for the source
     * @return the encoded URI
     * @throws IllegalArgumentException when the given value is not a valid URI component
     */
    static String encodeUriComponent(String source, Charset charset, Type type) {
        if (!StringUtils.hasLength(source)) {
            return source;
        }
        replacedert.notNull(charset, "Charset must not be null");
        replacedert.notNull(type, "Type must not be null");
        byte[] bytes = source.getBytes(charset);
        ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length);
        boolean changed = false;
        for (byte b : bytes) {
            if (b < 0) {
                b += 256;
            }
            if (type.isAllowed(b)) {
                bos.write(b);
            } else {
                bos.write('%');
                char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
                char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
                bos.write(hex1);
                bos.write(hex2);
                changed = true;
            }
        }
        return (changed ? new String(bos.toByteArray(), charset) : source);
    }

    private Type getHostType() {
        return (this.host != null && this.host.startsWith("[") ? Type.HOST_IPV6 : Type.HOST_IPV4);
    }

    // Verifying
    /**
     * Check if any of the URI components contain any illegal characters.
     * @throws IllegalArgumentException if any component has illegal characters
     */
    private void verify() {
        verifyUriComponent(getScheme(), Type.SCHEME);
        verifyUriComponent(this.userInfo, Type.USER_INFO);
        verifyUriComponent(this.host, getHostType());
        this.path.verify();
        this.queryParams.forEach((key, values) -> {
            verifyUriComponent(key, Type.QUERY_PARAM);
            for (String value : values) {
                verifyUriComponent(value, Type.QUERY_PARAM);
            }
        });
        verifyUriComponent(getFragment(), Type.FRAGMENT);
    }

    private static void verifyUriComponent(@Nullable String source, Type type) {
        if (source == null) {
            return;
        }
        int length = source.length();
        for (int i = 0; i < length; i++) {
            char ch = source.charAt(i);
            if (ch == '%') {
                if ((i + 2) < length) {
                    char hex1 = source.charAt(i + 1);
                    char hex2 = source.charAt(i + 2);
                    int u = Character.digit(hex1, 16);
                    int l = Character.digit(hex2, 16);
                    if (u == -1 || l == -1) {
                        throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                    }
                    i += 2;
                } else {
                    throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\"");
                }
            } else if (!type.isAllowed(ch)) {
                throw new IllegalArgumentException("Invalid character '" + ch + "' for " + type.name() + " in \"" + source + "\"");
            }
        }
    }

    // Expanding
    @Override
    protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
        replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
        String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
        String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
        String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
        String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
        String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
        PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
        MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
        return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
    }

    private MultiValueMap<String, String> expandQueryParams(UriTemplateVariables variables) {
        int size = this.queryParams.size();
        MultiValueMap<String, String> result = new LinkedMultiValueMap<>(size);
        UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables);
        this.queryParams.forEach((key, values) -> {
            String name = expandUriComponent(key, queryVariables, this.variableEncoder);
            List<String> expandedValues = new ArrayList<>(values.size());
            for (String value : values) {
                expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder));
            }
            result.put(name, expandedValues);
        });
        return CollectionUtils.unmodifiableMultiValueMap(result);
    }

    @Override
    public UriComponents normalize() {
        String normalizedPath = StringUtils.cleanPath(getPath());
        FullPathComponent path = new FullPathComponent(normalizedPath);
        return new HierarchicalUriComponents(getScheme(), getFragment(), this.userInfo, this.host, this.port, path, this.queryParams, this.encodeState, this.variableEncoder);
    }

    // Other functionality
    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme()).append(':');
        }
        if (this.userInfo != null || this.host != null) {
            uriBuilder.append("//");
            if (this.userInfo != null) {
                uriBuilder.append(this.userInfo).append('@');
            }
            if (this.host != null) {
                uriBuilder.append(this.host);
            }
            if (getPort() != -1) {
                uriBuilder.append(':').append(this.port);
            }
        }
        String path = getPath();
        if (StringUtils.hasLength(path)) {
            if (uriBuilder.length() != 0 && path.charAt(0) != PATH_DELIMITER) {
                uriBuilder.append(PATH_DELIMITER);
            }
            uriBuilder.append(path);
        }
        String query = getQuery();
        if (query != null) {
            uriBuilder.append('?').append(query);
        }
        if (getFragment() != null) {
            uriBuilder.append('#').append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            if (this.encodeState.isEncoded()) {
                return new URI(toUriString());
            } else {
                String path = getPath();
                if (StringUtils.hasLength(path) && path.charAt(0) != PATH_DELIMITER) {
                    // Only prefix the path delimiter if something exists before it
                    if (getScheme() != null || getUserInfo() != null || getHost() != null || getPort() != -1) {
                        path = PATH_DELIMITER + path;
                    }
                }
                return new URI(getScheme(), getUserInfo(), getHost(), getPort(), path, getQuery(), getFragment());
            }
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        if (getScheme() != null) {
            builder.scheme(getScheme());
        }
        if (getUserInfo() != null) {
            builder.userInfo(getUserInfo());
        }
        if (getHost() != null) {
            builder.host(getHost());
        }
        // Avoid parsing the port, may have URI variable..
        if (this.port != null) {
            builder.port(this.port);
        }
        this.path.copyToUriComponentsBuilder(builder);
        if (!getQueryParams().isEmpty()) {
            builder.queryParams(getQueryParams());
        }
        if (getFragment() != null) {
            builder.fragment(getFragment());
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof HierarchicalUriComponents)) {
            return false;
        }
        HierarchicalUriComponents otherComp = (HierarchicalUriComponents) other;
        return (ObjectUtils.nullSafeEquals(getScheme(), otherComp.getScheme()) && ObjectUtils.nullSafeEquals(getUserInfo(), otherComp.getUserInfo()) && ObjectUtils.nullSafeEquals(getHost(), otherComp.getHost()) && getPort() == otherComp.getPort() && this.path.equals(otherComp.path) && this.queryParams.equals(otherComp.queryParams) && ObjectUtils.nullSafeEquals(getFragment(), otherComp.getFragment()));
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.userInfo);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.host);
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.port);
        result = 31 * result + this.path.hashCode();
        result = 31 * result + this.queryParams.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }

    // Nested types
    /**
     * Enumeration used to identify the allowed characters per URI component.
     * <p>Contains methods to indicate whether a given character is valid in a specific URI component.
     * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
     */
    enum Type {

        SCHEME {

            @Override
            public boolean isAllowed(int c) {
                return isAlpha(c) || isDigit(c) || '+' == c || '-' == c || '.' == c;
            }
        }
        ,
        AUTHORITY {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c;
            }
        }
        ,
        USER_INFO {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || ':' == c;
            }
        }
        ,
        HOST_IPV4 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c);
            }
        }
        ,
        HOST_IPV6 {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c) || isSubDelimiter(c) || '[' == c || ']' == c || ':' == c;
            }
        }
        ,
        PORT {

            @Override
            public boolean isAllowed(int c) {
                return isDigit(c);
            }
        }
        ,
        PATH {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c;
            }
        }
        ,
        PATH_SEGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c);
            }
        }
        ,
        QUERY {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        QUERY_PARAM {

            @Override
            public boolean isAllowed(int c) {
                if ('=' == c || '&' == c) {
                    return false;
                } else {
                    return isPchar(c) || '/' == c || '?' == c;
                }
            }
        }
        ,
        FRAGMENT {

            @Override
            public boolean isAllowed(int c) {
                return isPchar(c) || '/' == c || '?' == c;
            }
        }
        ,
        URI {

            @Override
            public boolean isAllowed(int c) {
                return isUnreserved(c);
            }
        }
        ;

        /**
         * Indicates whether the given character is allowed in this URI component.
         * @return {@code true} if the character is allowed; {@code false} otherwise
         */
        public abstract boolean isAllowed(int c);

        /**
         * Indicates whether the given character is in the {@code ALPHA} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isAlpha(int c) {
            return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
        }

        /**
         * Indicates whether the given character is in the {@code DIGIT} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isDigit(int c) {
            return (c >= '0' && c <= '9');
        }

        /**
         * Indicates whether the given character is in the {@code gen-delims} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isGenericDelimiter(int c) {
            return (':' == c || '/' == c || '?' == c || '#' == c || '[' == c || ']' == c || '@' == c);
        }

        /**
         * Indicates whether the given character is in the {@code sub-delims} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isSubDelimiter(int c) {
            return ('!' == c || '$' == c || '&' == c || '\'' == c || '(' == c || ')' == c || '*' == c || '+' == c || ',' == c || ';' == c || '=' == c);
        }

        /**
         * Indicates whether the given character is in the {@code reserved} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isReserved(int c) {
            return (isGenericDelimiter(c) || isSubDelimiter(c));
        }

        /**
         * Indicates whether the given character is in the {@code unreserved} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isUnreserved(int c) {
            return (isAlpha(c) || isDigit(c) || '-' == c || '.' == c || '_' == c || '~' == c);
        }

        /**
         * Indicates whether the given character is in the {@code pchar} set.
         * @see <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, appendix A</a>
         */
        protected boolean isPchar(int c) {
            return (isUnreserved(c) || isSubDelimiter(c) || ':' == c || '@' == c);
        }
    }

    private enum EncodeState {

        /**
         * Not encoded.
         */
        RAW,
        /**
         * URI vars expanded first and then each URI component encoded by
         * quoting only illegal characters within that URI component.
         */
        FULLY_ENCODED,
        /**
         * URI template encoded first by quoting illegal characters only, and
         * then URI vars encoded more strictly when expanded, by quoting both
         * illegal chars and chars with reserved meaning.
         */
        TEMPLATE_ENCODED;

        public boolean isEncoded() {
            return this.equals(FULLY_ENCODED) || this.equals(TEMPLATE_ENCODED);
        }
    }

    private static clreplaced UriTemplateEncoder implements BiFunction<String, Type, String> {

        private final Charset charset;

        private final StringBuilder currentLiteral = new StringBuilder();

        private final StringBuilder currentVariable = new StringBuilder();

        private final StringBuilder output = new StringBuilder();

        public UriTemplateEncoder(Charset charset) {
            this.charset = charset;
        }

        @Override
        public String apply(String source, Type type) {
            // Only URI variable (nothing to encode)..
            if (source.length() > 1 && source.charAt(0) == '{' && source.charAt(source.length() - 1) == '}') {
                return source;
            }
            // Only literal (encode full source)..
            if (source.indexOf('{') == -1) {
                return encodeUriComponent(source, this.charset, type);
            }
            // Mixed literal parts and URI variables, maybe (encode literal parts only)..
            int level = 0;
            clear(this.currentLiteral);
            clear(this.currentVariable);
            clear(this.output);
            for (char c : source.toCharArray()) {
                if (c == '{') {
                    level++;
                    if (level == 1) {
                        encodeAndAppendCurrentLiteral(type);
                    }
                }
                if (c == '}' && level > 0) {
                    level--;
                    this.currentVariable.append('}');
                    if (level == 0) {
                        this.output.append(this.currentVariable);
                        clear(this.currentVariable);
                    }
                } else if (level > 0) {
                    this.currentVariable.append(c);
                } else {
                    this.currentLiteral.append(c);
                }
            }
            if (level > 0) {
                this.currentLiteral.append(this.currentVariable);
            }
            encodeAndAppendCurrentLiteral(type);
            return this.output.toString();
        }

        private void encodeAndAppendCurrentLiteral(Type type) {
            this.output.append(encodeUriComponent(this.currentLiteral.toString(), this.charset, type));
            clear(this.currentLiteral);
        }

        private void clear(StringBuilder sb) {
            sb.delete(0, sb.length());
        }
    }

    /**
     * Defines the contract for path (segments).
     */
    interface PathComponent extends Serializable {

        String getPath();

        List<String> getPathSegments();

        PathComponent encode(BiFunction<String, Type, String> encoder);

        void verify();

        PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder);

        void copyToUriComponentsBuilder(UriComponentsBuilder builder);
    }

    /**
     * Represents a path backed by a String.
     */
    static final clreplaced FullPathComponent implements PathComponent {

        private final String path;

        public FullPathComponent(@Nullable String path) {
            this.path = (path != null ? path : "");
        }

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

        @Override
        public List<String> getPathSegments() {
            String[] segments = StringUtils.tokenizeToStringArray(getPath(), PATH_DELIMITER_STRING);
            return Collections.unmodifiableList(Arrays.asList(segments));
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            String encodedPath = encoder.apply(getPath(), Type.PATH);
            return new FullPathComponent(encodedPath);
        }

        @Override
        public void verify() {
            verifyUriComponent(getPath(), Type.PATH);
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            String expandedPath = expandUriComponent(getPath(), uriVariables, encoder);
            return new FullPathComponent(expandedPath);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.path(getPath());
        }

        @Override
        public boolean equals(Object other) {
            return (this == other || (other instanceof FullPathComponent && getPath().equals(((FullPathComponent) other).getPath())));
        }

        @Override
        public int hashCode() {
            return getPath().hashCode();
        }
    }

    /**
     * Represents a path backed by a String list (i.e. path segments).
     */
    static final clreplaced PathSegmentComponent implements PathComponent {

        private final List<String> pathSegments;

        public PathSegmentComponent(List<String> pathSegments) {
            replacedert.notNull(pathSegments, "List must not be null");
            this.pathSegments = Collections.unmodifiableList(new ArrayList<>(pathSegments));
        }

        @Override
        public String getPath() {
            StringBuilder pathBuilder = new StringBuilder();
            pathBuilder.append(PATH_DELIMITER);
            for (Iterator<String> iterator = this.pathSegments.iterator(); iterator.hasNext(); ) {
                String pathSegment = iterator.next();
                pathBuilder.append(pathSegment);
                if (iterator.hasNext()) {
                    pathBuilder.append(PATH_DELIMITER);
                }
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            return this.pathSegments;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> encodedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String encodedPathSegment = encoder.apply(pathSegment, Type.PATH_SEGMENT);
                encodedPathSegments.add(encodedPathSegment);
            }
            return new PathSegmentComponent(encodedPathSegments);
        }

        @Override
        public void verify() {
            for (String pathSegment : getPathSegments()) {
                verifyUriComponent(pathSegment, Type.PATH_SEGMENT);
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<String> pathSegments = getPathSegments();
            List<String> expandedPathSegments = new ArrayList<>(pathSegments.size());
            for (String pathSegment : pathSegments) {
                String expandedPathSegment = expandUriComponent(pathSegment, uriVariables, encoder);
                expandedPathSegments.add(expandedPathSegment);
            }
            return new PathSegmentComponent(expandedPathSegments);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            builder.pathSegment(StringUtils.toStringArray(getPathSegments()));
        }

        @Override
        public boolean equals(Object other) {
            return (this == other || (other instanceof PathSegmentComponent && getPathSegments().equals(((PathSegmentComponent) other).getPathSegments())));
        }

        @Override
        public int hashCode() {
            return getPathSegments().hashCode();
        }
    }

    /**
     * Represents a collection of PathComponents.
     */
    static final clreplaced PathComponentComposite implements PathComponent {

        private final List<PathComponent> pathComponents;

        public PathComponentComposite(List<PathComponent> pathComponents) {
            replacedert.notNull(pathComponents, "PathComponent List must not be null");
            this.pathComponents = pathComponents;
        }

        @Override
        public String getPath() {
            StringBuilder pathBuilder = new StringBuilder();
            for (PathComponent pathComponent : this.pathComponents) {
                pathBuilder.append(pathComponent.getPath());
            }
            return pathBuilder.toString();
        }

        @Override
        public List<String> getPathSegments() {
            List<String> result = new ArrayList<>();
            for (PathComponent pathComponent : this.pathComponents) {
                result.addAll(pathComponent.getPathSegments());
            }
            return result;
        }

        @Override
        public PathComponent encode(BiFunction<String, Type, String> encoder) {
            List<PathComponent> encodedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                encodedComponents.add(pathComponent.encode(encoder));
            }
            return new PathComponentComposite(encodedComponents);
        }

        @Override
        public void verify() {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.verify();
            }
        }

        @Override
        public PathComponent expand(UriTemplateVariables uriVariables, @Nullable UnaryOperator<String> encoder) {
            List<PathComponent> expandedComponents = new ArrayList<>(this.pathComponents.size());
            for (PathComponent pathComponent : this.pathComponents) {
                expandedComponents.add(pathComponent.expand(uriVariables, encoder));
            }
            return new PathComponentComposite(expandedComponents);
        }

        @Override
        public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
            for (PathComponent pathComponent : this.pathComponents) {
                pathComponent.copyToUriComponentsBuilder(builder);
            }
        }
    }

    private static clreplaced QueryUriTemplateVariables implements UriTemplateVariables {

        private final UriTemplateVariables delegate;

        public QueryUriTemplateVariables(UriTemplateVariables delegate) {
            this.delegate = delegate;
        }

        @Override
        public Object getValue(@Nullable String name) {
            Object value = this.delegate.getValue(name);
            if (ObjectUtils.isArray(value)) {
                value = StringUtils.arrayToCommaDelimitedString(ObjectUtils.toObjectArray(value));
            }
            return value;
        }
    }
}

19 Source : HierarchicalUriComponents.java
with MIT License
from mindcarver

// Expanding
@Override
protected HierarchicalUriComponents expandInternal(UriTemplateVariables uriVariables) {
    replacedert.state(!this.encodeState.equals(EncodeState.FULLY_ENCODED), "URI components already encoded, and could not possibly contain '{' or '}'.");
    String schemeTo = expandUriComponent(getScheme(), uriVariables, this.variableEncoder);
    String fragmentTo = expandUriComponent(getFragment(), uriVariables, this.variableEncoder);
    String userInfoTo = expandUriComponent(this.userInfo, uriVariables, this.variableEncoder);
    String hostTo = expandUriComponent(this.host, uriVariables, this.variableEncoder);
    String portTo = expandUriComponent(this.port, uriVariables, this.variableEncoder);
    PathComponent pathTo = this.path.expand(uriVariables, this.variableEncoder);
    MultiValueMap<String, String> queryParamsTo = expandQueryParams(uriVariables);
    return new HierarchicalUriComponents(schemeTo, fragmentTo, userInfoTo, hostTo, portTo, pathTo, queryParamsTo, this.encodeState, this.variableEncoder);
}

19 Source : MediaTypeFactory.java
with MIT License
from mindcarver

/**
 * A factory delegate for resolving {@link MediaType} objects
 * from {@link Resource} handles or filenames.
 *
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @since 5.0
 */
public final clreplaced MediaTypeFactory {

    private static final String MIME_TYPES_FILE_NAME = "/org/springframework/http/mime.types";

    private static final MultiValueMap<String, MediaType> fileExtensionToMediaTypes = parseMimeTypes();

    private MediaTypeFactory() {
    }

    /**
     * Parse the {@code mime.types} file found in the resources. Format is:
     * <code>
     * # comments begin with a '#'<br>
     * # the format is <mime type> <space separated file extensions><br>
     * # for example:<br>
     * text/plain    txt text<br>
     * # this would map file.txt and file.text to<br>
     * # the mime type "text/plain"<br>
     * </code>
     * @return a multi-value map, mapping media types to file extensions.
     */
    private static MultiValueMap<String, MediaType> parseMimeTypes() {
        try (InputStream is = MediaTypeFactory.clreplaced.getResourcereplacedtream(MIME_TYPES_FILE_NAME)) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.US_ASCII));
            MultiValueMap<String, MediaType> result = new LinkedMultiValueMap<>();
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.isEmpty() || line.charAt(0) == '#') {
                    continue;
                }
                String[] tokens = StringUtils.tokenizeToStringArray(line, " \t\n\r\f");
                MediaType mediaType = MediaType.parseMediaType(tokens[0]);
                for (int i = 1; i < tokens.length; i++) {
                    String fileExtension = tokens[i].toLowerCase(Locale.ENGLISH);
                    result.add(fileExtension, mediaType);
                }
            }
            return result;
        } catch (IOException ex) {
            throw new IllegalStateException("Could not load '" + MIME_TYPES_FILE_NAME + "'", ex);
        }
    }

    /**
     * Determine a media type for the given resource, if possible.
     * @param resource the resource to introspect
     * @return the corresponding media type, or {@code null} if none found
     */
    public static Optional<MediaType> getMediaType(@Nullable Resource resource) {
        return Optional.ofNullable(resource).map(Resource::getFilename).flatMap(MediaTypeFactory::getMediaType);
    }

    /**
     * Determine a media type for the given file name, if possible.
     * @param filename the file name plus extension
     * @return the corresponding media type, or {@code null} if none found
     */
    public static Optional<MediaType> getMediaType(@Nullable String filename) {
        return getMediaTypes(filename).stream().findFirst();
    }

    /**
     * Determine the media types for the given file name, if possible.
     * @param filename the file name plus extension
     * @return the corresponding media types, or an empty list if none found
     */
    public static List<MediaType> getMediaTypes(@Nullable String filename) {
        return Optional.ofNullable(StringUtils.getFilenameExtension(filename)).map(s -> s.toLowerCase(Locale.ENGLISH)).map(fileExtensionToMediaTypes::get).orElse(Collections.emptyList());
    }
}

19 Source : JsonPathRequestMatchersIntegrationTests.java
with MIT License
from mindcarver

/**
 * Examples of defining expectations on JSON request content with
 * <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
 *
 * @author Rossen Stoyanchev
 * @author Sam Brannen
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchers
 * @see org.springframework.test.web.client.match.JsonPathRequestMatchersTests
 */
public clreplaced JsonPathRequestMatchersIntegrationTests {

    private static final MultiValueMap<String, Person> people = new LinkedMultiValueMap<>();

    static {
        people.add("composers", new Person("Johann Sebastian Bach"));
        people.add("composers", new Person("Johannes Brahms"));
        people.add("composers", new Person("Edvard Grieg"));
        people.add("composers", new Person("Robert Schumann"));
        people.add("performers", new Person("Vladimir Ashkenazy"));
        people.add("performers", new Person("Yehudi Menuhin"));
    }

    private final RestTemplate restTemplate = new RestTemplate(Collections.singletonList(new MappingJackson2HttpMessageConverter()));

    private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate);

    @Test
    public void exists() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0]").exists()).andExpect(jsonPath("$.composers[1]").exists()).andExpect(jsonPath("$.composers[2]").exists()).andExpect(jsonPath("$.composers[3]").exists()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void doesNotExist() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist()).andExpect(jsonPath("$.composers[?(@.name == 'Robert Schuuuuuuman')]").doesNotExist()).andExpect(jsonPath("$.composers[4]").doesNotExist()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void value() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach")).andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin")).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchers() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))).andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))).andExpect(jsonPath("$.composers[0].name", startsWith("Johann"))).andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy"))).andExpect(jsonPath("$.performers[1].name", containsString("di Me"))).andExpect(jsonPath("$.composers[1].name", isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))).andExpect(jsonPath("$.composers[:3].name", hasItem("Johannes Brahms"))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void hamcrestMatchersWithParameterizedJsonPaths() throws Exception {
        String composerName = "$.composers[%s].name";
        String performerName = "$.performers[%s].name";
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath(composerName, 0).value(startsWith("Johann"))).andExpect(jsonPath(performerName, 0).value(endsWith("Ashkenazy"))).andExpect(jsonPath(performerName, 1).value(containsString("di Me"))).andExpect(jsonPath(composerName, 1).value(isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isArray() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers").isArray()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isString() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0].name").isString()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isNumber() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0].someDouble").isNumber()).andRespond(withSuccess());
        executeAndVerify();
    }

    @Test
    public void isBoolean() throws Exception {
        this.mockServer.expect(requestTo("/composers")).andExpect(content().contentType("application/json;charset=UTF-8")).andExpect(jsonPath("$.composers[0].someBoolean").isBoolean()).andRespond(withSuccess());
        executeAndVerify();
    }

    private void executeAndVerify() throws URISyntaxException {
        this.restTemplate.put(new URI("/composers"), people);
        this.mockServer.verify();
    }
}

19 Source : FormParameters.java
with MIT License
from ljtfreitas

public clreplaced FormParameters implements MultiValueMap<String, Object> {

    private final MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();

    public FormParameters(Parameter... parameters) {
        Arrays.stream(parameters).forEach(p -> map.add(p.name(), p.value()));
    }

    @Override
    public void addAll(MultiValueMap<String, Object> source) {
        map.addAll(source);
    }

    @Override
    public void addAll(String key, List<? extends Object> values) {
        map.addAll(key, values);
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public List<Object> get(Object key) {
        return map.get(key);
    }

    @Override
    public List<Object> put(String key, List<Object> value) {
        return map.put(key, value);
    }

    @Override
    public List<Object> remove(Object key) {
        return map.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ? extends List<Object>> m) {
        map.putAll(m);
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public Set<String> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<List<Object>> values() {
        return map.values();
    }

    @Override
    public Set<java.util.Map.Entry<String, List<Object>>> entrySet() {
        return map.entrySet();
    }

    @Override
    public Object getFirst(String key) {
        return map.getFirst(key);
    }

    @Override
    public void add(String key, Object value) {
        map.add(key, value);
    }

    @Override
    public void set(String key, Object value) {
        map.set(key, value);
    }

    @Override
    public void setAll(Map<String, Object> values) {
        map.setAll(values);
    }

    @Override
    public Map<String, Object> toSingleValueMap() {
        return map.toSingleValueMap();
    }

    public static clreplaced Parameter {

        private final String name;

        private final Object value;

        public Parameter(String name, Object value) {
            this.name = name;
            this.value = value;
        }

        public String name() {
            return name;
        }

        public Object value() {
            return value;
        }
    }
}

19 Source : MockMultipartActionRequest.java
with Apache License 2.0
from liferay

/**
 * Mock implementation of the {@link com.liferay.portletmvc4spring.multipart.MultipartActionRequest} interface.
 *
 * <p>Useful for testing application controllers that access multipart uploads. The {@link
 * org.springframework.mock.web.MockMultipartFile} can be used to populate these mock requests with files.
 *
 * @author  Juergen Hoeller
 * @author  Arjen Poutsma
 * @since   2.0
 * @see     org.springframework.mock.web.MockMultipartFile
 */
public clreplaced MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest {

    private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();

    /**
     * Add a file to this request. The parameter name from the multipart form is taken from the {@link
     * org.springframework.web.multipart.MultipartFile#getName()}.
     *
     * @param  file  multipart file to be added
     */
    public void addFile(MultipartFile file) {
        replacedert.notNull(file, "MultipartFile must not be null");
        this.multipartFiles.add(file.getName(), file);
    }

    @Override
    public MultipartFile getFile(String name) {
        return this.multipartFiles.getFirst(name);
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return this.multipartFiles.toSingleValueMap();
    }

    @Override
    public Iterator<String> getFileNames() {
        return this.multipartFiles.keySet().iterator();
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return new LinkedMultiValueMap<String, MultipartFile>(this.multipartFiles);
    }

    @Override
    public String getMultipartContentType(String paramOrFileName) {
        MultipartFile file = getFile(paramOrFileName);
        if (file != null) {
            return file.getContentType();
        } else {
            return null;
        }
    }
}

19 Source : MockMultipartActionRequest.java
with Apache License 2.0
from langtianya

/**
 * Mock implementation of the
 * {@link org.springframework.web.portlet.multipart.MultipartActionRequest} interface.
 *
 * <p>Useful for testing application controllers that access multipart uploads.
 * The {@link org.springframework.mock.web.MockMultipartFile} can be used to
 * populate these mock requests with files.
 *
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @since 2.0
 * @see org.springframework.mock.web.MockMultipartFile
 */
public clreplaced MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest {

    private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();

    /**
     * Add a file to this request. The parameter name from the multipart
     * form is taken from the {@link org.springframework.web.multipart.MultipartFile#getName()}.
     * @param file multipart file to be added
     */
    public void addFile(MultipartFile file) {
        replacedert.notNull(file, "MultipartFile must not be null");
        this.multipartFiles.add(file.getName(), file);
    }

    @Override
    public Iterator<String> getFileNames() {
        return this.multipartFiles.keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return this.multipartFiles.getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return this.multipartFiles.toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return new LinkedMultiValueMap<String, MultipartFile>(this.multipartFiles);
    }

    @Override
    public String getMultipartContentType(String paramOrFileName) {
        MultipartFile file = getFile(paramOrFileName);
        if (file != null) {
            return file.getContentType();
        } else {
            return null;
        }
    }
}

19 Source : FlashMap.java
with Apache License 2.0
from langtianya

/**
 * A FlashMap provides a way for one request to store attributes intended for
 * use in another. This is most commonly needed when redirecting from one URL
 * to another -- e.g. the Post/Redirect/Get pattern. A FlashMap is saved before
 * the redirect (typically in the session) and is made available after the
 * redirect and removed immediately.
 *
 * <p>A FlashMap can be set up with a request path and request parameters to
 * help identify the target request. Without this information, a FlashMap is
 * made available to the next request, which may or may not be the intended
 * recipient. On a redirect, the target URL is known and a FlashMap can be
 * updated with that information. This is done automatically when the
 * {@code org.springframework.web.servlet.view.RedirectView} is used.
 *
 * <p>Note: annotated controllers will usually not use FlashMap directly.
 * See {@code org.springframework.web.servlet.mvc.support.RedirectAttributes}
 * for an overview of using flash attributes in annotated controllers.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @see FlashMapManager
 */
@SuppressWarnings("serial")
public final clreplaced FlashMap extends HashMap<String, Object> implements Comparable<FlashMap> {

    private String targetRequestPath;

    private final MultiValueMap<String, String> targetRequestParams = new LinkedMultiValueMap<String, String>(4);

    private long expirationTime = -1;

    /**
     * Provide a URL path to help identify the target request for this FlashMap.
     * <p>The path may be absolute (e.g. "/application/resource") or relative to the
     * current request (e.g. "../resource").
     */
    public void setTargetRequestPath(String path) {
        this.targetRequestPath = path;
    }

    /**
     * Return the target URL path (or {@code null} if none specified).
     */
    public String getTargetRequestPath() {
        return this.targetRequestPath;
    }

    /**
     * Provide request parameters identifying the request for this FlashMap.
     * @param params a Map with the names and values of expected parameters
     */
    public FlashMap addTargetRequestParams(MultiValueMap<String, String> params) {
        if (params != null) {
            for (String key : params.keySet()) {
                for (String value : params.get(key)) {
                    addTargetRequestParam(key, value);
                }
            }
        }
        return this;
    }

    /**
     * Provide a request parameter identifying the request for this FlashMap.
     * @param name the expected parameter name (skipped if empty or {@code null})
     * @param value the expected value (skipped if empty or {@code null})
     */
    public FlashMap addTargetRequestParam(String name, String value) {
        if (StringUtils.hasText(name) && StringUtils.hasText(value)) {
            this.targetRequestParams.add(name, value);
        }
        return this;
    }

    /**
     * Return the parameters identifying the target request, or an empty map.
     */
    public MultiValueMap<String, String> getTargetRequestParams() {
        return this.targetRequestParams;
    }

    /**
     * Start the expiration period for this instance.
     * @param timeToLive the number of seconds before expiration
     */
    public void startExpirationPeriod(int timeToLive) {
        this.expirationTime = System.currentTimeMillis() + timeToLive * 1000;
    }

    /**
     * Set the expiration time for the FlashMap. This is provided for serialization
     * purposes but can also be used instead {@link #startExpirationPeriod(int)}.
     * @since 4.2
     */
    public void setExpirationTime(long expirationTime) {
        this.expirationTime = expirationTime;
    }

    /**
     * Return the expiration time for the FlashMap or -1 if the expiration
     * period has not started.
     * @since 4.2
     */
    public long getExpirationTime() {
        return this.expirationTime;
    }

    /**
     * Return whether this instance has expired depending on the amount of
     * elapsed time since the call to {@link #startExpirationPeriod}.
     */
    public boolean isExpired() {
        return (this.expirationTime != -1 && System.currentTimeMillis() > this.expirationTime);
    }

    /**
     * Compare two FlashMaps and prefer the one that specifies a target URL
     * path or has more target URL parameters. Before comparing FlashMap
     * instances ensure that they match a given request.
     */
    @Override
    public int compareTo(FlashMap other) {
        int thisUrlPath = (this.targetRequestPath != null ? 1 : 0);
        int otherUrlPath = (other.targetRequestPath != null ? 1 : 0);
        if (thisUrlPath != otherUrlPath) {
            return otherUrlPath - thisUrlPath;
        } else {
            return other.targetRequestParams.size() - this.targetRequestParams.size();
        }
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof FlashMap)) {
            return false;
        }
        FlashMap otherFlashMap = (FlashMap) other;
        return (super.equals(otherFlashMap) && ObjectUtils.nullSafeEquals(this.targetRequestPath, otherFlashMap.targetRequestPath) && this.targetRequestParams.equals(otherFlashMap.targetRequestParams));
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.targetRequestPath);
        result = 31 * result + this.targetRequestParams.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "FlashMap [attributes=" + super.toString() + ", targetRequestPath=" + this.targetRequestPath + ", targetRequestParams=" + this.targetRequestParams + "]";
    }
}

19 Source : MockMultipartHttpServletRequest.java
with Apache License 2.0
from langtianya

/**
 * Mock implementation of the
 * {@link org.springframework.web.multipart.MultipartHttpServletRequest} interface.
 *
 * <p>As of Spring 4.0, this set of mocks is designed on a Servlet 3.0 baseline.
 *
 * <p>Useful for testing application controllers that access multipart uploads.
 * The {@link MockMultipartFile} can be used to populate these mock requests
 * with files.
 *
 * @author Juergen Hoeller
 * @author Eric Crampton
 * @author Arjen Poutsma
 * @since 2.0
 * @see MockMultipartFile
 */
public clreplaced MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {

    private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with a default
     * {@link MockServletContext}.
     * @see #MockMultipartHttpServletRequest(ServletContext)
     */
    public MockMultipartHttpServletRequest() {
        this(null);
    }

    /**
     * Create a new {@code MockMultipartHttpServletRequest} with the supplied {@link ServletContext}.
     * @param servletContext the ServletContext that the request runs in
     * (may be {@code null} to use a default {@link MockServletContext})
     */
    public MockMultipartHttpServletRequest(ServletContext servletContext) {
        super(servletContext);
        setMethod("POST");
        setContentType("multipart/form-data");
    }

    /**
     * Add a file to this request. The parameter name from the multipart
     * form is taken from the {@link MultipartFile#getName()}.
     * @param file multipart file to be added
     */
    public void addFile(MultipartFile file) {
        replacedert.notNull(file, "MultipartFile must not be null");
        this.multipartFiles.add(file.getName(), file);
    }

    @Override
    public Iterator<String> getFileNames() {
        return this.multipartFiles.keySet().iterator();
    }

    @Override
    public MultipartFile getFile(String name) {
        return this.multipartFiles.getFirst(name);
    }

    @Override
    public List<MultipartFile> getFiles(String name) {
        List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
        if (multipartFiles != null) {
            return multipartFiles;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, MultipartFile> getFileMap() {
        return this.multipartFiles.toSingleValueMap();
    }

    @Override
    public MultiValueMap<String, MultipartFile> getMultiFileMap() {
        return new LinkedMultiValueMap<String, MultipartFile>(this.multipartFiles);
    }

    @Override
    public String getMultipartContentType(String paramOrFileName) {
        MultipartFile file = getFile(paramOrFileName);
        if (file != null) {
            return file.getContentType();
        } else {
            return null;
        }
    }

    @Override
    public HttpMethod getRequestMethod() {
        return HttpMethod.resolve(getMethod());
    }

    @Override
    public HttpHeaders getRequestHeaders() {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, Collections.list(getHeaders(headerName)));
        }
        return headers;
    }

    @Override
    public HttpHeaders getMultipartHeaders(String paramOrFileName) {
        String contentType = getMultipartContentType(paramOrFileName);
        if (contentType != null) {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", contentType);
            return headers;
        } else {
            return null;
        }
    }
}

19 Source : UriComponentsBuilder.java
with Apache License 2.0
from langtianya

/**
 * Builder for {@link UriComponents}.
 *
 * <p>Typical usage involves:
 * <ol>
 * <li>Create a {@code UriComponentsBuilder} with one of the static factory methods
 * (such as {@link #fromPath(String)} or {@link #fromUri(URI)})</li>
 * <li>Set the various URI components through the respective methods ({@link #scheme(String)},
 * {@link #userInfo(String)}, {@link #host(String)}, {@link #port(int)}, {@link #path(String)},
 * {@link #pathSegment(String...)}, {@link #queryParam(String, Object...)}, and
 * {@link #fragment(String)}.</li>
 * <li>Build the {@link UriComponents} instance with the {@link #build()} method.</li>
 * </ol>
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @author Phillip Webb
 * @author Oliver Gierke
 * @since 3.1
 * @see #newInstance()
 * @see #fromPath(String)
 * @see #fromUri(URI)
 */
public clreplaced UriComponentsBuilder implements Cloneable {

    private static final Pattern QUERY_PARAM_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?");

    private static final String SCHEME_PATTERN = "([^:/?#]+):";

    private static final String HTTP_PATTERN = "(?i)(http|https):";

    private static final String USERINFO_PATTERN = "([^@\\[/?#]*)";

    private static final String HOST_IPV4_PATTERN = "[^\\[/?#:]*";

    private static final String HOST_IPV6_PATTERN = "\\[[\\p{XDigit}\\:\\.]*[%\\p{Alnum}]*\\]";

    private static final String HOST_PATTERN = "(" + HOST_IPV6_PATTERN + "|" + HOST_IPV4_PATTERN + ")";

    private static final String PORT_PATTERN = "(\\d*(?:\\{[^/]+?\\})?)";

    private static final String PATH_PATTERN = "([^?#]*)";

    private static final String QUERY_PATTERN = "([^#]*)";

    private static final String LAST_PATTERN = "(.*)";

    // Regex patterns that matches URIs. See RFC 3986, appendix B
    private static final Pattern URI_PATTERN = Pattern.compile("^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?");

    private static final Pattern HTTP_URL_PATTERN = Pattern.compile("^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?");

    private static final Pattern FORWARDED_HOST_PATTERN = Pattern.compile("host=\"?([^;,\"]+)\"?");

    private static final Pattern FORWARDED_PROTO_PATTERN = Pattern.compile("proto=\"?([^;,\"]+)\"?");

    private String scheme;

    private String ssp;

    private String userInfo;

    private String host;

    private String port;

    private CompositePathComponentBuilder pathBuilder;

    private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();

    private String fragment;

    /**
     * Default constructor. Protected to prevent direct instantiation.
     * @see #newInstance()
     * @see #fromPath(String)
     * @see #fromUri(URI)
     */
    protected UriComponentsBuilder() {
        this.pathBuilder = new CompositePathComponentBuilder();
    }

    /**
     * Create a deep copy of the given UriComponentsBuilder.
     * @param other the other builder to copy from
     */
    protected UriComponentsBuilder(UriComponentsBuilder other) {
        this.scheme = other.scheme;
        this.ssp = other.ssp;
        this.userInfo = other.userInfo;
        this.host = other.host;
        this.port = other.port;
        this.pathBuilder = (CompositePathComponentBuilder) other.pathBuilder.clone();
        this.queryParams.putAll(other.queryParams);
        this.fragment = other.fragment;
    }

    // Factory methods
    /**
     * Create a new, empty builder.
     * @return the new {@code UriComponentsBuilder}
     */
    public static UriComponentsBuilder newInstance() {
        return new UriComponentsBuilder();
    }

    /**
     * Create a builder that is initialized with the given path.
     * @param path the path to initialize with
     * @return the new {@code UriComponentsBuilder}
     */
    public static UriComponentsBuilder fromPath(String path) {
        UriComponentsBuilder builder = new UriComponentsBuilder();
        builder.path(path);
        return builder;
    }

    /**
     * Create a builder that is initialized with the given {@code URI}.
     * @param uri the URI to initialize with
     * @return the new {@code UriComponentsBuilder}
     */
    public static UriComponentsBuilder fromUri(URI uri) {
        UriComponentsBuilder builder = new UriComponentsBuilder();
        builder.uri(uri);
        return builder;
    }

    /**
     * Create a builder that is initialized with the given URI string.
     * <p><strong>Note:</strong> The presence of reserved characters can prevent
     * correct parsing of the URI string. For example if a query parameter
     * contains {@code '='} or {@code '&'} characters, the query string cannot
     * be parsed unambiguously. Such values should be subsreplaceduted for URI
     * variables to enable correct parsing:
     * <pre clreplaced="code">
     * String uriString = "/hotels/42?filter={value}";
     * UriComponentsBuilder.fromUriString(uriString).buildAndExpand("hot&cold");
     * </pre>
     * @param uri the URI string to initialize with
     * @return the new {@code UriComponentsBuilder}
     */
    public static UriComponentsBuilder fromUriString(String uri) {
        replacedert.notNull(uri, "URI must not be null");
        Matcher matcher = URI_PATTERN.matcher(uri);
        if (matcher.matches()) {
            UriComponentsBuilder builder = new UriComponentsBuilder();
            String scheme = matcher.group(2);
            String userInfo = matcher.group(5);
            String host = matcher.group(6);
            String port = matcher.group(8);
            String path = matcher.group(9);
            String query = matcher.group(11);
            String fragment = matcher.group(13);
            boolean opaque = false;
            if (StringUtils.hasLength(scheme)) {
                String rest = uri.substring(scheme.length());
                if (!rest.startsWith(":/")) {
                    opaque = true;
                }
            }
            builder.scheme(scheme);
            if (opaque) {
                String ssp = uri.substring(scheme.length()).substring(1);
                if (StringUtils.hasLength(fragment)) {
                    ssp = ssp.substring(0, ssp.length() - (fragment.length() + 1));
                }
                builder.schemeSpecificPart(ssp);
            } else {
                builder.userInfo(userInfo);
                builder.host(host);
                if (StringUtils.hasLength(port)) {
                    builder.port(port);
                }
                builder.path(path);
                builder.query(query);
            }
            if (StringUtils.hasText(fragment)) {
                builder.fragment(fragment);
            }
            return builder;
        } else {
            throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
        }
    }

    /**
     * Create a URI components builder from the given HTTP URL String.
     * <p><strong>Note:</strong> The presence of reserved characters can prevent
     * correct parsing of the URI string. For example if a query parameter
     * contains {@code '='} or {@code '&'} characters, the query string cannot
     * be parsed unambiguously. Such values should be subsreplaceduted for URI
     * variables to enable correct parsing:
     * <pre clreplaced="code">
     * String uriString = "/hotels/42?filter={value}";
     * UriComponentsBuilder.fromUriString(uriString).buildAndExpand("hot&cold");
     * </pre>
     * @param httpUrl the source URI
     * @return the URI components of the URI
     */
    public static UriComponentsBuilder fromHttpUrl(String httpUrl) {
        replacedert.notNull(httpUrl, "HTTP URL must not be null");
        Matcher matcher = HTTP_URL_PATTERN.matcher(httpUrl);
        if (matcher.matches()) {
            UriComponentsBuilder builder = new UriComponentsBuilder();
            String scheme = matcher.group(1);
            builder.scheme(scheme != null ? scheme.toLowerCase() : null);
            builder.userInfo(matcher.group(4));
            String host = matcher.group(5);
            if (StringUtils.hasLength(scheme) && !StringUtils.hasLength(host)) {
                throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
            }
            builder.host(host);
            String port = matcher.group(7);
            if (StringUtils.hasLength(port)) {
                builder.port(port);
            }
            builder.path(matcher.group(8));
            builder.query(matcher.group(10));
            return builder;
        } else {
            throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
        }
    }

    /**
     * Create a new {@code UriComponents} object from the URI replacedociated with
     * the given HttpRequest while also overlaying with values from the headers
     * "Forwarded" (<a href="http://tools.ietf.org/html/rfc7239">RFC 7239</a>, or
     * "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if "Forwarded" is
     * not found.
     * @param request the source request
     * @return the URI components of the URI
     * @since 4.1.5
     */
    public static UriComponentsBuilder fromHttpRequest(HttpRequest request) {
        URI uri = request.getURI();
        UriComponentsBuilder builder = UriComponentsBuilder.fromUri(uri);
        String scheme = uri.getScheme();
        String host = uri.getHost();
        int port = uri.getPort();
        String forwardedHeader = request.getHeaders().getFirst("Forwarded");
        if (StringUtils.hasText(forwardedHeader)) {
            String forwardedToUse = StringUtils.commaDelimitedListToStringArray(forwardedHeader)[0];
            Matcher m = FORWARDED_HOST_PATTERN.matcher(forwardedToUse);
            if (m.find()) {
                host = m.group(1).trim();
            }
            m = FORWARDED_PROTO_PATTERN.matcher(forwardedToUse);
            if (m.find()) {
                scheme = m.group(1).trim();
            }
        } else {
            String hostHeader = request.getHeaders().getFirst("X-Forwarded-Host");
            if (StringUtils.hasText(hostHeader)) {
                String[] hosts = StringUtils.commaDelimitedListToStringArray(hostHeader);
                String hostToUse = hosts[0];
                if (hostToUse.contains(":")) {
                    String[] hostAndPort = StringUtils.split(hostToUse, ":");
                    host = hostAndPort[0];
                    port = Integer.parseInt(hostAndPort[1]);
                } else {
                    host = hostToUse;
                    port = -1;
                }
            }
            String portHeader = request.getHeaders().getFirst("X-Forwarded-Port");
            if (StringUtils.hasText(portHeader)) {
                String[] ports = StringUtils.commaDelimitedListToStringArray(portHeader);
                port = Integer.parseInt(ports[0]);
            }
            String protocolHeader = request.getHeaders().getFirst("X-Forwarded-Proto");
            if (StringUtils.hasText(protocolHeader)) {
                String[] protocols = StringUtils.commaDelimitedListToStringArray(protocolHeader);
                scheme = protocols[0];
            }
        }
        builder.scheme(scheme);
        builder.host(host);
        builder.port(null);
        if (scheme.equals("http") && port != 80 || scheme.equals("https") && port != 443) {
            builder.port(port);
        }
        return builder;
    }

    /**
     * Create an instance by parsing the "Origin" header of an HTTP request.
     * @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454</a>
     */
    public static UriComponentsBuilder fromOriginHeader(String origin) {
        Matcher matcher = URI_PATTERN.matcher(origin);
        if (matcher.matches()) {
            UriComponentsBuilder builder = new UriComponentsBuilder();
            String scheme = matcher.group(2);
            String host = matcher.group(6);
            String port = matcher.group(8);
            if (StringUtils.hasLength(scheme)) {
                builder.scheme(scheme);
            }
            builder.host(host);
            if (StringUtils.hasLength(port)) {
                builder.port(port);
            }
            return builder;
        } else {
            throw new IllegalArgumentException("[" + origin + "] is not a valid \"Origin\" header value");
        }
    }

    // build methods
    /**
     * Build a {@code UriComponents} instance from the various components contained in this builder.
     * @return the URI components
     */
    public UriComponents build() {
        return build(false);
    }

    /**
     * Build a {@code UriComponents} instance from the various components
     * contained in this builder.
     * @param encoded whether all the components set in this builder are
     * encoded ({@code true}) or not ({@code false})
     * @return the URI components
     */
    public UriComponents build(boolean encoded) {
        if (this.ssp != null) {
            return new OpaqueUriComponents(this.scheme, this.ssp, this.fragment);
        } else {
            return new HierarchicalUriComponents(this.scheme, this.userInfo, this.host, this.port, this.pathBuilder.build(), this.queryParams, this.fragment, encoded, true);
        }
    }

    /**
     * Build a {@code UriComponents} instance and replaces URI template variables
     * with the values from a map. This is a shortcut method which combines
     * calls to {@link #build()} and then {@link UriComponents#expand(Map)}.
     * @param uriVariables the map of URI variables
     * @return the URI components with expanded values
     */
    public UriComponents buildAndExpand(Map<String, ?> uriVariables) {
        return build(false).expand(uriVariables);
    }

    /**
     * Build a {@code UriComponents} instance and replaces URI template variables
     * with the values from an array. This is a shortcut method which combines
     * calls to {@link #build()} and then {@link UriComponents#expand(Object...)}.
     * @param uriVariableValues URI variable values
     * @return the URI components with expanded values
     */
    public UriComponents buildAndExpand(Object... uriVariableValues) {
        return build(false).expand(uriVariableValues);
    }

    /**
     * Build a URI String. This is a shortcut method which combines calls
     * to {@link #build()}, then {@link UriComponents#encode()} and finally
     * {@link UriComponents#toUriString()}.
     * @since 4.1
     * @see UriComponents#toUriString()
     */
    public String toUriString() {
        return build(false).encode().toUriString();
    }

    // URI components methods
    /**
     * Initialize all components of this URI builder with the components of the given URI.
     * @param uri the URI
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder uri(URI uri) {
        replacedert.notNull(uri, "URI must not be null");
        this.scheme = uri.getScheme();
        if (uri.isOpaque()) {
            this.ssp = uri.getRawSchemeSpecificPart();
            resetHierarchicalComponents();
        } else {
            if (uri.getRawUserInfo() != null) {
                this.userInfo = uri.getRawUserInfo();
            }
            if (uri.getHost() != null) {
                this.host = uri.getHost();
            }
            if (uri.getPort() != -1) {
                this.port = String.valueOf(uri.getPort());
            }
            if (StringUtils.hasLength(uri.getRawPath())) {
                this.pathBuilder = new CompositePathComponentBuilder(uri.getRawPath());
            }
            if (StringUtils.hasLength(uri.getRawQuery())) {
                this.queryParams.clear();
                query(uri.getRawQuery());
            }
            resetSchemeSpecificPart();
        }
        if (uri.getRawFragment() != null) {
            this.fragment = uri.getRawFragment();
        }
        return this;
    }

    private void resetHierarchicalComponents() {
        this.userInfo = null;
        this.host = null;
        this.port = null;
        this.pathBuilder = new CompositePathComponentBuilder();
        this.queryParams.clear();
    }

    private void resetSchemeSpecificPart() {
        this.ssp = null;
    }

    /**
     * Set the URI scheme. The given scheme may contain URI template variables,
     * and may also be {@code null} to clear the scheme of this builder.
     * @param scheme the URI scheme
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder scheme(String scheme) {
        this.scheme = scheme;
        return this;
    }

    /**
     * Set all components of this URI builder from the given {@link UriComponents}.
     * @param uriComponents the UriComponents instance
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder uriComponents(UriComponents uriComponents) {
        replacedert.notNull(uriComponents, "UriComponents must not be null");
        uriComponents.copyToUriComponentsBuilder(this);
        return this;
    }

    /**
     * Set the URI scheme-specific-part. When invoked, this method overwrites
     * {@linkplain #userInfo(String) user-info}, {@linkplain #host(String) host},
     * {@linkplain #port(int) port}, {@linkplain #path(String) path}, and
     * {@link #query(String) query}.
     * @param ssp the URI scheme-specific-part, may contain URI template parameters
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder schemeSpecificPart(String ssp) {
        this.ssp = ssp;
        resetHierarchicalComponents();
        return this;
    }

    /**
     * Set the URI user info. The given user info may contain URI template variables,
     * and may also be {@code null} to clear the user info of this builder.
     * @param userInfo the URI user info
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder userInfo(String userInfo) {
        this.userInfo = userInfo;
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the URI host. The given host may contain URI template variables,
     * and may also be {@code null} to clear the host of this builder.
     * @param host the URI host
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder host(String host) {
        this.host = host;
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the URI port. Preplaceding {@code -1} will clear the port of this builder.
     * @param port the URI port
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder port(int port) {
        replacedert.isTrue(port >= -1, "Port must be >= -1");
        this.port = String.valueOf(port);
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the URI port. Use this method only when the port needs to be
     * parameterized with a URI variable. Otherwise use {@link #port(int)}.
     * Preplaceding {@code null} will clear the port of this builder.
     * @param port the URI port
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder port(String port) {
        this.port = port;
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Append the given path to the existing path of this builder.
     * The given path may contain URI template variables.
     * @param path the URI path
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder path(String path) {
        this.pathBuilder.addPath(path);
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the path of this builder overriding all existing path and path segment values.
     * @param path the URI path; a {@code null} value results in an empty path.
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder replacePath(String path) {
        this.pathBuilder = new CompositePathComponentBuilder(path);
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Append path segments to the existing path. Each path segment may contain
     * URI template variables and should not contain any slashes.
     * Use {@code path("/")} subsequently to ensure a trailing slash.
     * @param pathSegments the URI path segments
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder pathSegment(String... pathSegments) throws IllegalArgumentException {
        this.pathBuilder.addPathSegments(pathSegments);
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Append the given query to the existing query of this builder.
     * The given query may contain URI template variables.
     * <p><strong>Note:</strong> The presence of reserved characters can prevent
     * correct parsing of the URI string. For example if a query parameter
     * contains {@code '='} or {@code '&'} characters, the query string cannot
     * be parsed unambiguously. Such values should be subsreplaceduted for URI
     * variables to enable correct parsing:
     * <pre clreplaced="code">
     * UriComponentsBuilder.fromUriString("/hotels/42")
     * 	.query("filter={value}")
     * 	.buildAndExpand("hot&cold");
     * </pre>
     * @param query the query string
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder query(String query) {
        if (query != null) {
            Matcher matcher = QUERY_PARAM_PATTERN.matcher(query);
            while (matcher.find()) {
                String name = matcher.group(1);
                String eq = matcher.group(2);
                String value = matcher.group(3);
                queryParam(name, (value != null ? value : (StringUtils.hasLength(eq) ? "" : null)));
            }
        } else {
            this.queryParams.clear();
        }
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the query of this builder overriding all existing query parameters.
     * @param query the query string; a {@code null} value removes all query parameters.
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder replaceQuery(String query) {
        this.queryParams.clear();
        query(query);
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Append the given query parameter to the existing query parameters. The
     * given name or any of the values may contain URI template variables. If no
     * values are given, the resulting URI will contain the query parameter name
     * only (i.e. {@code ?foo} instead of {@code ?foo=bar}.
     * @param name the query parameter name
     * @param values the query parameter values
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder queryParam(String name, Object... values) {
        replacedert.notNull(name, "Name must not be null");
        if (!ObjectUtils.isEmpty(values)) {
            for (Object value : values) {
                String valuereplacedtring = (value != null ? value.toString() : null);
                this.queryParams.add(name, valuereplacedtring);
            }
        } else {
            this.queryParams.add(name, null);
        }
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Add the given query parameters.
     * @param params the params
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder queryParams(MultiValueMap<String, String> params) {
        if (params != null) {
            this.queryParams.putAll(params);
        }
        return this;
    }

    /**
     * Set the query parameter values overriding all existing query values for
     * the same parameter. If no values are given, the query parameter is removed.
     * @param name the query parameter name
     * @param values the query parameter values
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder replaceQueryParam(String name, Object... values) {
        replacedert.notNull(name, "Name must not be null");
        this.queryParams.remove(name);
        if (!ObjectUtils.isEmpty(values)) {
            queryParam(name, values);
        }
        resetSchemeSpecificPart();
        return this;
    }

    /**
     * Set the query parameter values overriding all existing query values.
     * @param params the query parameter name
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder replaceQueryParams(MultiValueMap<String, String> params) {
        this.queryParams.clear();
        if (params != null) {
            this.queryParams.putAll(params);
        }
        return this;
    }

    /**
     * Set the URI fragment. The given fragment may contain URI template variables,
     * and may also be {@code null} to clear the fragment of this builder.
     * @param fragment the URI fragment
     * @return this UriComponentsBuilder
     */
    public UriComponentsBuilder fragment(String fragment) {
        if (fragment != null) {
            replacedert.hasLength(fragment, "Fragment must not be empty");
            this.fragment = fragment;
        } else {
            this.fragment = null;
        }
        return this;
    }

    @Override
    public Object clone() {
        return new UriComponentsBuilder(this);
    }

    private interface PathComponentBuilder extends Cloneable {

        PathComponent build();

        Object clone();
    }

    private static clreplaced CompositePathComponentBuilder implements PathComponentBuilder {

        private final LinkedList<PathComponentBuilder> builders = new LinkedList<PathComponentBuilder>();

        public CompositePathComponentBuilder() {
        }

        public CompositePathComponentBuilder(String path) {
            addPath(path);
        }

        public void addPathSegments(String... pathSegments) {
            if (!ObjectUtils.isEmpty(pathSegments)) {
                PathSegmentComponentBuilder psBuilder = getLastBuilder(PathSegmentComponentBuilder.clreplaced);
                FullPathComponentBuilder fpBuilder = getLastBuilder(FullPathComponentBuilder.clreplaced);
                if (psBuilder == null) {
                    psBuilder = new PathSegmentComponentBuilder();
                    this.builders.add(psBuilder);
                    if (fpBuilder != null) {
                        fpBuilder.removeTrailingSlash();
                    }
                }
                psBuilder.append(pathSegments);
            }
        }

        public void addPath(String path) {
            if (StringUtils.hasText(path)) {
                PathSegmentComponentBuilder psBuilder = getLastBuilder(PathSegmentComponentBuilder.clreplaced);
                FullPathComponentBuilder fpBuilder = getLastBuilder(FullPathComponentBuilder.clreplaced);
                if (psBuilder != null) {
                    path = path.startsWith("/") ? path : "/" + path;
                }
                if (fpBuilder == null) {
                    fpBuilder = new FullPathComponentBuilder();
                    this.builders.add(fpBuilder);
                }
                fpBuilder.append(path);
            }
        }

        @SuppressWarnings("unchecked")
        private <T> T getLastBuilder(Clreplaced<T> builderClreplaced) {
            if (!this.builders.isEmpty()) {
                PathComponentBuilder last = this.builders.getLast();
                if (builderClreplaced.isInstance(last)) {
                    return (T) last;
                }
            }
            return null;
        }

        @Override
        public PathComponent build() {
            int size = this.builders.size();
            List<PathComponent> components = new ArrayList<PathComponent>(size);
            for (PathComponentBuilder componentBuilder : this.builders) {
                PathComponent pathComponent = componentBuilder.build();
                if (pathComponent != null) {
                    components.add(pathComponent);
                }
            }
            if (components.isEmpty()) {
                return HierarchicalUriComponents.NULL_PATH_COMPONENT;
            }
            if (components.size() == 1) {
                return components.get(0);
            }
            return new HierarchicalUriComponents.PathComponentComposite(components);
        }

        @Override
        public Object clone() {
            CompositePathComponentBuilder compositeBuilder = new CompositePathComponentBuilder();
            for (PathComponentBuilder builder : this.builders) {
                compositeBuilder.builders.add((PathComponentBuilder) builder.clone());
            }
            return compositeBuilder;
        }
    }

    private static clreplaced FullPathComponentBuilder implements PathComponentBuilder {

        private final StringBuilder path = new StringBuilder();

        public void append(String path) {
            this.path.append(path);
        }

        @Override
        public PathComponent build() {
            if (this.path.length() == 0) {
                return null;
            }
            String path = this.path.toString();
            while (true) {
                int index = path.indexOf("//");
                if (index == -1) {
                    break;
                }
                path = path.substring(0, index) + path.substring(index + 1);
            }
            return new HierarchicalUriComponents.FullPathComponent(path);
        }

        public void removeTrailingSlash() {
            int index = this.path.length() - 1;
            if (this.path.charAt(index) == '/') {
                this.path.deleteCharAt(index);
            }
        }

        @Override
        public Object clone() {
            FullPathComponentBuilder builder = new FullPathComponentBuilder();
            builder.append(this.path.toString());
            return builder;
        }
    }

    private static clreplaced PathSegmentComponentBuilder implements PathComponentBuilder {

        private final List<String> pathSegments = new LinkedList<String>();

        public void append(String... pathSegments) {
            for (String pathSegment : pathSegments) {
                if (StringUtils.hasText(pathSegment)) {
                    this.pathSegments.add(pathSegment);
                }
            }
        }

        @Override
        public PathComponent build() {
            return (this.pathSegments.isEmpty() ? null : new HierarchicalUriComponents.PathSegmentComponent(this.pathSegments));
        }

        @Override
        public Object clone() {
            PathSegmentComponentBuilder builder = new PathSegmentComponentBuilder();
            builder.pathSegments.addAll(this.pathSegments);
            return builder;
        }
    }
}

19 Source : OpaqueUriComponents.java
with Apache License 2.0
from langtianya

/**
 * Extension of {@link UriComponents} for opaque URIs.
 *
 * @author Arjen Poutsma
 * @author Phillip Webb
 * @since 3.2
 * @see <a href="http://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical vs Opaque URIs</a>
 */
@SuppressWarnings("serial")
final clreplaced OpaqueUriComponents extends UriComponents {

    private static final MultiValueMap<String, String> QUERY_PARAMS_NONE = new LinkedMultiValueMap<String, String>(0);

    private final String ssp;

    OpaqueUriComponents(String scheme, String schemeSpecificPart, String fragment) {
        super(scheme, fragment);
        this.ssp = schemeSpecificPart;
    }

    @Override
    public String getSchemeSpecificPart() {
        return this.ssp;
    }

    @Override
    public String getUserInfo() {
        return null;
    }

    @Override
    public String getHost() {
        return null;
    }

    @Override
    public int getPort() {
        return -1;
    }

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

    @Override
    public List<String> getPathSegments() {
        return Collections.emptyList();
    }

    @Override
    public String getQuery() {
        return null;
    }

    @Override
    public MultiValueMap<String, String> getQueryParams() {
        return QUERY_PARAMS_NONE;
    }

    @Override
    public UriComponents encode(String encoding) throws UnsupportedEncodingException {
        return this;
    }

    @Override
    protected UriComponents expandInternal(UriTemplateVariables uriVariables) {
        String expandedScheme = expandUriComponent(getScheme(), uriVariables);
        String expandedSsp = expandUriComponent(getSchemeSpecificPart(), uriVariables);
        String expandedFragment = expandUriComponent(getFragment(), uriVariables);
        return new OpaqueUriComponents(expandedScheme, expandedSsp, expandedFragment);
    }

    @Override
    public UriComponents normalize() {
        return this;
    }

    @Override
    public String toUriString() {
        StringBuilder uriBuilder = new StringBuilder();
        if (getScheme() != null) {
            uriBuilder.append(getScheme());
            uriBuilder.append(':');
        }
        if (this.ssp != null) {
            uriBuilder.append(this.ssp);
        }
        if (getFragment() != null) {
            uriBuilder.append('#');
            uriBuilder.append(getFragment());
        }
        return uriBuilder.toString();
    }

    @Override
    public URI toUri() {
        try {
            return new URI(getScheme(), this.ssp, getFragment());
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not create URI object: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
        builder.scheme(getScheme());
        builder.schemeSpecificPart(getSchemeSpecificPart());
        builder.fragment(getFragment());
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof OpaqueUriComponents)) {
            return false;
        }
        OpaqueUriComponents other = (OpaqueUriComponents) obj;
        return ObjectUtils.nullSafeEquals(getScheme(), other.getScheme()) && ObjectUtils.nullSafeEquals(this.ssp, other.ssp) && ObjectUtils.nullSafeEquals(getFragment(), other.getFragment());
    }

    @Override
    public int hashCode() {
        int result = ObjectUtils.nullSafeHashCode(getScheme());
        result = 31 * result + ObjectUtils.nullSafeHashCode(this.ssp);
        result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());
        return result;
    }
}

See More Examples