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

main.java.com.cloudant.client.internal.URIBaseMethods Maven / Gradle / Ivy

There is a newer version: 2.20.1
Show newest version
package com.cloudant.client.internal;

import com.cloudant.client.org.lightcouch.Params;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

/**
 * Provides methods using fluent style setters to build a Cloudant account or database URI.
 * The use of generics provides the subclasses a way to re-use common URI methods with
 * different types. Current types are {@link DatabaseURIHelper} for creating a URI to
 * interact with a Cloudant database, and {@link URIBase} for interacting with a
 * Cloudant account.
 */
abstract class URIBaseMethods {

    private static final String _design_prefix_encoded = "_design%2F";
    private static final String _local_prefix_encoded = "_local%2F";
    /* key=value params */
    Params qParams = new Params();
    String completeQuery = "";
    String path = "";
    URI baseUri;

    public abstract T returnThis();

    /**
     * Sets a path(s) for the URI.
     * Note: File separator is handled in this method
     * and should not be passed as parameter.
     *
     * @return The updated {@link T} object.
     */
    public T path(String path) {
        if (path.length() == 0) {
            this.path += encodePath(path);
        } else {
            this.path += "/" + encodePath(path);
        }
        return returnThis();
    }

    /**
     * Add the given {@code name} and {@code value} to the query parameters.
     *
     * @param name    The name of the parameter to add/replace.
     * @param value   The value of the parameter.
     * @return The updated {@link T} object.
     */
    public T query(String name, Object value) {
        this.query(name, value, true);
        return returnThis();
    }

    /**
     * Add the given {@code name} and {@code value} to the query parameters or replace
     * the existing query parameter matching {@code name} with one with the new {@code value}.
     *
     * @param name    The name of the parameter to add/replace.
     * @param value   The value of the parameter.
     * @param replace set to true to replace the value of an existing query parameter matching
     *                {@code name}, or false to add a new one. Note that if this is true and there
     *                is no parameter matching {@code name}, the parameter will be added.
     * @return The updated {@link T} object.
     */
    public T query(String name, Object value, boolean replace) {
        if (name != null && value != null) {
            if (replace) {
                this.qParams.replaceOrAdd(name, value.toString());
            } else {
                this.qParams.addParam(name, value.toString());
            }
        }
        return returnThis();
    }

    /**
     * Return the Cloudant account URI.
     * @return account URI
     */
    public URI getUri() {
        return baseUri;
    }

    /**
     * Encode a path in a manner suitable for a GET request
     * @param in The path to encode, eg "a/document"
     * @return The encoded path eg "a%2Fdocument"
     */
    String encodePath(String in) {
        try {
            String encodedString = HierarchicalUriComponents.encodeUriComponent(in, "UTF-8",
                    HierarchicalUriComponents.Type.PATH_SEGMENT);
            if (encodedString.startsWith(_design_prefix_encoded) ||
                    encodedString.startsWith(_local_prefix_encoded)) {
                // we replaced the first slash in the design or local doc URL, which we shouldn't
                // so let's put it back
                return encodedString.replaceFirst("%2F", "/");
            } else {
                return encodedString;
            }
        } catch (UnsupportedEncodingException uee) {
            // This should never happen as every implementation of the java platform is required
            // to support UTF-8.
            throw new RuntimeException(
                    "Couldn't encode ID " + in,
                    uee);
        }
    }

    /**
     * Build and return the complete URI containing values
     * such as the document ID, attachment ID, and query syntax.
     */
    public URI build() {
        try {
            String uriString = String.format("%s%s", baseUri.toASCIIString(),
                    (path.isEmpty() ? "" : path));
            if(qParams != null && qParams.size() > 0) {
                //Add queries together if both exist
                if(!completeQuery.isEmpty()) {
                    uriString = String.format("%s?%s&%s", uriString,
                            getJoinedQuery(qParams.getParams()),
                            completeQuery);
                } else {
                    uriString = String.format("%s?%s", uriString,
                            getJoinedQuery(qParams.getParams()));
                }
            } else if(!completeQuery.isEmpty()) {
                uriString = String.format("%s?%s", uriString, completeQuery);
            }

            return new URI(uriString);
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private String getJoinedQuery(List parts) {
        StringBuilder queryBuilder = new StringBuilder();
        for(String query : parts) {
            if(query != null && !query.isEmpty()) {
                queryBuilder.append(query);
                queryBuilder.append("&");
            }
        }
        //Remove final `&`
        queryBuilder.deleteCharAt(queryBuilder.length() - 1);
        return queryBuilder.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy