org.dynamoframework.utils.ClassUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dynamo-impl Show documentation
Show all versions of dynamo-impl Show documentation
Dynamo Framework implementation project.
package org.dynamoframework.utils;
/*-
* #%L
* Dynamo Framework
* %%
* Copyright (C) 2014 - 2024 Open Circle Solutions
* %%
* 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.
* #L%
*/
import jakarta.validation.constraints.Size;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.dynamoframework.exception.OCSRuntimeException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
/**
* @author Bas Rutten
*/
@Slf4j
@UtilityClass
public final class ClassUtils {
private static final String GET = "get";
private static final String IS = "is";
private static final String SET = "set";
/**
* Checks if the specified property can be set for the specified object. This
* method supports nested properties
*
* @param obj the object
* @param fieldName the name of the field
* @return true if this is the case, false otherwise
*/
public static boolean canSetProperty(Object obj, String fieldName) {
try {
int p = fieldName.indexOf('.');
if (p >= 0) {
String firstProperty = fieldName.substring(0, p);
Object first = MethodUtils.invokeMethod(obj,
GET + StringUtils.capitalize(firstProperty));
if (first != null) {
return canSetProperty(first, fieldName.substring(p + 1));
}
return false;
} else {
return hasMethod(obj, SET + StringUtils.capitalize(fieldName));
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new OCSRuntimeException(e.getMessage(), e);
}
}
/**
* Clears an attribute value
*
* @param obj the object on which to clear the field
* @param attributeName the name of the attribute
* @param argType the argument type
*/
public static void clearAttributeValue(Object obj, String attributeName, Class> argType) {
try {
int p = attributeName.indexOf('.');
if (p >= 0) {
String firstProperty = attributeName.substring(0, p);
Object first = MethodUtils.invokeMethod(obj, GET + StringUtils.capitalize(firstProperty));
if (first != null) {
clearAttributeValue(first, attributeName.substring(p + 1), argType);
}
} else {
Method method = obj.getClass().getMethod(SET + StringUtils.capitalize(attributeName), argType);
method.invoke(obj, (Object) null);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new OCSRuntimeException(e.getMessage(), e);
}
}
/**
* Tries to retrieve an annotation, by first looking at the field name, and then
* at the getter method
*
* @param clazz the class
* @param attributeName the name of the field
* @param annotationClass the annotation class to look for
* @return the annotation
*/
public static T getAnnotation(Class> clazz, String attributeName, Class annotationClass) {
T entity = getAnnotationOnMethod(clazz, attributeName, annotationClass);
if (entity == null) {
entity = getAnnotationOnField(clazz, attributeName, annotationClass);
}
return entity;
}
/**
* Get the value of a field in an annotation
*
* @param field The field with annotations
* @param annotationClass The class of the annotation
* @param attributeName The name of the attribute on the annotation type to find
* the value
* @return the value of the field of the annotation or null when not found
*/
@SuppressWarnings("unchecked")
public static R getAnnotationAttributeValue(Field field, Class annotationClass,
String attributeName) {
R result = null;
Annotation annotation = getAnnotationOnField(field, annotationClass);
if (annotation != null) {
result = (R) AnnotationUtils.getValue(annotation, attributeName);
}
return result;
}
/**
* Return an annotation on a certain field
*
* @param clazz the class
* @param fieldName the field name
* @param annotationClass the class of the annotation
* @return the annotation
*/
public static T getAnnotationOnField(Class> clazz, String fieldName,
Class annotationClass) {
Field field = getField(clazz, fieldName);
if (field != null) {
return getAnnotationOnField(field, annotationClass);
}
return null;
}
/**
* Returns an annotation on a certain field
*
* @param field the field
* @param annotationClass the annotation class
* @return the annotation
*/
@SuppressWarnings("unchecked")
public static T getAnnotationOnField(Field field, Class annotationClass) {
T result = null;
if (field != null) {
for (Annotation a : field.getDeclaredAnnotations()) {
if (a.annotationType().equals(annotationClass)) {
result = (T) a;
}
}
}
return result;
}
/**
* Looks for an annotation on a getter method
*
* @param clazz the class
* @param fieldName the name of the field (will be prepended with "get")
* @param annotationClass the class of the annotation to look for
* @return the annotation
*/
public static T getAnnotationOnMethod(Class> clazz, String fieldName,
Class annotationClass) {
Method method = getGetterMethod(clazz, fieldName);
if (method != null) {
return getAnnotationOnMethod(method, annotationClass);
}
return null;
}
/**
* Looks for an annotation on a (getter) method
*
* @param method the method
* @param annotationClass the class of the annotation
* @return the annotation
*/
@SuppressWarnings("unchecked")
public static T getAnnotationOnMethod(Method method, Class annotationClass) {
T result = null;
if (method != null) {
for (Annotation a : method.getDeclaredAnnotations()) {
if (a.annotationType().equals(annotationClass)) {
result = (T) a;
}
}
}
return result;
}
/**
* Retrieves the contents of a field as a byte array
*
* @param obj the object
* @param fieldName the name of the field
* @return the content, as a byte array
*/
public static byte[] getBytes(Object obj, String fieldName) {
return (byte[]) getFieldValue(obj, fieldName);
}
/**
* Find constructor based on the types of the given arguments used to
* instantiate the class with the found constructor
*
* @param clazz the class for which to find the constructor
* @param args the arguments
* @return the constructor
*/
public static Constructor getConstructor(Class clazz, Object... args) {
Constructor constructor = null;
List> types = new ArrayList<>();
for (Object arg : args) {
types.add(arg.getClass());
}
try {
if (types.isEmpty()) {
constructor = clazz.getConstructor();
} else {
constructor = clazz.getConstructor(types.toArray(new Class>[0]));
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return constructor;
}
/**
* Returns a field with a certain name from a class
*
* @param clazz the class
* @param fieldName the name of the filed
* @return the field
*/
public static Field getField(Class> clazz, String fieldName) {
Field field = null;
if (clazz != null) {
try {
field = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
if (clazz.getSuperclass() != null) {
return getField(clazz.getSuperclass(), fieldName);
}
}
}
return field;
}
/**
* Retrieves a field value
*
* @param obj the object from which to retrieve the field value
* @param fieldName the name of the field
* @return the field value
*/
public static Object getFieldValue(Object obj, String fieldName) {
try {
int p = fieldName.indexOf('.');
if (p >= 0) {
String firstProperty = fieldName.substring(0, p);
Object first = MethodUtils.invokeMethod(obj, GET + StringUtils.capitalize(firstProperty));
return first == null ? null : getFieldValue(first, fieldName.substring(p + 1));
} else {
if (hasMethod(obj, GET + StringUtils.capitalize(fieldName))) {
// first check for a getter
return MethodUtils.invokeMethod(obj, GET + StringUtils.capitalize(fieldName));
} else {
// next, check for an "is" method in case of a boolean
return MethodUtils.invokeMethod(obj, IS + StringUtils.capitalize(fieldName));
}
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new OCSRuntimeException("Error getting of " + obj + ":" + e.getMessage(), e);
}
}
/**
* Returns a field value as a String
*
* @param obj the object
* @param fieldName the name of the field
* @return the field value, as a string
*/
public static String getFieldValueAsString(Object obj, String fieldName) {
return getFieldValueAsString(obj, fieldName, null);
}
/**
* Returns a field value as a String
*
* @param obj the object
* @param fieldName the name of the field
* @param defaultValue the default value that is used in case of a null value
* @return the field value as a String
*/
public static String getFieldValueAsString(Object obj, String fieldName, String defaultValue) {
Object temp = getFieldValue(obj, fieldName);
return temp == null ? defaultValue : temp.toString();
}
/**
* Retrieves the getter method for a certain property
*
* @param clazz the class
* @param fieldName the name of the property
* @return the method
*/
public static Method getGetterMethod(Class> clazz, String fieldName) {
Method method = null;
if (clazz != null) {
try {
// first, try to find a "get" method
method = clazz.getDeclaredMethod(GET + StringUtils.capitalize(fieldName));
} catch (NoSuchMethodException | SecurityException ex) {
try {
// next, try to find an "is" method
method = clazz.getDeclaredMethod(IS + StringUtils.capitalize(fieldName));
} catch (NoSuchMethodException | SecurityException ex2) {
// if that fails, try the superclass
if (clazz.getSuperclass() != null) {
return getGetterMethod(clazz.getSuperclass(), fieldName);
}
}
}
}
return method;
}
/**
* Returns the maximum allowed length of a field
*
* @param clazz the clazz on which the field is located
* @param fieldName the name of the field
* @return the maximum length
*/
public static int getMaxLength(Class> clazz, String fieldName) {
Size size = getAnnotation(clazz, fieldName, Size.class);
if (size != null) {
return size.max();
}
return -1;
}
/**
* Return a Class> representing the generic parameter for the given indexes.
* Indexes are zero based; for example given the type Map>, getGeneric(0) will access the Integer. Nested generics can be
* accessed by specifying multiple indexes; for example getGeneric(1, 0) will
* access the String from the nested List. For convenience, if no indexes are
* specified the first generic is returned.
*
* @param type the class
* @param fieldName the name of the field
* @param indexes the set of indexes
* @return the resolved type
*/
public static Class> getResolvedType(Class type, String fieldName, int... indexes) {
Field field = getField(type, fieldName);
if (field != null) {
ResolvableType rt = ResolvableType.forField(field);
if (indexes != null && indexes.length > 0) {
rt = rt.getGeneric(indexes);
}
return rt.resolve();
}
return null;
}
/**
* Check if the object has a (public) method that has the specified name
*
* @param obj the object to check
* @param methodName the name of the method
* @return true if this is the case, false otherwise
*/
public static boolean hasMethod(Object obj, String methodName) {
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(methodName) && Modifier.isPublic(method.getModifiers())) {
return true;
}
}
return false;
}
/**
* Instantiate a class with the given arguments; assumed is that all arguments
* are not null so the types can be determined and a matching constructor can be
* found. When no constructor is found null is returned.
*
* @param clazz the class
* @param args the constructor arguments to pass
* @return the instantiated class
*/
public static T instantiateClass(Class clazz, Object... args) {
Constructor constructor = getConstructor(clazz, args);
if (constructor != null) {
return org.springframework.beans.BeanUtils.instantiateClass(constructor, args);
}
return null;
}
public static void setBytes(byte[] bytes, Object obj, String fieldName) {
if (bytes != null) {
setFieldValue(obj, fieldName, bytes);
} else {
clearAttributeValue(obj, fieldName, byte[].class);
}
}
/**
* Sets the value of the provided field on the provided object
*
* @param obj the object
* @param fieldName the name of the field
* @param value the value to set
*/
public static void setFieldValue(Object obj, String fieldName, Object value) {
try {
int p = fieldName.indexOf('.');
if (p >= 0) {
String firstProperty = fieldName.substring(0, p);
Object first = MethodUtils.invokeMethod(obj, GET + StringUtils.capitalize(firstProperty));
if (first != null) {
if (first instanceof Collection> col) {
col.forEach(c -> setFieldValue(c, fieldName.substring(p + 1), value));
} else {
setFieldValue(first, fieldName.substring(p + 1), value);
}
}
} else {
MethodUtils.invokeMethod(obj, SET + StringUtils.capitalize(fieldName), value);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
log.error(e.getMessage(), e);
throw new OCSRuntimeException(e.getMessage(), e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy