package org.gbif.ws.client;

import feign.Response;
import feign.codec.ErrorDecoder;
import org.gbif.api.exception.ServiceUnavailableException;
import org.gbif.ws.NotFoundException;
import org.springframework.security.access.AccessDeniedException;

import javax.validation.ValidationException;
import java.net.URI;

public class ClientErrorDecoder implements ErrorDecoder {

  @Override
  public Exception decode(String methodKey, Response response) {
    switch (response.status()) {
      case 400:
        return new IllegalArgumentException("A bad request received");
      case 401:
        return new AccessDeniedException("Unauthorized request received");
      case 403:
        return new AccessDeniedException("Forbidden request received");
      case 404:
        return new NotFoundException("Resource not found", URI.create(response.request().url()));
      case 422:
        return new ValidationException();
      case 500:
        return new ServiceUnavailableException("An internal server error occurred, please try again later");
      case 501:
        return new UnsupportedOperationException("Method not implement yet");
      default:
        return new RuntimeException("Unexpected exception");
    }
  }
}

@@ -22,16 +22,57 @@
 lient;%0A%0A
+import com.google.common.io.CharStreams;%0A
 import f
@@ -208,32 +208,89 @@
 FoundException;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 import org.sprin
@@ -401,153 +401,676 @@
 ava.
-net.URI;%0A%0Apublic class ClientErrorDecoder implements ErrorDecoder %7B%0A%0A  @Override%0A  public Exception decode(String methodKey, Response response) %7B
+io.IOException;%0Aimport java.io.Reader;%0Aimport java.net.URI;%0A%0A@SuppressWarnings(%22UnstableApiUsage%22)%0Apublic class ClientErrorDecoder implements ErrorDecoder %7B%0A%0A  private static final Logger LOG = LoggerFactory.getLogger(ClientErrorDecoder.class);%0A%0A  @Override%0A  public Exception decode(String methodKey, Response response) %7B%0A    String message = null;%0A%0A    try (Reader reader = response.body().asReader()) %7B%0A      //Easy way to read the stream and get a String object%0A      message = CharStreams.toString(reader);%0A      LOG.error(%22Client exception: %7B%7D%22, message);%0A    %7D catch (IOException e) %7B%0A      LOG.error(%22Exception during reading client error response%22, e);%0A    %7D%0A
 %0A   
@@ -1505,24 +1505,132 @@
       return
+ message != null%0A            ? new ValidationException(extractValidationErrorMessage(message))%0A            :
  new Validat
@@ -1835,16 +1835,44 @@
 ception(
+message != null ? message : 
 %22Method 
@@ -1943,16 +1943,44 @@
 ception(
+message != null ? message : 
 %22Unexpec
@@ -2005,11 +2005,196 @@
    %7D%0A  %7D
+%0A%0A  private String extractValidationErrorMessage(String message) %7B%0A    return message.replace(%22%3Cul%3E%3Cli%3E%22, %22%22)%0A        .replace(%22%3C/li%3E%3C/ul%3E%22, %22%22)%0A        .replace(%22%3Cli%3E%3C/li%3E%22, %22, %22);%0A  %7D
 %0A%7D%0A

Improve ClientErrorDecoder