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

com.aeontronix.commons.URLBuilder Maven / Gradle / Ivy

Go to download

Various utility classes. Except for very rare exceptions (annotation-based validation) this will not require any dependencies beyond the JRE

The newest version!
/*
 * Copyright (c) 2014 Kloudtek Ltd
 */

package com.aeontronix.commons;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

import static com.aeontronix.commons.StringUtils.isNotEmpty;

public class URLBuilder {
    private String protocol;
    private String userInfo;
    private final List parameters = new ArrayList();
    private String host;
    private String fragment;
    private int port;
    private StringBuilder path;
    private String ref;

    public URLBuilder(String url) {
        if (url == null) {
            throw new IllegalArgumentException("url mustn't be null");
        }
        URI u = URI.create(url);
        parseUri(u);
    }

    public URLBuilder(URI uri) {
        if (uri == null) {
            throw new IllegalArgumentException("uri mustn't be null");
        }
        parseUri(uri);
    }

    public URLBuilder(URL url) throws URISyntaxException {
        if (url == null) {
            throw new IllegalArgumentException("url mustn't be null");
        }
        parseUri(url.toURI());
    }

    private void parseUri(URI u) {
        protocol = u.getScheme();
        userInfo = u.getUserInfo();
        host = u.getHost();
        port = u.getPort();
        path = new StringBuilder();
        String uPath = u.getPath();
        if (uPath != null) {
            if (!uPath.startsWith("/")) {
                path.append('/');
            }
            this.path.append(uPath);
        }
        if (isNotEmpty(u.getRawQuery())) {
            parseQueryParams(u.getRawQuery());
        }
        ref = u.getFragment();
        if (ref != null) {
            int qidx = ref.indexOf("?");
            if (qidx != -1) {
                parseQueryParams(ref.substring(qidx + 1));
                ref = ref.substring(0, qidx);
            }
        }
    }

    private void parseQueryParams(String query) {
        StringTokenizer tok = new StringTokenizer(query, "&");
        while (tok.hasMoreElements()) {
            String[] kv = tok.nextToken().split("=");
            if (kv.length > 2) {
                throw new IllegalArgumentException("Invalid URL query params: " + Arrays.toString(kv));
            } else if (kv.length == 1) {
                parameters.add(new Param(kv[0], ""));
            } else {
                parameters.add(new Param(kv[0], kv[1]));
            }
        }
    }

    public URLBuilder(String baseUrl, String... path) {
        this(baseUrl);
        for (String p : path) {
            path(p);
        }
    }

    public URLBuilder fragment(String fragment) {
        this.fragment = fragment;
        return this;
    }

    /**
     * Add a single path element which will be encoded before adding to the path
     *
     * @param pathElements Path element
     * @return builder
     */
    public URLBuilder pathEl(String... pathElements) {
        if (pathElements != null) {
            for (String el : pathElements) {
                path(StringUtils.urlPathEncode(el));
            }
        }
        return this;
    }

    /**
     * Add a path to the URL. It will also parse and add any query parameters present.
     *
     * @param path path
     * @return URLBuilder URL Building
     */
    public URLBuilder path(String path) {
        boolean leftHasSlash = this.path.length() > 0 && this.path.charAt(this.path.length() - 1) == '/';
        int qidx = path.indexOf("?");
        if (qidx != -1) {
            parseQueryParams(path.substring(qidx + 1, path.length()));
            path = path.substring(0, qidx);
        }
        boolean rightHasSlash = path.startsWith("/");
        if (!leftHasSlash && !rightHasSlash) {
            this.path.append('/');
        }
        if (leftHasSlash && rightHasSlash) {
            this.path.append(path.substring(1, path.length()));
        } else {
            this.path.append(path);
        }
        return this;
    }

    public URLBuilder queryParam(String key, Object value) {
        queryParam(StringUtils.urlEncode(key), value != null ? value.toString() : null, true, false);
        return this;
    }

    public URLBuilder queryParam(String key, long value) {
        queryParam(StringUtils.urlEncode(key), Long.toString(value), true, false);
        return this;
    }

    public URLBuilder queryParam(String key, int value) {
        queryParam(StringUtils.urlEncode(key), Integer.toString(value), true, false);
        return this;
    }

    public URLBuilder queryParam(String key, byte value) {
        queryParam(StringUtils.urlEncode(key), Byte.toString(value), true, false);
        return this;
    }

    public URLBuilder queryParam(String key, boolean value) {
        queryParam(StringUtils.urlEncode(key), Boolean.toString(value), true, false);
        return this;
    }

    public URLBuilder queryParam(String key, String value, boolean encode, boolean append) {
        final String encodedValue = encode && value != null ? StringUtils.urlEncode(value) : value;
        if (append) {
            if (value != null) {
                parameters.add(new Param(key, encodedValue));
            }
        } else {
            final List list = parameters.stream().filter(param -> param.key.equals(key)).collect(Collectors.toList());
            if (list.isEmpty()) {
                if (value != null) {
                    parameters.add(new Param(key, encodedValue));
                }
            } else {
                final Param param = list.get(list.size() - 1);
                if (value != null) {
                    param.value = encodedValue;
                } else {
                    parameters.remove(param);
                }
            }
        }
        return this;
    }

    public URLBuilder setUserInfo(String userInfo) {
        this.userInfo = StringUtils.urlEncode(userInfo);
        return this;
    }

    public URLBuilder setProtocol(String protocol) {
        this.protocol = protocol;
        return this;
    }

    public URLBuilder setRef(String ref) {
        this.ref = StringUtils.urlEncode(ref);
        return this;
    }

    public URLBuilder setHost(String host) {
        this.host = host;
        return this;
    }

    public URLBuilder setPort(int port) {
        this.port = port;
        return this;
    }

    public URL toURL() {
        try {
            return new URL(toString());
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public URI toURI() {
        return URI.create(toString());
    }

    @Override
    public String toString() {
        StringBuilder url = new StringBuilder();
        if (isNotEmpty(protocol)) {
            url.append(protocol).append("://");
        }
        if (isNotEmpty(userInfo)) {
            url.append(StringUtils.urlEncode(userInfo)).append('@');
        }
        if (isNotEmpty(host)) {
            url.append(host);
        }
        if (port != -1) {
            url.append(':').append(port);
        }
        url.append(path.toString());
        if (ref != null) {
            url.append('#').append(ref);
        }
        if (!parameters.isEmpty()) {
            url.append('?');
            Iterator i = parameters.iterator();
            while (i.hasNext()) {
                Param p = i.next();
                url.append(p.key).append("=").append(p.value);
                if (i.hasNext()) {
                    url.append("&");
                }
            }
        }
        return url.toString();
    }

    public class Param {
        private String key;
        private String value;

        public Param(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy