org.turbogwt.net.client.UriBuilderImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.turbogwt.net.client.UriBuilderImpl.java

Source

/*
 * Copyright 2014 Grow Bit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.turbogwt.net.client;

import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.http.client.URL;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.turbogwt.core.collections.client.LightMap;
import org.turbogwt.net.shared.MultivaluedParamComposition;
import org.turbogwt.net.shared.Uri;
import org.turbogwt.net.shared.UriBuilder;
import org.turbogwt.net.shared.UriBuilderException;

/**
 * Default implementation of {@link org.turbogwt.net.shared.UriBuilder}.
 *
 * @author Danilo Reinert
 */
public class UriBuilderImpl extends UriBuilder {

    private MultivaluedParamComposition strategy = MultivaluedParamComposition.REPEATED_PARAM;
    private String scheme;
    private String user;
    private String password;
    private String host;
    private Integer port;
    private JsArrayString segments;
    private String fragment;
    private Map<String, Object[]> queryParams;
    private Map<String, Map<String, Object[]>> matrixParams;

    @Override
    public UriBuilder multivaluedParamComposition(MultivaluedParamComposition strategy)
            throws IllegalArgumentException {
        assertNotNull(strategy, "MultivaluedParamComposition strategy cannot be null.");
        this.strategy = strategy;
        return this;
    }

    @Override
    public UriBuilder scheme(String scheme) throws IllegalArgumentException {
        // TODO: check scheme validity
        this.scheme = scheme;
        return this;
    }

    @Override
    public UriBuilder user(String user) {
        if (user == null) {
            this.user = null;
            this.password = null;
        } else {
            this.user = user;
        }
        return this;
    }

    @Override
    public UriBuilder password(String password) {
        this.password = password;
        return this;
    }

    @Override
    public UriBuilder host(String host) throws IllegalArgumentException {
        // TODO: check host validity
        this.host = host;
        return this;
    }

    @Override
    public UriBuilder port(int port) throws IllegalArgumentException {
        if (port > -1) {
            this.port = port;
        } else {
            this.port = null;
        }
        return this;
    }

    @Override
    public UriBuilder path(String path) {
        assertNotNull(path, "Path cannot be null.");
        if (!path.isEmpty()) {
            String[] splittedSegments = path.split("/");
            ensureSegments();
            for (String segment : splittedSegments) {
                if (!segment.isEmpty())
                    this.segments.push(segment);
            }
        }
        return this;
    }

    @Override
    public UriBuilder segment(Object... segments) throws IllegalArgumentException {
        assertNotNull(segments, "Segments cannot be null.");
        ensureSegments();
        for (Object o : segments) {
            String segment = o.toString();
            assertNotNullOrEmpty(segment, "Segment cannot be null or empty.", false);
            this.segments.push(segment);
        }
        return this;
    }

    @Override
    public UriBuilder matrixParam(String name, Object... values) throws IllegalArgumentException {
        assertNotNullOrEmpty(name, "Parameter name cannot be null or empty.", false);
        assertNotNull(values, "Parameter values cannot be null.");

        if (matrixParams == null) {
            matrixParams = GWT.create(LightMap.class);
        }

        // TODO: validate this assertion
        assertNotNull(segments, "There is no segment added to the URI. "
                + "There must be at least one segment added in order to bind matrix parameters");

        String segment = segments.get(segments.length() - 1);

        Map<String, Object[]> segmentParams = matrixParams.get(segment);
        if (segmentParams == null) {
            segmentParams = GWT.create(LightMap.class);
            matrixParams.put(segment, segmentParams);
        }
        // TODO: instead of setting the array, incrementally add to an existing one?
        segmentParams.put(name, values);

        return this;
    }

    @Override
    public UriBuilder queryParam(String name, Object... values) throws IllegalArgumentException {
        assertNotNull(name, "Parameter name cannot be null.");
        assertNotNull(values, "Parameter values cannot be null.");
        if (queryParams == null)
            queryParams = GWT.create(LightMap.class);
        queryParams.put(name, values);
        return this;
    }

    @Override
    public UriBuilder fragment(String fragment) {
        this.fragment = fragment;
        return this;
    }

    @Override
    public Uri build(Object... values) {
        final String encScheme = encodePart(scheme);
        final String encUser = encodePart(user);
        final String encPassword = encodePart(password);
        final String encHost = encodePart(host);

        List<String> templateParams = new ArrayList<>();

        StringBuilder pathBuilder = new StringBuilder();
        if (segments != null) {
            for (int i = 0; i < segments.length(); i++) {
                final String segment = segments.get(i);
                final String parsed = parsePart(values, templateParams, segment);
                pathBuilder.append(URL.encodePathSegment(parsed));

                // Check if there are matrix params for this segment
                if (matrixParams != null) {
                    Map<String, Object[]> segmentParams = matrixParams.get(segment);
                    if (segmentParams != null) {
                        pathBuilder.append(";");
                        Set<String> params = segmentParams.keySet();
                        for (String param : params) {
                            pathBuilder.append(strategy.asUriPart(";", param, segmentParams.get(param)))
                                    .append(';');
                        }
                        pathBuilder.deleteCharAt(pathBuilder.length() - 1);
                    }
                }
                pathBuilder.append('/');
            }
            pathBuilder.deleteCharAt(pathBuilder.length() - 1);
        }
        final String encPath = pathBuilder.toString();

        StringBuilder queryBuilder = null;
        if (queryParams != null) {
            queryBuilder = new StringBuilder();
            Set<String> params = queryParams.keySet();
            for (String param : params) {
                queryBuilder.append(strategy.asUriPart("&", param, queryParams.get(param))).append('&');
            }
            queryBuilder.deleteCharAt(queryBuilder.length() - 1);
        }
        final String encQuery = queryBuilder != null ? queryBuilder.toString() : null;

        final String encFragment = fragment != null ? encodePart(parsePart(values, templateParams, fragment))
                : null;

        return new Uri(encScheme, encUser, encPassword, encHost, port, encPath, encQuery, encFragment);
    }

    private String encodePart(String segment) {
        return segment != null ? URL.encodePathSegment(segment) : null;
    }

    private String parsePart(Object[] values, List<String> templateParams, String segment) {
        int cursor = segment.indexOf("{");
        while (cursor > -1) {
            int closingBracket = segment.indexOf("}", cursor);
            if (closingBracket > -1) {
                final String param = segment.substring(cursor + 1, closingBracket);
                int i = templateParams.indexOf(param);
                if (i == -1) {
                    // Check if has more template values
                    if (values.length < templateParams.size() + 1)
                        throw new UriBuilderException(
                                "The supplied values are not enough to replace the existing " + "template params");
                    // Add template param
                    i = templateParams.size();
                    templateParams.add(param);
                }
                final String value = values[i].toString();
                segment = segment.substring(0, cursor) + value + segment.substring(closingBracket + 1);
                cursor = segment.indexOf("{", closingBracket + 1);
            } else {
                cursor = -1;
            }
        }
        return segment;
    }

    /**
     * Assert that the value is not null.
     *
     * @param value   the value
     * @param message the message to include with any exceptions
     *
     * @throws IllegalArgumentException if value is null
     */
    private void assertNotNull(Object value, String message) throws IllegalArgumentException {
        if (value == null) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Assert that the value is not null or empty.
     *
     * @param value   the value
     * @param message the message to include with any exceptions
     * @param isState if true, throw a state exception instead
     *
     * @throws IllegalArgumentException if value is null
     * @throws IllegalStateException    if value is null and isState is true
     */
    private void assertNotNullOrEmpty(String value, String message, boolean isState)
            throws IllegalArgumentException {
        if (value == null || value.length() == 0) {
            if (isState) {
                throw new IllegalStateException(message);
            } else {
                throw new IllegalArgumentException(message);
            }
        }
    }

    private void ensureSegments() {
        if (this.segments == null)
            this.segments = (JsArrayString) JsArrayString.createArray();
    }
}