
feign.RequestTemplateFactoryResolver Maven / Gradle / Ivy
/*
* Copyright 2012-2023 The Feign Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package feign;
import static feign.Util.checkArgument;
import static feign.Util.checkNotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.template.UriUtils;
final class RequestTemplateFactoryResolver {
private final Encoder encoder;
private final QueryMapEncoder queryMapEncoder;
RequestTemplateFactoryResolver(
Encoder encoder,
QueryMapEncoder queryMapEncoder) {
this.encoder = checkNotNull(encoder, "encoder");
this.queryMapEncoder = checkNotNull(queryMapEncoder, "queryMapEncoder");
}
public RequestTemplate.Factory resolve(Target> target, MethodMetadata md) {
if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
return new BuildFormEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else if (md.bodyIndex() != null || md.alwaysEncodeBody()) {
return new BuildEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
} else {
return new BuildTemplateByResolvingArgs(md, queryMapEncoder, target);
}
}
private static class BuildTemplateByResolvingArgs implements RequestTemplate.Factory {
private final QueryMapEncoder queryMapEncoder;
protected final MethodMetadata metadata;
protected final Target> target;
private final Map indexToExpander =
new LinkedHashMap();
private BuildTemplateByResolvingArgs(MethodMetadata metadata, QueryMapEncoder queryMapEncoder,
Target target) {
this.metadata = metadata;
this.target = target;
this.queryMapEncoder = queryMapEncoder;
if (metadata.indexToExpander() != null) {
indexToExpander.putAll(metadata.indexToExpander());
return;
}
if (metadata.indexToExpanderClass().isEmpty()) {
return;
}
for (Map.Entry> indexToExpanderClass : metadata
.indexToExpanderClass().entrySet()) {
try {
indexToExpander
.put(indexToExpanderClass.getKey(), indexToExpanderClass.getValue().newInstance());
} catch (InstantiationException e) {
throw new IllegalStateException(e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
@Override
public RequestTemplate create(Object[] argv) {
RequestTemplate mutable = RequestTemplate.from(metadata.template());
mutable.feignTarget(target);
if (metadata.urlIndex() != null) {
int urlIndex = metadata.urlIndex();
checkArgument(argv[urlIndex] != null, "URI parameter %s was null", urlIndex);
mutable.target(String.valueOf(argv[urlIndex]));
}
Map varBuilder = new LinkedHashMap();
for (Map.Entry> entry : metadata.indexToName().entrySet()) {
int i = entry.getKey();
Object value = argv[entry.getKey()];
if (value != null) { // Null values are skipped.
if (indexToExpander.containsKey(i)) {
value = expandElements(indexToExpander.get(i), value);
}
for (String name : entry.getValue()) {
varBuilder.put(name, value);
}
}
}
RequestTemplate template = resolve(argv, mutable, varBuilder);
if (metadata.queryMapIndex() != null) {
// add query map parameters after initial resolve so that they take
// precedence over any predefined values
Object value = argv[metadata.queryMapIndex()];
Map queryMap = toQueryMap(value, metadata.queryMapEncoder());
template = addQueryMapQueryParameters(queryMap, template);
}
if (metadata.headerMapIndex() != null) {
// add header map parameters for a resolution of the user pojo object
Object value = argv[metadata.headerMapIndex()];
Map headerMap = toQueryMap(value, metadata.queryMapEncoder());
template = addHeaderMapHeaders(headerMap, template);
}
return template;
}
private Map toQueryMap(Object value, QueryMapEncoder queryMapEncoder) {
if (value instanceof Map) {
return (Map) value;
}
try {
// encode with @QueryMap annotation if exists otherwise with the one from this resolver
return queryMapEncoder != null ? queryMapEncoder.encode(value)
: this.queryMapEncoder.encode(value);
} catch (EncodeException e) {
throw new IllegalStateException(e);
}
}
private Object expandElements(Param.Expander expander, Object value) {
if (value instanceof Iterable) {
return expandIterable(expander, (Iterable) value);
}
return expander.expand(value);
}
private List expandIterable(Param.Expander expander, Iterable value) {
List values = new ArrayList();
for (Object element : value) {
if (element != null) {
values.add(expander.expand(element));
}
}
return values;
}
@SuppressWarnings("unchecked")
private RequestTemplate addHeaderMapHeaders(Map headerMap,
RequestTemplate mutable) {
for (Map.Entry currEntry : headerMap.entrySet()) {
Collection values = new ArrayList();
Object currValue = currEntry.getValue();
if (currValue instanceof Iterable>) {
Iterator> iter = ((Iterable>) currValue).iterator();
while (iter.hasNext()) {
Object nextObject = iter.next();
values.add(nextObject == null ? null : nextObject.toString());
}
} else {
values.add(currValue == null ? null : currValue.toString());
}
mutable.header(currEntry.getKey(), values);
}
return mutable;
}
@SuppressWarnings("unchecked")
private RequestTemplate addQueryMapQueryParameters(Map queryMap,
RequestTemplate mutable) {
for (Map.Entry currEntry : queryMap.entrySet()) {
Collection values = new ArrayList();
Object currValue = currEntry.getValue();
if (currValue instanceof Iterable>) {
Iterator> iter = ((Iterable>) currValue).iterator();
while (iter.hasNext()) {
Object nextObject = iter.next();
values.add(nextObject == null ? null : UriUtils.encode(nextObject.toString()));
}
} else if (currValue instanceof Object[]) {
for (Object value : (Object[]) currValue) {
values.add(value == null ? null : UriUtils.encode(value.toString()));
}
} else {
if (currValue != null) {
values.add(UriUtils.encode(currValue.toString()));
}
}
if (values.size() > 0) {
mutable.query(UriUtils.encode(currEntry.getKey()), values);
}
}
return mutable;
}
protected RequestTemplate resolve(Object[] argv,
RequestTemplate mutable,
Map variables) {
return mutable.resolve(variables);
}
}
private static class BuildFormEncodedTemplateFromArgs extends BuildTemplateByResolvingArgs {
private final Encoder encoder;
private BuildFormEncodedTemplateFromArgs(MethodMetadata metadata, Encoder encoder,
QueryMapEncoder queryMapEncoder, Target target) {
super(metadata, queryMapEncoder, target);
this.encoder = encoder;
}
@Override
protected RequestTemplate resolve(Object[] argv,
RequestTemplate mutable,
Map variables) {
Map formVariables = new LinkedHashMap();
for (Map.Entry entry : variables.entrySet()) {
if (metadata.formParams().contains(entry.getKey())) {
formVariables.put(entry.getKey(), entry.getValue());
}
}
try {
encoder.encode(formVariables, Encoder.MAP_STRING_WILDCARD, mutable);
} catch (EncodeException e) {
throw e;
} catch (RuntimeException e) {
throw new EncodeException(e.getMessage(), e);
}
return super.resolve(argv, mutable, variables);
}
}
private static class BuildEncodedTemplateFromArgs extends BuildTemplateByResolvingArgs {
private final Encoder encoder;
private BuildEncodedTemplateFromArgs(MethodMetadata metadata, Encoder encoder,
QueryMapEncoder queryMapEncoder, Target target) {
super(metadata, queryMapEncoder, target);
this.encoder = encoder;
}
@Override
protected RequestTemplate resolve(Object[] argv,
RequestTemplate mutable,
Map variables) {
boolean alwaysEncodeBody = mutable.methodMetadata().alwaysEncodeBody();
Object body = null;
if (!alwaysEncodeBody) {
body = argv[metadata.bodyIndex()];
checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex());
}
try {
if (alwaysEncodeBody) {
body = argv == null ? new Object[0] : argv;
encoder.encode(body, Object[].class, mutable);
} else {
encoder.encode(body, metadata.bodyType(), mutable);
}
} catch (EncodeException e) {
throw e;
} catch (RuntimeException e) {
throw new EncodeException(e.getMessage(), e);
}
return super.resolve(argv, mutable, variables);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy