import org.apache.log4j.Logger;
import org.primefaces.extensions.converter.JsonConverter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;/*** Builder for request parameters.*/
public class RequestParameterBuilder {private Logger LOG = Logger.getLogger(RequestParameterBuilder.class);private StringBuilder buffer;private String originalUrl;private JsonConverter jsonConverter;private String encoding;private boolean added;/*** Creates a builder instance by the current request URL.*/public RequestParameterBuilder() {this(((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURL().toString());}/*** Creates a builder instance by the given URL.** @param url URL*/public RequestParameterBuilder(String url) {buffer = new StringBuilder(url);originalUrl = url;jsonConverter = new JsonConverter();encoding = FacesContext.getCurrentInstance().getExternalContext().getRequestCharacterEncoding();if (encoding == null) {encoding = 'UTF-8';}}/*** Adds a request parameter to the URL without specifying a data type of the given parameter value.* Parameter's value is converted to JSON notation when adding. Furthermore, it will be encoded* according to the acquired encoding.** @param name name of the request parameter* @param value value of the request parameter* @return RequestParameterBuilder updated this instance which can be reused*/public RequestParameterBuilder paramJson(String name, Object value) throws UnsupportedEncodingException {return paramJson(name, value, null);}/*** Adds a request parameter to the URL with specifying a data type of the given parameter value. Data type is sometimes* required, especially for Java generic types, because type information is erased at runtime and the conversion to JSON* will not work properly. Parameter's value is converted to JSON notation when adding. Furthermore, it will be encoded* according to the acquired encoding.** @param name name of the request parameter* @param value value of the request parameter* @param type data type of the value object. Any primitive type, array, non generic or generic type is supported.* Data type is sometimes required to convert a value to a JSON representation. All data types should be* fully qualified.* @return RequestParameterBuilder updated this instance which can be reused*/public RequestParameterBuilder paramJson(String name, Object value, String type)throws UnsupportedEncodingException {jsonConverter.setType(type);String jsonValue;if (value == null) {jsonValue = 'null';} else {jsonValue = jsonConverter.getAsString(null, null, value);}if (added || originalUrl.contains('?')) {buffer.append('&');} else {buffer.append('?');}buffer.append(name);buffer.append('=');buffer.append(URLEncoder.encode(jsonValue, encoding));// set a flag that at least one request parameter was addedadded = true;return this;}/*** Adds a request parameter to the URL. This is a convenient method for primitive, plain data types.* Parameter's value will not be converted to JSON notation when adding. It will be only encoded* according to the acquired encoding. Note: null values will not be added.** @param name name of the request parameter* @param value value of the request parameter* @return RequestParameterBuilder updated this instance which can be reused*/public RequestParameterBuilder param(String name, Object value) throws UnsupportedEncodingException {if (value == null) {return this;}if (added || originalUrl.contains('?')) {buffer.append('&');} else {buffer.append('?');}buffer.append(name);buffer.append('=');buffer.append(URLEncoder.encode(value.toString(), encoding));// set a flag that at least one request parameter was addedadded = true;return this;}/*** Builds the end result.** @return String end result*/public String build() {String url = buffer.toString();if (url.length() > 2083) {LOG.error('URL ' + url + ' is longer than 2083 chars (' + buffer.length() +'). It may not work properly in old IE versions.');}return url;}/*** Resets the internal state in order to be reused.** @return RequestParameterBuilder reseted builder*/public RequestParameterBuilder reset() {buffer = new StringBuilder(originalUrl);jsonConverter.setType(null);added = false;return this;}
}