/* * Copyright 2012 uaiHebert Solucoes em Informatica * * 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 com.uaihebert.util; import com.uaihebert.model.EntityPathHelper; import javax.persistence.Embeddable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; public final class ReflectionUtil { private static final int LAST_CLASS_OF_PATH = 2; private static final List<Class> ALLOWED_BAG_TYPES = new ArrayList<Class>(); static { ALLOWED_BAG_TYPES.add(Set.class); ALLOWED_BAG_TYPES.add(List.class); ALLOWED_BAG_TYPES.add(Collection.class); } private ReflectionUtil() { } private static String getAttributeType(final Class<?> entityClass, final String attributeName) { return getAttributeType(entityClass, attributeName, false); } private static String getAttributeType(final Class<?> entityClass, final String attributeName, final boolean silently) { validateData(entityClass, attributeName); Field currentField = null; final String[] pathArray = EntityPathHelper.extractPaths(attributeName); Class<?> currentClass = entityClass; for (int i = 0; i < pathArray.length; i++) { final Field foundField = getField(currentClass, pathArray[i], silently); final int fieldPosition = i + 1; if (fieldPosition < pathArray.length) { currentClass = foundField.getType(); if (currentClass.equals(List.class) || currentClass.equals(Set.class) || currentClass.equals(Collection.class)) { currentClass = extractBagType(foundField); } } else { currentField = foundField; } } if (currentField != null) { return currentField.getType().getCanonicalName(); } return null; } private static Class extractBagType(final Field foundField) { final Class currentClass; final Type genericType = foundField.getGenericType(); final ParameterizedType aType = (ParameterizedType) genericType; final Type[] fieldArgTypes = aType.getActualTypeArguments(); currentClass = (Class) fieldArgTypes[0]; return currentClass; } private static void validateData(final Class<?> entityClass, final String attributeName) { if (entityClass == null) { throw new IllegalArgumentException("entityClass parameter cannot be null"); } if (attributeName == null || attributeName.isEmpty()) { throw new IllegalArgumentException("attributeName parameter cannot be null"); } } private static List<Field> getAllFields(final List<Field> fields, final Class<?> type) { Collections.addAll(fields, type.getDeclaredFields()); if (type.getSuperclass() != null) { fields.addAll(getAllFields(fields, type.getSuperclass())); } return fields; } private static Field getField(final Class<?> entityClass, final String attributeName, final boolean silently) { final List<Field> fields = new ArrayList<Field>(); getAllFields(fields, entityClass); final String internedName = attributeName.intern(); for (final Field field : fields) { if (internedName.equals(field.getName())) { return field; } } if (silently) { return null; } throw new IllegalArgumentException("We could not find the parameter: " + attributeName + " in the given class: " + entityClass); } public static boolean isDouble(final Class<?> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("double"); } public static <T> boolean isFloat(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("float"); } public static <T> boolean isLong(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("long"); } private static <T> boolean isInteger(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("integer") || "int".equalsIgnoreCase(attributeType); } public static <T> boolean isString(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("string"); } public static <T> boolean isDate(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("util.date"); } public static <T> boolean isCalendar(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("calendar"); } private static boolean isBagType(final Class<?> entityClass) { return ALLOWED_BAG_TYPES.contains(entityClass); } public static <T> boolean isList(final Class<T> entityClass, final String collectionName) { final String attributeType = getAttributeType(entityClass, collectionName); return attributeType.toLowerCase().contains("list"); } public static <T> boolean isList(final Class<T> entityClass, final String collectionName, final boolean silently) { final String attributeType = getAttributeType(entityClass, collectionName, silently); return attributeType != null && attributeType.toLowerCase().contains("list"); } public static <T> boolean isSet(final Class<T> entityClass, final String collectionName) { final String attributeType = getAttributeType(entityClass, collectionName); return attributeType.toLowerCase().contains("set"); } public static <T> boolean isSet(final Class<T> entityClass, final String collectionName, final boolean silently) { final String attributeType = getAttributeType(entityClass, collectionName, silently); return attributeType != null && attributeType.toLowerCase().contains("set"); } public static <T> boolean isMap(final Class<T> entityClass, final String collectionName) { final String attributeType = getAttributeType(entityClass, collectionName); return attributeType.toLowerCase().contains("map"); } public static <T> boolean isMap(final Class<T> entityClass, final String collectionName, final boolean silently) { final String attributeType = getAttributeType(entityClass, collectionName, silently); return attributeType != null && attributeType.toLowerCase().contains("map"); } public static <T> boolean isCollection(final Class<T> entityClass, final String collectionName) { final String attributeType = getAttributeType(entityClass, collectionName); return attributeType.toLowerCase().contains("collection"); } public static <T> boolean isCollection(final Class<T> entityClass, final String collectionName, final boolean silently) { final String attributeType = getAttributeType(entityClass, collectionName, silently); return attributeType != null && attributeType.toLowerCase().contains("collection"); } public static <T> boolean isBigDecimal(final Class<T> entityClass, final String attributeName) { final String attributeType = getAttributeType(entityClass, attributeName); return attributeType.toLowerCase().contains("bigdecimal"); } public static boolean isEmbeddedId(final String path, final Class<?> entityClass) { final String[] paths = EntityPathHelper.extractPaths(path); final Class<?> attributeClass = getClassOfTheLastAttribute(paths, entityClass); final Annotation[] declaredAnnotations = attributeClass.getDeclaredAnnotations(); for (final Annotation annotation : declaredAnnotations) { if (annotation instanceof Embeddable) { return true; } } return false; } public static Class getClassOfTheLastAttribute(final String[] fullPath, final Class<?> entityClass) { final String currentPosition = fullPath[0]; final Field attributeField = getField(entityClass, currentPosition, false); final Class attributeClass = extractClassFromField(attributeField); if (fullPath.length > LAST_CLASS_OF_PATH) { final String constructedPath = EntityPathHelper.constructPathFromArray(1, fullPath.length, fullPath); return getClassOfTheLastAttribute(EntityPathHelper.extractPaths(constructedPath), attributeClass); } return attributeClass; } private static Class extractClassFromField(final Field attributeField) { if (ReflectionUtil.isBagType(attributeField.getType())) { final ParameterizedType collectionType = (ParameterizedType) attributeField.getGenericType(); return (Class) collectionType.getActualTypeArguments()[0]; } return attributeField.getType(); } public static boolean isSupportedCollection(final Class entityClass, final String collectionName, final boolean silently) { return isCollection(entityClass, collectionName, silently) || isSet(entityClass, collectionName, silently) || isList(entityClass, collectionName, silently) || isMap(entityClass, collectionName, silently); } public static boolean isNumber(final Class entityClass, final String attributeName) { return isDecimalType(entityClass, attributeName) || isLong(entityClass, attributeName) || isInteger(entityClass, attributeName); } private static boolean isDecimalType(final Class entityClass, final String attributeName) { return isBigDecimal(entityClass, attributeName) || isDouble(entityClass, attributeName) || isFloat(entityClass, attributeName); } }