
org.sparta.springwebutils.util.ExternalEntryPointHelper Maven / Gradle / Ivy
package org.sparta.springwebutils.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sparta.springwebutils.annotation.ExternalEntryPoint;
import org.sparta.springwebutils.entity.EntryPointParameter;
/**
* @author Carlos Eduardo Endler Genz – Sparta Java Team
*
* History:
* Mar 5, 2014 - Carlos Eduardo Endler Genz
* Mar 14, 2014 - Daniel Conde Diehl - Not ignoring list on object scan
*
*/
public final class ExternalEntryPointHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(ExternalEntryPointHelper.class);
/**
* Returns whether the supplied method is an Entry Point or not.
* It might be annotated by @ExternalEntryPoint
*
* @param method Method to be scanned
* @param scanEntryPointAnnotation Does it has annotation
* @return boolean
*/
public static boolean isAnEntryPoint(Method method, boolean scanEntryPointAnnotation) {
return !scanEntryPointAnnotation
|| scanEntryPointAnnotation && method.isAnnotationPresent(ExternalEntryPoint.class)
|| scanEntryPointAnnotation && method.getDeclaringClass().isAnnotationPresent(ExternalEntryPoint.class);
}
/**
* Deeply finds all the attributes of the supplied class
*
* @param parameterType Type of parameter
* @param typeBlacklist blackList by type
* @param nameBlacklist blackList by name
* @param maxDeepLevel How deep should algorithm go in the object
* @return List
*/
public static List getInternalEntryPointParametersRecursively(Class> parameterType, Set> typeBlacklist, Set nameBlacklist, int maxDeepLevel) {
return getInternalEntryPointParametersRecursively(parameterType, typeBlacklist, nameBlacklist, null, 1, maxDeepLevel);
}
/**
* Deeply finds all the attributes of the supplied class
*
* @param parameterType Type of parameter
* @param typeBlacklist blackList by type
* @param nameBlacklist blackList by name
* @param parent parent
* @param level what the level of immersion now
* @param maxDeepLevel How deep should algorithm go in the object
* @return List
*/
private static List getInternalEntryPointParametersRecursively(Class> parameterType, Set> typeBlacklist, Set nameBlacklist, Field parent, int level, int maxDeepLevel) {
final List list = new ArrayList();
for (Field field : parameterType.getDeclaredFields()) {
field.setAccessible(true);
if (typeBlacklist.contains(field.getType()) || nameBlacklist.contains(field.getName())) {
continue;
}
if (isSimpleRequestParameter(field.getType())) {
final EntryPointParameter param = new EntryPointParameter();
param.setName(parent != null ? parent.getName() + "." + field.getName() : field.getName());
param.setType(field.getType());
list.add(param);
} else if (shouldWeGoDeep(field.getType()) && level < maxDeepLevel) {
// Object arrays are not supported and lists are not supported
list.addAll(getInternalEntryPointParametersRecursively(field.getType(), typeBlacklist, nameBlacklist, field, ++level, maxDeepLevel));
} else {
LOGGER.warn("We might have reached a cycle, ignoring parameter {}", field.getName());
}
}
return list;
}
/**
* Decide whether to go deep or not base on type
*
* @param type parameter type for the decision
* @return boolean
*/
private static boolean shouldWeGoDeep(Class> type) {
return !type.isArray()
&& !ClassUtils.isAssignable(type, Collection.class);
}
/**
* Finds out if the supplied type is a simple element (primitive/wrapper, an primitive/wrapper array or a Collection instance)
*
* @param parameterType type to check
* @return boolean
*/
public static boolean isSimpleRequestParameter(Class> parameterType) {
return ClassUtils.isPrimitiveOrWrapper(parameterType)
|| (parameterType.isArray() && ClassUtils.isPrimitiveOrWrapper(parameterType.getComponentType()))
|| (ClassUtils.isAssignable(parameterType, Collection.class))
|| ClassUtils.isAssignable(parameterType, String.class)
|| ClassUtils.isAssignable(parameterType, String[].class);
}
/**
* Based on the input for scanning annotations, look for @ExternalEntryPoint and get the decorated name from it, if any.
*
* @param method method to check
* @param scanEntryPointAnnotation annotation
* @return String
*/
public static String getEntryPointDecoratedName(Method method, boolean scanEntryPointAnnotation) {
String decoratedName = method.getName();
if (scanEntryPointAnnotation) {
// we look at the method level
if (method.isAnnotationPresent(ExternalEntryPoint.class)) {
final ExternalEntryPoint externalEntryPoint = method.getAnnotation(ExternalEntryPoint.class);
if (StringUtils.isNotBlank(externalEntryPoint.name())) {
decoratedName = externalEntryPoint.name();
}
}
}
return decoratedName;
}
/**
* Based on the input for scanning annotations, look for @ExternalEntryPoint and get the specific type black list elements.
*
* @param predefinedTypeBlacklist black list
* @param method method to check
* @param scanEntryPointAnnotation annotation
* @return Set
*/
public static Set> getConsolidatedTypeBlacklist(List> predefinedTypeBlacklist, Method method, boolean scanEntryPointAnnotation) {
final Set> consolidatedBlacklist = new HashSet>(predefinedTypeBlacklist);
if (scanEntryPointAnnotation) {
// first we look into the class level
if (method.getDeclaringClass().isAnnotationPresent(ExternalEntryPoint.class)) {
final ExternalEntryPoint externalEntryPoint = method.getDeclaringClass().getAnnotation(ExternalEntryPoint.class);
if (externalEntryPoint.typeBlacklist() != null) {
consolidatedBlacklist.addAll(Arrays.asList(externalEntryPoint.typeBlacklist()));
}
}
// then we look at the method level
if (method.isAnnotationPresent(ExternalEntryPoint.class)) {
final ExternalEntryPoint externalEntryPoint = method.getAnnotation(ExternalEntryPoint.class);
if (externalEntryPoint.typeBlacklist() != null) {
consolidatedBlacklist.addAll(Arrays.asList(externalEntryPoint.typeBlacklist()));
}
}
}
return consolidatedBlacklist;
}
/**
* Based on the input for scanning annotations, look for @ExternalEntryPoint and get the specific name black list elements.
*
* @param predefinedNameBlacklist black list
* @param method method to check
* @param scanEntryPointAnnotation annotation
* @return Set
*/
public static Set getConsolidatedNameBlacklist(List predefinedNameBlacklist, Method method, boolean scanEntryPointAnnotation) {
final Set consolidatedBlacklist = new HashSet(predefinedNameBlacklist);
if (scanEntryPointAnnotation) {
// first we look into the class level
if (method.getDeclaringClass().isAnnotationPresent(ExternalEntryPoint.class)) {
final ExternalEntryPoint externalEntryPoint = method.getDeclaringClass().getAnnotation(ExternalEntryPoint.class);
if (externalEntryPoint.nameBlacklist() != null) {
consolidatedBlacklist.addAll(Arrays.asList(externalEntryPoint.nameBlacklist()));
}
}
// then we look at the method level
if (method.isAnnotationPresent(ExternalEntryPoint.class)) {
final ExternalEntryPoint externalEntryPoint = method.getAnnotation(ExternalEntryPoint.class);
if (externalEntryPoint.nameBlacklist() != null) {
consolidatedBlacklist.addAll(Arrays.asList(externalEntryPoint.nameBlacklist()));
}
}
}
return consolidatedBlacklist;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy