001
002package io.vrap.rmf.base.client;
003
004import java.nio.charset.StandardCharsets;
005import java.util.HashMap;
006import java.util.Map;
007import java.util.Optional;
008
009import org.apache.commons.lang3.builder.EqualsBuilder;
010import org.apache.commons.lang3.builder.HashCodeBuilder;
011import org.apache.commons.lang3.builder.ToStringBuilder;
012
013public class ApiHttpResponse<U> extends Base implements ContextAware<ApiHttpResponse<U>> {
014
015    private int statusCode;
016    private ApiHttpHeaders headers;
017    private U body;
018    private String message;
019
020    private Map<Object, Object> contextMap = new HashMap<>();
021
022    public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body) {
023        this(statusCode, headers, body, null);
024    }
025
026    public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body, final String message) {
027        this.statusCode = statusCode;
028        this.headers = Optional.ofNullable(headers).orElse(new ApiHttpHeaders());
029        this.body = body;
030        this.message = message;
031    }
032
033    public ApiHttpResponse(final int statusCode, final ApiHttpHeaders headers, final U body, final String message,
034            final Map<Object, Object> contextMap) {
035        this.statusCode = statusCode;
036        this.headers = Optional.ofNullable(headers).orElse(new ApiHttpHeaders());
037        this.body = body;
038        this.message = message;
039        this.contextMap = contextMap;
040    }
041
042    public ApiHttpResponse(final ApiHttpResponse<U> response) {
043        this.statusCode = response.statusCode;
044        this.headers = response.headers;
045        this.body = response.body;
046        this.message = response.message;
047        this.contextMap = response.contextMap;
048    }
049
050    public Map<Object, Object> getContextMap() {
051        return contextMap;
052    }
053
054    public ApiHttpResponse<U> withContextMap(final Map<Object, Object> contextMap) {
055        ApiHttpResponse<U> response = copy();
056        response.contextMap = new HashMap<>(contextMap);
057
058        return response;
059    }
060
061    @SuppressWarnings("unchecked")
062    public <T> T getContext(Class<T> key) {
063        return (T) contextMap.get(key);
064    }
065
066    public <T> ApiHttpResponse<U> addContext(T value) {
067        ApiHttpResponse<U> response = copy();
068        Map<Object, Object> contextMap = new HashMap<>(response.contextMap);
069        contextMap.put(value.getClass(), value);
070        response.contextMap = contextMap;
071
072        return response;
073    }
074
075    public Object getContext(Object key) {
076        return contextMap.get(key);
077    }
078
079    public ApiHttpResponse<U> addContext(Object key, Object value) {
080        ApiHttpResponse<U> response = copy();
081        Map<Object, Object> contextMap = new HashMap<>(response.contextMap);
082        contextMap.put(key, value);
083        response.contextMap = contextMap;
084
085        return response;
086    }
087
088    public int getStatusCode() {
089        return statusCode;
090    }
091
092    public ApiHttpResponse<U> withStatusCode(final int statusCode) {
093        ApiHttpResponse<U> response = copy();
094        response.statusCode = statusCode;
095
096        return response;
097    }
098
099    public ApiHttpHeaders getHeaders() {
100        return headers;
101    }
102
103    public ApiHttpResponse<U> withHeaders(final ApiHttpHeaders headers) {
104        ApiHttpResponse<U> response = copy();
105        response.headers = headers;
106
107        return response;
108    }
109
110    public U getBody() {
111        return body;
112    }
113
114    public ApiHttpResponse<U> withBody(final U body) {
115        ApiHttpResponse<U> response = copy();
116        response.body = body;
117
118        return response;
119    }
120
121    public String getMessage() {
122        return message;
123    }
124
125    public ApiHttpResponse<U> withMessage(final String message) {
126        ApiHttpResponse<U> response = copy();
127        response.message = message;
128
129        return response;
130    }
131
132    @Override
133    public String toString() {
134        return new ToStringBuilder(this).append("statusCode", statusCode)
135                .append("headers", headers)
136                .append("textInterpretedBody", getSecuredBody())
137                .toString();
138    }
139
140    static String tryToFilter(final String input) {
141        return input.replaceAll("(\"\\w*([Pp]ass|access_token|refresh_token)\\w*\"):\"[^\"]*\"",
142            "$1:\"**removed from output**\"");
143    }
144
145    public Optional<String> getBodyAsString() {
146        if (body instanceof byte[]) {
147            return Optional.of(body).map(b -> tryToFilter(new String((byte[]) b, StandardCharsets.UTF_8)));
148        }
149        else {
150            return Optional.ofNullable(body).map(Object::toString);
151        }
152    }
153
154    public String getSecuredBody() {
155        return getBodyAsString().orElse("empty body");
156    }
157
158    private ApiHttpResponse<U> copy() {
159        return new ApiHttpResponse<>(this);
160    }
161
162    @Override
163    public boolean equals(Object o) {
164        if (this == o)
165            return true;
166
167        if (o == null || getClass() != o.getClass())
168            return false;
169
170        ApiHttpResponse<?> response = (ApiHttpResponse<?>) o;
171
172        return new EqualsBuilder().append(statusCode, response.statusCode)
173                .append(headers, response.headers)
174                .append(body, response.body)
175                .append(message, response.message)
176                .append(contextMap, response.contextMap)
177                .isEquals();
178    }
179
180    @Override
181    public int hashCode() {
182        return new HashCodeBuilder(17, 37).append(statusCode)
183                .append(headers)
184                .append(body)
185                .append(message)
186                .append(contextMap)
187                .toHashCode();
188    }
189}