All Downloads are FREE. Search and download functionalities are using the official Maven repository.

feign.MethodMetadata 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 java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;
import feign.Param.Expander;

public final class MethodMetadata implements Serializable {

  private static final long serialVersionUID = 1L;
  private String configKey;
  private transient Type returnType;
  private Integer urlIndex;
  private Integer bodyIndex;
  private Integer headerMapIndex;
  private Integer queryMapIndex;
  private QueryMapEncoder queryMapEncoder;
  private boolean alwaysEncodeBody;
  private transient Type bodyType;
  private final RequestTemplate template = new RequestTemplate();
  private final List formParams = new ArrayList();
  private final Map> indexToName =
      new LinkedHashMap>();
  private final Map> indexToExpanderClass =
      new LinkedHashMap>();
  private final Map indexToEncoded = new LinkedHashMap();
  private transient Map indexToExpander;
  private BitSet parameterToIgnore = new BitSet();
  private boolean ignored;
  private transient Class targetType;
  private transient Method method;
  private transient final List warnings = new ArrayList<>();

  MethodMetadata() {
    template.methodMetadata(this);
  }

  /**
   * Used as a reference to this method. For example, {@link Logger#log(String, String, Object...)
   * logging} or {@link ReflectiveFeign reflective dispatch}.
   *
   * @see Feign#configKey(Class, java.lang.reflect.Method)
   */
  public String configKey() {
    return configKey;
  }

  public MethodMetadata configKey(String configKey) {
    this.configKey = configKey;
    return this;
  }

  public Type returnType() {
    return returnType;
  }

  public MethodMetadata returnType(Type returnType) {
    this.returnType = returnType;
    return this;
  }

  public Integer urlIndex() {
    return urlIndex;
  }

  public MethodMetadata urlIndex(Integer urlIndex) {
    this.urlIndex = urlIndex;
    return this;
  }

  public Integer bodyIndex() {
    return bodyIndex;
  }

  public MethodMetadata bodyIndex(Integer bodyIndex) {
    this.bodyIndex = bodyIndex;
    return this;
  }

  public Integer headerMapIndex() {
    return headerMapIndex;
  }

  public MethodMetadata headerMapIndex(Integer headerMapIndex) {
    this.headerMapIndex = headerMapIndex;
    return this;
  }

  public Integer queryMapIndex() {
    return queryMapIndex;
  }

  public MethodMetadata queryMapIndex(Integer queryMapIndex) {
    this.queryMapIndex = queryMapIndex;
    return this;
  }

  public QueryMapEncoder queryMapEncoder() {
    return queryMapEncoder;
  }

  public MethodMetadata queryMapEncoder(QueryMapEncoder queryMapEncoder) {
    this.queryMapEncoder = queryMapEncoder;
    return this;
  }

  @Experimental
  public boolean alwaysEncodeBody() {
    return alwaysEncodeBody;
  }

  @Experimental
  MethodMetadata alwaysEncodeBody(boolean alwaysEncodeBody) {
    this.alwaysEncodeBody = alwaysEncodeBody;
    return this;
  }

  /**
   * Type corresponding to {@link #bodyIndex()}.
   */
  public Type bodyType() {
    return bodyType;
  }

  public MethodMetadata bodyType(Type bodyType) {
    this.bodyType = bodyType;
    return this;
  }

  public RequestTemplate template() {
    return template;
  }

  public List formParams() {
    return formParams;
  }

  public Map> indexToName() {
    return indexToName;
  }

  public Map indexToEncoded() {
    return indexToEncoded;
  }

  /**
   * If {@link #indexToExpander} is null, classes here will be instantiated by newInstance.
   */
  public Map> indexToExpanderClass() {
    return indexToExpanderClass;
  }

  /**
   * After {@link #indexToExpanderClass} is populated, this is set by contracts that support runtime
   * injection.
   */
  public MethodMetadata indexToExpander(Map indexToExpander) {
    this.indexToExpander = indexToExpander;
    return this;
  }

  /**
   * When not null, this value will be used instead of {@link #indexToExpander()}.
   */
  public Map indexToExpander() {
    return indexToExpander;
  }

  /**
   * @param i individual parameter that should be ignored
   * @return this instance
   */
  public MethodMetadata ignoreParamater(int i) {
    this.parameterToIgnore.set(i);
    return this;
  }

  public BitSet parameterToIgnore() {
    return parameterToIgnore;
  }

  public MethodMetadata parameterToIgnore(BitSet parameterToIgnore) {
    this.parameterToIgnore = parameterToIgnore;
    return this;
  }

  /**
   * @param i individual parameter to check if should be ignored
   * @return true when field should not be processed by feign
   */
  public boolean shouldIgnoreParamater(int i) {
    return parameterToIgnore.get(i);
  }

  /**
   * @param index
   * @return true if the parameter {@code index} was already consumed by a any
   *         {@link MethodMetadata} holder
   */
  public boolean isAlreadyProcessed(Integer index) {
    return index.equals(urlIndex)
        || index.equals(bodyIndex)
        || index.equals(headerMapIndex)
        || index.equals(queryMapIndex)
        || indexToName.containsKey(index)
        || indexToExpanderClass.containsKey(index)
        || indexToEncoded.containsKey(index)
        || (indexToExpander != null && indexToExpander.containsKey(index))
        || parameterToIgnore.get(index);
  }

  public void ignoreMethod() {
    this.ignored = true;
  }

  public boolean isIgnored() {
    return ignored;
  }

  @Experimental
  public MethodMetadata targetType(Class targetType) {
    this.targetType = targetType;
    return this;
  }

  @Experimental
  public Class targetType() {
    return targetType;
  }

  @Experimental
  public MethodMetadata method(Method method) {
    this.method = method;
    return this;
  }

  @Experimental
  public Method method() {
    return method;
  }

  public void addWarning(String warning) {
    warnings.add(warning);
  }

  public String warnings() {
    return warnings.stream()
        .collect(Collectors.joining("\n- ", "\nWarnings:\n- ", ""));
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy