ProviderMethodResolver.java

  1. /*
  2.  *    Copyright 2009-2024 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.  *       https://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.  * <p>
  25.  * This interface need to implements at an SQL provider class and it need to define the default constructor for creating
  26.  * a new instance.
  27.  *
  28.  * @since 3.5.1
  29.  *
  30.  * @author Kazuki Shimizu
  31.  */
  32. public interface ProviderMethodResolver {

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

  70. }