package org.gbif.ws.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Request;
import feign.RequestTemplate;
import feign.Util;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.jackson.JacksonEncoder;
import org.apache.commons.lang3.SerializationUtils;
import org.gbif.api.model.registry.PostPersist;
import org.gbif.api.model.registry.PrePersist;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;

public class ClientEncoder implements Encoder {

  private JacksonEncoder jacksonEncoder;

  public ClientEncoder(ObjectMapper objectMapper) {
    this.jacksonEncoder = new JacksonEncoder(objectMapper);
  }

  @Override
  public void encode(Object object, Type bodyType, RequestTemplate template)
      throws EncodeException {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<Object>> violations = new HashSet<>();

    if ("POST".equals(template.method())) {
      violations = validator.validate(object, javax.validation.groups.Default.class, PrePersist.class);
    } else if ("PUT".equals(template.method())) {
      violations = validator.validate(object, javax.validation.groups.Default.class, PostPersist.class);
    }

    if (bodyType == String.class) {
      template.body(object.toString());
    } else if (bodyType == byte[].class) {
      template.body((byte[]) object, null);
    } else {
      if (!violations.isEmpty()) {
        ConstraintViolationException exception = new ConstraintViolationException(violations);
        byte[] data = SerializationUtils.serialize(exception);
        template.header("hasConstraintViolations", String.valueOf(violations.size()));
        template.body(Request.Body.encoded(data, Util.UTF_8));
      } else {
        jacksonEncoder.encode(object, bodyType, template);
      }
    }
  }
}

@@ -654,22 +654,70 @@
 va.util.
-HashSe
+Arrays;%0Aimport java.util.HashSet;%0Aimport java.util.Lis
 t;%0Aimpor
@@ -783,16 +783,165 @@
 oder %7B%0A%0A
+  private static final List%3CString%3E PUT_EXCLUDE_LIST =%0A      Arrays.asList(%22/grscicoll/collection%22, %22/grscicoll/institution%22, %22/grscicoll/person%22);%0A%0A
   privat
@@ -1593,32 +1593,88 @@
 te.method())) %7B%0A
+      if (isMethodNotInExcludeList(template.url())) %7B%0A  
       violations
@@ -1758,24 +1758,96 @@
 ist.class);%0A
+      %7D else %7B%0A        violations = validator.validate(object);%0A      %7D%0A
     %7D%0A%0A    i
@@ -2438,24 +2438,24 @@
 e);%0A      %7D%0A
-
     %7D%0A  %7D%0A%7D%0A
@@ -2451,11 +2451,117 @@
    %7D%0A  %7D
+%0A%0A  private boolean isMethodNotInExcludeList(String url) %7B%0A    return !PUT_EXCLUDE_LIST.contains(url);%0A  %7D
 %0A%7D%0A

Exclude some resources from validation in ClientEncoder