/**
  * Return the Jackson {@link JavaType} for the specified type and context class.
  *
  * <p>The default implementation returns {@code typeFactory.constructType(type, contextClass)},
  * but this can be overridden in subclasses, to allow for custom generic collection handling. For
  * instance:
  *
  * <pre class="code">
  * protected JavaType getJavaType(Type type) {
  *   if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
  *     return TypeFactory.collectionType(ArrayList.class, MyBean.class);
  *   } else {
  *     return super.getJavaType(type);
  *   }
  * }
  * </pre>
  *
  * @param type the generic type to return the Jackson JavaType for
  * @param contextClass a context class for the target type, for example a class in which the
  *     target type appears in a method signature (can be {@code null})
  * @return the Jackson JavaType
  */
 protected JavaType getJavaType(Type type, Class<?> contextClass) {
   TypeFactory typeFactory = this.objectMapper.getTypeFactory();
   if (type instanceof TypeVariable && contextClass != null) {
     ResolvableType resolvedType =
         resolveVariable((TypeVariable<?>) type, ResolvableType.forClass(contextClass));
     if (resolvedType != ResolvableType.NONE) {
       return typeFactory.constructType(resolvedType.resolve());
     }
   }
   return typeFactory.constructType(type);
 }
  /**
   * Invokes all {@link ResourceProcessor} instances registered for the type of the given value and
   * reference type.
   *
   * @param value must not be {@literal null}.
   * @param referenceType must not be {@literal null}.
   * @return
   */
  @SuppressWarnings("unchecked")
  public <T extends ResourceSupport> T invokeProcessorsFor(T value, ResolvableType referenceType) {

    Assert.notNull(value, "Value must not be null!");
    Assert.notNull(referenceType, "Reference type must not be null!");

    // For Resources implementations, process elements first
    if (ResourceProcessorHandlerMethodReturnValueHandler.RESOURCES_TYPE.isAssignableFrom(
        referenceType)) {

      Resources<?> resources = (Resources<?>) value;
      ResolvableType elementTargetType =
          ResolvableType.forClass(Resources.class, referenceType.getRawClass()).getGeneric(0);
      List<Object> result = new ArrayList<Object>(resources.getContent().size());

      for (Object element : resources) {

        ResolvableType elementType = ResolvableType.forClass(element.getClass());

        if (!getRawType(elementTargetType).equals(elementType.getRawClass())) {
          elementTargetType = elementType;
        }

        result.add(invokeProcessorsFor(element, elementTargetType));
      }

      ReflectionUtils.setField(
          ResourceProcessorHandlerMethodReturnValueHandler.CONTENT_FIELD, resources, result);
    }

    return (T) invokeProcessorsFor((Object) value, referenceType);
  }
 @Test
 public void canDecode() {
   assertTrue(
       this.decoder.canDecode(
           ResolvableType.forClass(ByteBuffer.class), MimeTypeUtils.TEXT_PLAIN));
   assertFalse(
       this.decoder.canDecode(ResolvableType.forClass(Integer.class), MimeTypeUtils.TEXT_PLAIN));
   assertTrue(
       this.decoder.canDecode(
           ResolvableType.forClass(ByteBuffer.class), MimeTypeUtils.APPLICATION_JSON));
 }
 @Test
 public void canWrite() {
   assertTrue(
       this.encoder.canEncode(ResolvableType.forClass(String.class), MimeTypeUtils.TEXT_PLAIN));
   assertTrue(
       this.encoder.canEncode(
           ResolvableType.forClass(StringBuilder.class), MimeTypeUtils.TEXT_PLAIN));
   assertTrue(
       this.encoder.canEncode(
           ResolvableType.forClass(StringBuffer.class), MimeTypeUtils.TEXT_PLAIN));
   assertFalse(
       this.encoder.canEncode(ResolvableType.forClass(Integer.class), MimeTypeUtils.TEXT_PLAIN));
   assertFalse(
       this.encoder.canEncode(
           ResolvableType.forClass(String.class), MimeTypeUtils.APPLICATION_JSON));
 }
    /**
     * Creates a new {@link DefaultProcessorWrapper} with the given {@link ResourceProcessor}.
     *
     * @param processor must not be {@literal null}.
     */
    public DefaultProcessorWrapper(ResourceProcessor<?> processor) {

      Assert.notNull(processor);

      this.processor = processor;
      this.targetType =
          ResolvableType.forClass(ResourceProcessor.class, processor.getClass()).getGeneric(0);
    }
 @Test
 public void decode() throws InterruptedException {
   Stream<ByteBuffer> source =
       Streams.just(Buffer.wrap("{\"foo\": \"foofoo\", \"bar\": \"barbar\"}").byteBuffer());
   List<Object> results =
       Streams.wrap(decoder.decode(source, ResolvableType.forClass(Pojo.class), null))
           .toList()
           .await();
   assertEquals(1, results.size());
   assertEquals("foofoo", ((Pojo) results.get(0)).getFoo());
 }
 @SuppressWarnings("unchecked")
 protected H createHealthIndicator(S source) {
   Class<?>[] generics =
       ResolvableType.forClass(CompositeHealthIndicatorConfiguration.class, getClass())
           .resolveGenerics();
   Class<H> indicatorClass = (Class<H>) generics[0];
   Class<S> sourceClass = (Class<S>) generics[1];
   try {
     return indicatorClass.getConstructor(sourceClass).newInstance(source);
   } catch (Exception ex) {
     throw new IllegalStateException(
         "Unable to create indicator " + indicatorClass + " for source " + sourceClass, ex);
   }
 }
    /**
     * Returns whether the given {@link Resource} matches the given target {@link ResolvableType}.
     * We inspect the {@link Resource}'s value to determine the match.
     *
     * @param resource
     * @param target must not be {@literal null}.
     * @return whether the given {@link Resource} can be assigned to the given target {@link
     *     ResolvableType}
     */
    private static boolean isValueTypeMatch(Resource<?> resource, ResolvableType target) {

      if (resource == null || !isRawTypeAssignable(target, resource.getClass())) {
        return false;
      }

      Object content = resource.getContent();

      if (content == null) {
        return false;
      }

      ResolvableType type = findGenericType(target, Resource.class);
      return type != null
          && type.getGeneric(0).isAssignableFrom(ResolvableType.forClass(content.getClass()));
    }
 private List<ResolvableType> resolveDeclaredEventTypes() {
   int count = this.method.getParameterCount();
   if (count > 1) {
     throw new IllegalStateException(
         "Maximum one parameter is allowed for event listener method: " + this.method);
   }
   EventListener ann = getEventListener();
   if (ann != null && ann.classes().length > 0) {
     List<ResolvableType> types = new ArrayList<>();
     for (Class<?> eventType : ann.classes()) {
       types.add(ResolvableType.forClass(eventType));
     }
     return types;
   } else {
     if (count == 0) {
       throw new IllegalStateException(
           "Event parameter is mandatory for event listener method: " + this.method);
     }
     return Collections.singletonList(ResolvableType.forMethodParameter(this.method, 0));
   }
 }
    /**
     * Returns whether the given {@link Resources} instance matches the given {@link
     * ResolvableType}. We predict this by inspecting the first element of the content of the {@link
     * Resources}.
     *
     * @param resources the {@link Resources} to inspect.
     * @param target that target {@link ResolvableType}.
     * @return
     */
    static boolean isValueTypeMatch(Resources<?> resources, ResolvableType target) {

      if (resources == null) {
        return false;
      }

      Collection<?> content = resources.getContent();

      if (content.isEmpty()) {
        return false;
      }

      ResolvableType superType = null;

      for (Class<?> resourcesType :
          Arrays.<Class<?>>asList(resources.getClass(), Resources.class)) {

        superType = ResolvableType.forClass(resourcesType, getRawType(target));

        if (superType != null) {
          break;
        }
      }

      if (superType == null) {
        return false;
      }

      Object element = content.iterator().next();
      ResolvableType resourceType = superType.getGeneric(0);

      if (element instanceof Resource) {
        return ResourceProcessorWrapper.isValueTypeMatch((Resource<?>) element, resourceType);
      } else if (element instanceof EmbeddedWrapper) {
        return isRawTypeAssignable(resourceType, ((EmbeddedWrapper) element).getRelTargetType());
      }

      return false;
    }
  /**
   * Creates a new {@link ResourceProcessorInvoker} to consider the given {@link ResourceProcessor}
   * to post-process the controller methods return value to before invoking the delegate.
   *
   * @param processors the {@link ResourceProcessor}s to be considered, must not be {@literal null}.
   */
  public ResourceProcessorInvoker(Collection<ResourceProcessor<?>> processors) {

    Assert.notNull(processors, "ResourceProcessors must not be null!");

    this.processors = new ArrayList<ProcessorWrapper>();

    for (ResourceProcessor<?> processor : processors) {

      ResolvableType processorType =
          ResolvableType.forClass(ResourceProcessor.class, processor.getClass());
      Class<?> rawType = processorType.getGeneric(0).resolve();

      if (Resource.class.isAssignableFrom(rawType)) {
        this.processors.add(new ResourceProcessorWrapper(processor));
      } else if (Resources.class.isAssignableFrom(rawType)) {
        this.processors.add(new ResourcesProcessorWrapper(processor));
      } else {
        this.processors.add(new DefaultProcessorWrapper(processor));
      }
    }

    Collections.sort(this.processors, AnnotationAwareOrderComparator.INSTANCE);
  }
  /**
   * Invokes all {@link ResourceProcessor} instances registered for the type of the given value.
   *
   * @param value must not be {@literal null}.
   * @return
   */
  public <T extends ResourceSupport> T invokeProcessorsFor(T value) {

    Assert.notNull(value, "Value must not be null!");

    return invokeProcessorsFor(value, ResolvableType.forClass(value.getClass()));
  }
/**
 * Tests for {@link MockDefinition}.
 *
 * @author Phillip Webb
 */
public class MockDefinitionTests {

  private static final ResolvableType EXAMPLE_SERVICE_TYPE =
      ResolvableType.forClass(ExampleService.class);

  @Rule public ExpectedException thrown = ExpectedException.none();

  @Test
  public void classToMockMustNotBeNull() throws Exception {
    this.thrown.expect(IllegalArgumentException.class);
    this.thrown.expectMessage("TypeToMock must not be null");
    new MockDefinition(null, null, null, null, false, null, null);
  }

  @Test
  public void createWithDefaults() throws Exception {
    MockDefinition definition =
        new MockDefinition(null, EXAMPLE_SERVICE_TYPE, null, null, false, null, null);
    assertThat(definition.getName()).isNull();
    assertThat(definition.getTypeToMock()).isEqualTo(EXAMPLE_SERVICE_TYPE);
    assertThat(definition.getExtraInterfaces()).isEmpty();
    assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_DEFAULTS);
    assertThat(definition.isSerializable()).isFalse();
    assertThat(definition.getReset()).isEqualTo(MockReset.AFTER);
    assertThat(definition.getQualifier()).isNull();
  }

  @Test
  public void createExplicit() throws Exception {
    QualifierDefinition qualifier = mock(QualifierDefinition.class);
    MockDefinition definition =
        new MockDefinition(
            "name",
            EXAMPLE_SERVICE_TYPE,
            new Class<?>[] {ExampleExtraInterface.class},
            Answers.RETURNS_SMART_NULLS,
            true,
            MockReset.BEFORE,
            qualifier);
    assertThat(definition.getName()).isEqualTo("name");
    assertThat(definition.getTypeToMock()).isEqualTo(EXAMPLE_SERVICE_TYPE);
    assertThat(definition.getExtraInterfaces()).containsExactly(ExampleExtraInterface.class);
    assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
    assertThat(definition.isSerializable()).isTrue();
    assertThat(definition.getReset()).isEqualTo(MockReset.BEFORE);
    assertThat(definition.isProxyTargetAware()).isFalse();
    assertThat(definition.getQualifier()).isEqualTo(qualifier);
  }

  @Test
  public void createMock() throws Exception {
    MockDefinition definition =
        new MockDefinition(
            "name",
            EXAMPLE_SERVICE_TYPE,
            new Class<?>[] {ExampleExtraInterface.class},
            Answers.RETURNS_SMART_NULLS,
            true,
            MockReset.BEFORE,
            null);
    ExampleService mock = definition.createMock();
    MockCreationSettings<?> settings = SpringBootMockUtil.getMockSettings(mock);
    assertThat(mock).isInstanceOf(ExampleService.class);
    assertThat(mock).isInstanceOf(ExampleExtraInterface.class);
    assertThat(settings.getMockName().toString()).isEqualTo("name");
    assertThat(settings.getDefaultAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS.get());
    assertThat(settings.isSerializable()).isTrue();
    assertThat(MockReset.get(mock)).isEqualTo(MockReset.BEFORE);
  }
}
 @Test
 public void listenerWithSubTypeSeveralGenerics() {
   Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class);
   supportsEventType(true, method, ResolvableType.forClass(PayloadTestEvent.class));
 }
 @Test
 public void
     listenerWithPayloadTypeErasure() { // Always accept such event when the type is unknown
   Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class);
   supportsEventType(true, method, ResolvableType.forClass(PayloadApplicationEvent.class));
 }
 /**
  * Return a {@code BodyExtractor} that reads into a Reactor {@link Flux}.
  *
  * @param elementClass the class of element in the {@code Flux}
  * @param <T> the element type
  * @return a {@code BodyExtractor} that reads a mono
  */
 public static <T> BodyExtractor<Flux<T>> toFlux(Class<? extends T> elementClass) {
   Assert.notNull(elementClass, "'elementClass' must not be null");
   return toFlux(ResolvableType.forClass(elementClass));
 }