FormDataInserter.java
package org.bremersee.apiclient.webflux.contract.spring;
import static java.util.Objects.nonNull;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.function.Function;
import org.bremersee.apiclient.webflux.Invocation;
import org.bremersee.apiclient.webflux.InvocationParameter;
import org.springframework.core.ResolvableType;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient.RequestBodyUriSpec;
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec;
/**
* The form data inserter.
*
* @author Christian Bremer
*/
public class FormDataInserter extends SingleBodyInserter<MultiValueMap<String, ?>> {
private Function<Invocation, Optional<MediaType>> contentTypeResolver = new ContentTypeResolver();
/**
* With content type resolver.
*
* @param contentTypeResolver the content type resolver
* @return the form data inserter
*/
public FormDataInserter withContentTypeResolver(
Function<Invocation, Optional<MediaType>> contentTypeResolver) {
if (nonNull(contentTypeResolver)) {
this.contentTypeResolver = contentTypeResolver;
}
return this;
}
@Override
public boolean canInsert(Invocation invocation) {
return isFormData(invocation) && super.canInsert(invocation);
}
/**
* Is form data.
*
* @param invocation the invocation
* @return the boolean
*/
protected boolean isFormData(Invocation invocation) {
return contentTypeResolver.apply(invocation)
.filter(contentType -> contentType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED))
.isPresent();
}
@Override
protected MultiValueMap<String, ?> mapBody(InvocationParameter invocationParameter) {
//noinspection unchecked
return (MultiValueMap<String, ?>) invocationParameter.getValue();
}
@Override
protected boolean isPossibleBodyValue(InvocationParameter invocationParameter) {
return invocationParameter.getValue() instanceof MultiValueMap && isString(invocationParameter);
}
private boolean isString(InvocationParameter invocationParameter) {
Method method = invocationParameter.getMethod();
int index = invocationParameter.getIndex();
return Optional.of(ResolvableType.forMethodParameter(method, index))
.filter(resolvableType -> resolvableType.getGenerics().length >= 2)
.map(resolvableType -> resolvableType.resolveGeneric(0))
.filter(String.class::isAssignableFrom)
.isPresent();
}
@Override
protected RequestHeadersUriSpec<?> insert(
MultiValueMap<String, ?> body,
RequestBodyUriSpec requestBodyUriSpec) {
//noinspection rawtypes,unchecked
return (RequestHeadersUriSpec) requestBodyUriSpec
.body(BodyInserters.fromFormData((MultiValueMap<String, String>) body));
}
}