1 package com.atlassian.httpclient.api;
2
3 import com.google.common.base.Function;
4 import com.google.common.base.Predicate;
5 import com.google.common.collect.ImmutableMap;
6 import com.google.common.collect.Iterables;
7 import com.google.common.collect.Maps;
8
9 import java.util.Map;
10
11 final class ResponsePromiseMapFunction<O> implements Function<Response, O> {
12 private final ImmutableMap<StatusRange, Function<Response, ? extends O>> functions;
13 private Function<Response, ? extends O> othersFunction;
14
15 private ResponsePromiseMapFunction(ImmutableMap<StatusRange, Function<Response, ? extends O>> functions,
16 Function<Response, ? extends O> othersFunction) {
17 this.functions = functions;
18 this.othersFunction = othersFunction;
19 }
20
21 public static <T> ResponsePromiseMapFunctionBuilder<T> builder() {
22 return new ResponsePromiseMapFunctionBuilder<T>();
23 }
24
25 public static final class ResponsePromiseMapFunctionBuilder<T> implements Buildable<ResponsePromiseMapFunction<T>> {
26 private Map<StatusRange, Function<Response, ? extends T>> functionMap = Maps.newHashMap();
27 private Function<Response, ? extends T> othersFunction;
28
29 public void addStatusRangeFunction(StatusRange range, Function<Response, ? extends T> func) {
30 functionMap.put(range, func);
31 }
32
33 public void setOthersFunction(Function<Response, ? extends T> othersFunction) {
34 this.othersFunction = othersFunction;
35 }
36
37 @Override
38 public ResponsePromiseMapFunction<T> build() {
39 return new ResponsePromiseMapFunction<T>(ImmutableMap.copyOf(functionMap), othersFunction);
40 }
41 }
42
43 @Override
44 public O apply(Response response) {
45 final int statusCode = response.getStatusCode();
46 final Map<StatusRange, Function<Response, ? extends O>> matchingFunctions = Maps.filterKeys(functions, new Predicate<StatusRange>() {
47 @Override
48 public boolean apply(StatusRange input) {
49 return input.isIn(statusCode);
50 }
51 });
52
53 if (matchingFunctions.isEmpty()) {
54 if (othersFunction != null) {
55 return othersFunction.apply(response);
56 } else {
57 throw new IllegalStateException("Could not match any function to status " + statusCode);
58 }
59 } else if (matchingFunctions.size() > 1) {
60 throw new IllegalStateException("Found multiple functions for status " + statusCode);
61 } else {
62
63 return Iterables.getLast(matchingFunctions.values()).apply(response);
64 }
65 }
66
67 static interface StatusRange {
68 boolean isIn(int code);
69 }
70 }