/*******************************************************************************
* Copyright 2013 Geoscience Australia
*
* 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 au.gov.ga.earthsci.common.util;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* A builder class for creating URI instances.
* <p/>
* Provides support for adding and escaping parameters etc.
*
* @author James Navin (james.navin@ga.gov.au)
*
*/
public class URIBuilder
{
private String scheme;
private String userInfo;
private String host;
private Integer port;
private String path;
private Map<String, String> params = new LinkedHashMap<String, String>(); // Gives predictable parameter order
private String fragment;
/**
* Create a new empty URI builder
*/
public URIBuilder()
{
};
/**
* Create a new URI builder using values from the given URI as a base
*/
public URIBuilder(URI base)
{
if (base == null)
{
return;
}
scheme = base.getScheme();
userInfo = base.getUserInfo();
host = base.getHost();
port = base.getPort() == -1 ? null : base.getPort();
path = base.getPath();
fragment = base.getFragment();
if (Util.isEmpty(base.getQuery()))
{
return;
}
params.putAll(URIUtil.getParameterMap(base));
}
/**
* Set the URI scheme, overriding any existing value.
*/
public URIBuilder setScheme(String scheme)
{
this.scheme = scheme;
return this;
}
/**
* Set the fragment on the URI
*/
public URIBuilder setFragment(String fragment)
{
this.fragment = fragment;
return this;
}
/**
* Set the host on the URI
*/
public URIBuilder setHost(String host)
{
this.host = host;
return this;
}
/**
* Set the path on the URI
*/
public URIBuilder setPath(String path)
{
this.path = path;
return this;
}
/**
* Set the port on this URI
*/
public URIBuilder setPort(int port)
{
this.port = port;
return this;
}
/**
* Set the user info on this URI
*/
public URIBuilder setUserInfo(String userInfo)
{
this.userInfo = userInfo;
return this;
}
/**
* Set a query param on this URI, overriding any existing value.
* <p/>
* The provided value will be encoded as UTF8
*/
public URIBuilder setParam(String key, String value)
{
if (value == null)
{
return setEncodedParam(key, null);
}
return setEncodedParam(key, UTF8URLEncoder.encode(value));
}
/**
* Set an already encoded query param on this URI, overriding any existing
* value.
*/
public URIBuilder setEncodedParam(String key, String encodedValue)
{
this.params.put(key, encodedValue);
return this;
}
private boolean hasAuthority()
{
return !Util.isEmpty(userInfo) || !Util.isEmpty(host);
}
@SuppressWarnings("nls")
/**
* Build and return the URI from the information collected.
*
* @return The URI built from the information collected.
*
* @throws URISyntaxException If the resulting URI is invalid
*/
public URI build() throws URISyntaxException
{
StringBuilder result = new StringBuilder();
result.append(scheme);
result.append(':');
if (hasAuthority())
{
result.append("//");
}
if (!Util.isEmpty(userInfo))
{
result.append(userInfo);
if (!Util.isEmpty(host))
{
result.append('@');
}
}
if (!Util.isEmpty(host))
{
result.append(host);
}
if (port != null)
{
result.append(':').append(port);
}
if (!Util.isEmpty(path))
{
result.append(path);
}
if (!params.isEmpty())
{
result.append('?');
int count = 0;
for (Entry<String, String> param : params.entrySet())
{
if (count > 0)
{
result.append('&');
}
result.append(param.getKey());
if (param.getValue() != null)
{
result.append('=').append(param.getValue());
}
count++;
}
}
if (!Util.isEmpty(fragment))
{
result.append("#").append(fragment);
}
return new URI(result.toString());
}
}