ProviderMethodResolver.java

  1. /*
  2.  *    Copyright 2009-2021 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.builder.annotation;

  17. import java.lang.reflect.Method;
  18. import java.util.Arrays;
  19. import java.util.List;
  20. import java.util.stream.Collectors;

  21. import org.apache.ibatis.builder.BuilderException;

  22. /**
  23.  * The interface that resolve an SQL provider method via an SQL provider class.
  24.  *
  25.  * <p> This interface need to implements at an SQL provider class and
  26.  * it need to define the default constructor for creating a new instance.
  27.  *
  28.  * @since 3.5.1
  29.  * @author Kazuki Shimizu
  30.  */
  31. public interface ProviderMethodResolver {

  32.   /**
  33.    * Resolve an SQL provider method.
  34.    *
  35.    * <p> The default implementation return a method that matches following conditions.
  36.    * <ul>
  37.    *   <li>Method name matches with mapper method</li>
  38.    *   <li>Return type matches the {@link CharSequence}({@link String}, {@link StringBuilder}, etc...)</li>
  39.    * </ul>
  40.    * If matched method is zero or multiple, it throws a {@link BuilderException}.
  41.    *
  42.    * @param context a context for SQL provider
  43.    * @return an SQL provider method
  44.    * @throws BuilderException Throws when cannot resolve a target method
  45.    */
  46.   default Method resolveMethod(ProviderContext context) {
  47.     List<Method> sameNameMethods = Arrays.stream(getClass().getMethods())
  48.         .filter(m -> m.getName().equals(context.getMapperMethod().getName()))
  49.         .collect(Collectors.toList());
  50.     if (sameNameMethods.isEmpty()) {
  51.       throw new BuilderException("Cannot resolve the provider method because '"
  52.           + context.getMapperMethod().getName() + "' not found in SqlProvider '" + getClass().getName() + "'.");
  53.     }
  54.     List<Method> targetMethods = sameNameMethods.stream()
  55.         .filter(m -> CharSequence.class.isAssignableFrom(m.getReturnType()))
  56.         .collect(Collectors.toList());
  57.     if (targetMethods.size() == 1) {
  58.       return targetMethods.get(0);
  59.     }
  60.     if (targetMethods.isEmpty()) {
  61.       throw new BuilderException("Cannot resolve the provider method because '"
  62.           + context.getMapperMethod().getName() + "' does not return the CharSequence or its subclass in SqlProvider '"
  63.           + getClass().getName() + "'.");
  64.     } else {
  65.       throw new BuilderException("Cannot resolve the provider method because '"
  66.           + context.getMapperMethod().getName() + "' is found multiple in SqlProvider '" + getClass().getName() + "'.");
  67.     }
  68.   }

  69. }