package nl.knaw.huygens.alexandria.client;
import java.time.Duration;
import java.time.Instant;
/*
* #%L
* alexandria-java-client
* =======
* Copyright (C) 2015 - 2017 Huygens ING (KNAW)
* =======
* 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 3 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/gpl-3.0.html>.
* #L%
*/
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
public class RestRequester<T> {
private int retries = 5;
private Supplier<Response> responseSupplier;
Map<Status, Function<Response, RestResult<T>>> statusMappers = new HashMap<>();
private Function<Response, RestResult<T>> defaultMapper = RestResult::failingResult;
public static <T> RestRequester<T> withResponseSupplier(Supplier<Response> responseSupplier) {
RestRequester<T> requester = new RestRequester<>();
requester.responseSupplier = responseSupplier;
return requester;
}
public RestRequester<T> onStatus(Status status, Function<Response, RestResult<T>> mapper) {
statusMappers.put(status, mapper);
return this;
}
public RestRequester<T> onOtherStatus(Function<Response, RestResult<T>> defaultMapper) {
this.defaultMapper = defaultMapper;
return this;
}
public RestResult<T> getResult() {
int attempt = 0;
Response response = null;
Instant start = Instant.now();
while (response == null && attempt < retries) {
attempt++;
try {
response = responseSupplier.get();
} catch (ProcessingException pe) {
pe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
return timed(RestResult.failingResult(e), start);
}
}
if (response == null) {
return timed(RestResult.failingResult("No response from server after " + retries + " attempts."), start);
}
Status status = Status.fromStatusCode(response.getStatus());
if (statusMappers.containsKey(status)) {
RestResult<T> timed = timed(statusMappers.get(status).apply(response), start);
timed.setResponse(response);
return timed;
} else {
RestResult<T> timed = timed(defaultMapper.apply(response), start);
timed.setResponse(response);
return timed;
}
}
private RestResult<T> timed(RestResult<T> restResult, Instant start) {
return restResult.setTurnaroundTime(timeSince(start));
}
private Duration timeSince(Instant start) {
return Duration.between(start, Instant.now());
}
public void setRetries(int retries) {
this.retries = retries;
}
}