/* * Copyright 2008-2015 the original author or 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 org.springframework.data.repository.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import org.springframework.data.repository.Repository; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** * Utility class to work with classes. * * @author Oliver Gierke */ public abstract class ClassUtils { /** * Private constructor to prevent instantiation. */ private ClassUtils() {} /** * Returns whether the given class contains a property with the given name. * * @param type * @param property * @return */ public static boolean hasProperty(Class<?> type, String property) { if (null != ReflectionUtils.findMethod(type, "get" + property)) { return true; } return null != ReflectionUtils.findField(type, StringUtils.uncapitalize(property)); } /** * Returns wthere the given type is the {@link Repository} interface. * * @param interfaze * @return */ public static boolean isGenericRepositoryInterface(Class<?> interfaze) { return Repository.class.equals(interfaze); } /** * Returns whether the given type name is a repository interface name. * * @param interfaceName * @return */ public static boolean isGenericRepositoryInterface(String interfaceName) { return Repository.class.getName().equals(interfaceName); } /** * Returns the number of occurences of the given type in the given {@link Method}s parameters. * * @param method * @param type * @return */ public static int getNumberOfOccurences(Method method, Class<?> type) { int result = 0; for (Class<?> clazz : method.getParameterTypes()) { if (type.equals(clazz)) { result++; } } return result; } /** * Asserts the given {@link Method}'s return type to be one of the given types. Will unwrap known wrapper types before * the assignment check (see {@link QueryExecutionConverters}). * * @param method must not be {@literal null}. * @param types must not be {@literal null} or empty. */ public static void assertReturnTypeAssignable(Method method, Class<?>... types) { Assert.notNull(method, "Method must not be null!"); Assert.notEmpty(types, "Types must not be null or empty!"); TypeInformation<?> returnType = getEffectivelyReturnedTypeFrom(method); Arrays.stream(types)// .filter(it -> it.isAssignableFrom(returnType.getType()))// .findAny().orElseThrow(() -> new IllegalStateException( "Method has to have one of the following return types! " + Arrays.toString(types))); } /** * Returns whether the given object is of one of the given types. Will return {@literal false} for {@literal null}. * * @param object * @param types * @return */ public static boolean isOfType(Object object, Collection<Class<?>> types) { if (null == object) { return false; } return types.stream().anyMatch(it -> it.isAssignableFrom(object.getClass())); } /** * Returns whether the given {@link Method} has a parameter of the given type. * * @param method * @param type * @return */ public static boolean hasParameterOfType(Method method, Class<?> type) { return Arrays.asList(method.getParameterTypes()).contains(type); } /** * Helper method to extract the original exception that can possibly occur during a reflection call. * * @param ex * @throws Throwable */ public static void unwrapReflectionException(Exception ex) throws Throwable { if (ex instanceof InvocationTargetException) { throw ((InvocationTargetException) ex).getTargetException(); } throw ex; } private static TypeInformation<?> getEffectivelyReturnedTypeFrom(Method method) { TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method); return QueryExecutionConverters.supports(returnType.getType()) ? returnType.getRequiredComponentType() : returnType; } }