/**
* Copyright (C) 2011 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2.0 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.web.toolkit.client.common;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.http.client.URL;
/**
* Build a URL from a set of parameters.
*
* @author Séverin Moussel
*/
public class UrlBuilder {
private final HashMap<String, Object> parameters = new HashMap<String, Object>();
private String rootUrl = null;
private String anchor = null;
public UrlBuilder() {
}
public UrlBuilder(final String rootUrl) {
this.rootUrl = rootUrl;
}
public void setRootUrl(final String rootUrl) {
this.rootUrl = rootUrl;
}
protected String encode(String decodedURL) {
return URL.encode(decodedURL);
}
/**
* Build the URL and return it as an encoded string.
*/
@SuppressWarnings("unchecked")
private void buildParameters(final StringBuilder sb, final HashMap<String, Object> parameters, final String parentName) {
final java.util.Iterator<String> i = parameters.keySet().iterator();
char prefix = '&';
while (i.hasNext()) {
String name = i.next();
final Object value = parameters.get(name);
if (parentName != null) {
name = parentName + "[" + name + "]";
}
if (value instanceof String || value instanceof Character || value instanceof Number || value instanceof Boolean) {
sb.append(prefix).append(name).append('=');
sb.append(encode(String.valueOf(value)));
} else if (value instanceof Map) {
this.buildParameters(sb, (HashMap<String, Object>) value, name);
} else if (value instanceof List) {
this.buildParameters(sb, (List<Object>) value, name);
} else if (value == null) {
sb.append(prefix).append(name).append('=');
} else {
throw new IllegalArgumentException();
}
prefix = '&';
}
}
/**
* Build the URL and return it as an encoded string.
*/
@SuppressWarnings("unchecked")
private void buildParameters(final StringBuilder sb, final List<Object> parameters, String parentName) {
final Iterator<Object> i = parameters.iterator();
parentName = parentName + "[]";
while (i.hasNext()) {
final Object value = i.next();
if (value == null) {
sb.append('&').append(parentName).append('=');
} else if (value instanceof String) {
sb.append('&').append(parentName).append('=').append(encode((String) value));
} else if (value instanceof Map) {
this.buildParameters(sb, (HashMap<String, Object>) value, parentName);
} else if (value instanceof List) {
this.buildParameters(sb, (HashMap<String, Object>) value, parentName);
} else {
throw new IllegalArgumentException();
}
}
}
@Override
public String toString() {
final StringBuilder url = new StringBuilder();
this.buildParameters(url, this.parameters, null);
if (this.anchor != null) {
if (!this.anchor.startsWith("#")) {
url.append("#");
}
url.append(this.anchor);
}
return this.rootUrl + url.toString().replaceAll("^&", "?").replaceAll("\\[\\]=", "=").replaceAll("((\\[(.*?)\\])+?)=", "=$3%3d");
}
/**
* Remove a query parameter from the map.
*
* @param name
* the parameter name
*/
public UrlBuilder removeParameter(final String name) {
this.parameters.remove(name);
return this;
}
/**
* Set the anchor portion of the location (ex. myAnchor or #myAnchor).
*
* @param anchor
* the anchor
*/
public UrlBuilder setAnchor(final String anchor) {
this.anchor = anchor;
return this;
}
public UrlBuilder addParameter(final String key, final Object... values) {
if (values.length == 1) {
this.parameters.put(key, values[0]);
} else {
this.parameters.put(key, values);
}
return this;
}
public UrlBuilder addParameter(final String key, final HashMap<String, Object> values) {
this.parameters.put(key, values);
return this;
}
}