package com.griddynamics.jagger.invoker.v2; import org.apache.commons.lang.StringUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.common.collect.Lists.newArrayList; /** * An object that represents HTTP-request. It consists of {@link JHttpQuery#method}, * {@link JHttpQuery#headers}, {@link JHttpQuery#body} and {@link JHttpQuery#queryParams} fields. * <p> * It contains methods which makes query construction concise and easy to read. * * @param <T> type of the query {@link JHttpQuery#body} * @author Anton Antonenko * Example of query construction: * <pre>{@code * HashMap<String, String> cookies = new HashMap<>(); * cookies.put("JSESSIONID", "0123456789"); * * HttpHeaders headers = new HttpHeaders(); * headers.add("header", "value"); * * JHttpQuery<Integer> httpQuery = new JHttpQuery<Integer>() * .get() * .cookies(cookies) * .cookie("name", "value") * .headers(headers) * .header("header", newArrayList("value1", "value2")) * .queryParam("query param", "value") * .clientParam("client param", new Object()) * .body(42); * }</pre> * @since 2.0 * * @ingroup Main_Http_group */ @SuppressWarnings("unused") public class JHttpQuery<T> implements Serializable { public static final JHttpQuery EMPTY_QUERY = null; private HttpMethod method; private HttpHeaders headers; private T body; private Class responseBodyType; private Map<String, String> queryParams; private String path; /** * Sets parameter {@link HttpMethod method} to {@link JHttpQuery#method} field. <p> * * @param method {@link HttpMethod} to be used in request * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().method(HttpMethod.GET); } */ public JHttpQuery<T> method(HttpMethod method) { this.method = method; return this; } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#GET}. <p> * The same as {@code this.method(HttpMethod.GET); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().get(); } */ public JHttpQuery<T> get() { return method(HttpMethod.GET); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#POST}. <p> * The same as {@code this.method(HttpMethod.POST); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().post(); } */ public JHttpQuery<T> post() { return method(HttpMethod.POST); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#PUT}. <p> * The same as {@code this.method(HttpMethod.PUT); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().put(); } */ public JHttpQuery<T> put() { return method(HttpMethod.PUT); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#PATCH}. <p> * The same as {@code this.method(HttpMethod.PATCH); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().patch(); } */ public JHttpQuery<T> patch() { return method(HttpMethod.PATCH); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#DELETE}. <p> * The same as {@code this.method(HttpMethod.DELETE); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().delete(); } */ public JHttpQuery<T> delete() { return method(HttpMethod.DELETE); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#TRACE}. <p> * The same as {@code this.method(HttpMethod.TRACE); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().trace(); } */ public JHttpQuery<T> trace() { return method(HttpMethod.TRACE); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#HEAD}. <p> * The same as {@code this.method(HttpMethod.HEAD); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().head(); } */ public JHttpQuery<T> head() { return method(HttpMethod.HEAD); } /** * Sets {@link JHttpQuery#method} to {@link HttpMethod#OPTIONS}. <p> * The same as {@code this.method(HttpMethod.OPTIONS); } * * @return this * Usage: <p> * {@code JHttpQuery httpQuery = new JHttpQuery().options(); } */ public JHttpQuery<T> options() { return method(HttpMethod.OPTIONS); } /** * Sets parameter {@link HttpHeaders headers} to {@link JHttpQuery#headers} field. * * @param headers headers to be added to query * @return this * Usage: * <pre>{@code * HttpHeaders headers = new HttpHeaders(); * headers.add("header", "value") * * JHttpQuery httpQuery = new JHttpQuery().headers(headers); * }</pre> */ public JHttpQuery<T> headers(HttpHeaders headers) { this.headers = headers; return this; } /** * Sets parameter {@link Map headers} to {@link JHttpQuery#headers} field. * * @param headers headers to be added to query * @return this * Usage: * <pre>{@code * Map<String, List<String>> headers = new HashMap<>(); * headers.put("header", newArrayList("value1", "value2")); * * JHttpQuery httpQuery = new JHttpQuery().headers(headers); * }</pre> */ public JHttpQuery<T> headers(Map<String, List<String>> headers) { initHeadersIfNull(); this.headers.putAll(headers); return this; } /** * Adds header "key=values" to {@link JHttpQuery#headers}. * * @param key name of header * @param values values of header * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().header("header", newArrayList("value1", "value2")); * }</pre> */ public JHttpQuery<T> header(String key, List<String> values) { initHeadersIfNull(); headers.put(key, values); return this; } /** * Adds header "key=value" to {@link JHttpQuery#headers}. * * @param key name of header * @param value value of header * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().header("header", "value"); * }</pre> */ public JHttpQuery<T> header(String key, String value) { initHeadersIfNull(); headers.put(key, newArrayList(value)); return this; } /** * Adds {@link Map cookies} to {@link JHttpQuery#headers} field. * * @param cookies cookies to be added to query * @return this * Usage: * <pre>{@code * HashMap<String, String> cookies = new HashMap<>(); * cookies.put("JSESSIONID", "0123456789"); * * JHttpQuery httpQuery = new JHttpQuery().cookies(cookies)); * }</pre> */ public JHttpQuery<T> cookies(Map<String, String> cookies) { initHeadersIfNull(); cookies.entrySet().forEach(entry -> this.headers.add("Cookie", entry.getKey() + "=" + entry.getValue())); return this; } /** * Adds Cookie header "name=value" to {@link JHttpQuery#headers} field. * * @param name name of cookie * @param value value of cookie * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().cookie("name", "value"); * }</pre> */ public JHttpQuery<T> cookie(String name, String value) { initHeadersIfNull(); this.headers.add("Cookie", name + "=" + value); return this; } /** * Sets parameter {@link T body} to {@link JHttpQuery#body} field. * * @param body {@link T body} of the query * @return this * Usage: * <pre>{@code * JHttpQuery<Integer> httpQuery = new JHttpQuery<Integer>().body(42); * // or * JHttpQuery<Object> httpQuery = new JHttpQuery<Object>().body(new Object()); * // or * JHttpQuery<String> httpQuery = new JHttpQuery<String>().body("42"); * }</pre> */ public JHttpQuery<T> body(T body) { this.body = body; return this; } /** * Sets parameter {@link Class responseBodyType} to {@link JHttpQuery#responseBodyType} field. * * @param responseBodyType expected body type of response * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().responseBodyType(Integer.class); * }</pre> */ public JHttpQuery<T> responseBodyType(Class responseBodyType) { this.responseBodyType = responseBodyType; return this; } /** * Sets parameter {@link Map queryParams} to {@link JHttpQuery#queryParams} field. * * @param queryParams {@link Map} with query parameters to be added to query * @return this * Usage: * <pre>{@code * Map<String, String> queryParams = new HashMap<>(); * queryParams.put("page", "1"); * queryParams.put("sort", "asc"); * * JHttpQuery httpQuery = new JHttpQuery().queryParams(queryParams); * }</pre> */ public JHttpQuery<T> queryParams(Map<String, String> queryParams) { this.queryParams = queryParams; return this; } /** * Adds query parameter "paramName=paramValue" to {@link JHttpQuery#queryParams} field. * * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().queryParam("parameter","value"); * }</pre> */ public JHttpQuery<T> queryParam(String paramName, String paramValue) { if (queryParams == null) this.queryParams = new HashMap<>(); this.queryParams.put(paramName, paramValue); return this; } /** * Sets path to {@link JHttpQuery#path} field. * * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().path("/products"); * }</pre> */ public JHttpQuery<T> path(String path) { this.path = StringUtils.startsWith(path, "/") ? path : "/" + path; return this; } /** * Concatenates paths values and sets to {@link JHttpQuery#path} field. * * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().path("categories", "clothes", "jeans", "42"); * }</pre> */ public JHttpQuery<T> path(String... paths) { String path = StringUtils.join(paths, "/"); return path(path); } /** * Sets path of query to {@link JHttpQuery#path} field. Works the same as {@link String#format(String, Object...)}}. * * @return this * Usage: * <pre>{@code * JHttpQuery httpQuery = new JHttpQuery().path("/products/%s/%s", "categories", 42); * }</pre> * @see String#format(String, Object...) */ public JHttpQuery<T> path(String formatString, Object... args) { String path = String.format(formatString, args); return path(path); } public HttpMethod getMethod() { return method; } public T getBody() { return body; } public Class getResponseBodyType() { return responseBodyType; } public HttpHeaders getHeaders() { return headers; } public Map<String, String> getQueryParams() { return queryParams; } public String getPath() { return path; } private void initHeadersIfNull() { if (this.headers == null) this.headers = new HttpHeaders(); } public static JHttpQuery copyOf(JHttpQuery jHttpQuery) { if (jHttpQuery == null) return null; JHttpQuery copy = new JHttpQuery() .body(jHttpQuery.getBody()) .queryParams(jHttpQuery.getQueryParams()) .path(jHttpQuery.getPath()) .responseBodyType(jHttpQuery.getResponseBodyType()) .headers(jHttpQuery.getHeaders()); switch (jHttpQuery.getMethod()) { case DELETE: copy.delete(); break; case GET: copy.get(); break; case HEAD: copy.head(); break; case OPTIONS: copy.options(); break; case PATCH: copy.patch(); break; case POST: copy.post(); break; case PUT: copy.put(); break; case TRACE: copy.trace(); break; } return copy; } @Override public String toString() { return "JHttpQuery{" + "method=" + method + ", headers=" + headers + ", body=" + body + ", responseBodyType=" + responseBodyType + ", queryParams=" + queryParams + ", path='" + path + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; JHttpQuery<?> httpQuery = (JHttpQuery<?>) o; if (method != httpQuery.method) return false; if (headers != null ? !headers.equals(httpQuery.headers) : httpQuery.headers != null) return false; if (body != null ? !body.equals(httpQuery.body) : httpQuery.body != null) return false; if (responseBodyType != null ? !responseBodyType.equals(httpQuery.responseBodyType) : httpQuery.responseBodyType != null) return false; if (queryParams != null ? !queryParams.equals(httpQuery.queryParams) : httpQuery.queryParams != null) return false; return path != null ? path.equals(httpQuery.path) : httpQuery.path == null; } @Override public int hashCode() { int result = method.hashCode(); result = 31 * result + (headers != null ? headers.hashCode() : 0); result = 31 * result + (body != null ? body.hashCode() : 0); result = 31 * result + (responseBodyType != null ? responseBodyType.hashCode() : 0); result = 31 * result + (queryParams != null ? queryParams.hashCode() : 0); result = 31 * result + (path != null ? path.hashCode() : 0); return result; } }