View Javadoc

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              // when there we found one and only one function!
63              return Iterables.getLast(matchingFunctions.values()).apply(response);
64          }
65      }
66  
67      static interface StatusRange {
68          boolean isIn(int code);
69      }
70  }