de.alpharogroup.reflection.ReflectionExtensions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jobj-core Show documentation
Show all versions of jobj-core Show documentation
Provides utility classes for the java core classes
The newest version!
/**
* The MIT License
*
* Copyright (C) 2015 Asterios Raptis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package de.alpharogroup.reflection;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.objenesis.instantiator.ObjectInstantiator;
import de.alpharogroup.lang.ClassExtensions;
import de.alpharogroup.lang.ClassType;
import lombok.NonNull;
import lombok.experimental.UtilityClass;
import lombok.extern.java.Log;
/**
* The class {@link ReflectionExtensions} provides utility methods for the java reflection API
*/
@UtilityClass
@Log
public final class ReflectionExtensions
{
/**
* Creates a new array instance from the same type as the given {@link Class} and the given
* length
*
* @param
* the generic type
* @param cls
* the class object
* @param length
* the length of the array
* @return the new array instance
*/
@SuppressWarnings("unchecked")
public static T[] newArrayInstance(final @NonNull Class cls, final int length)
{
return (T[])Array.newInstance(cls, length);
}
/**
* Creates a new empty array instance from the given source array the length of the given source
* array
*
* @param
* the generic type
* @param source
* the source array
* @return the new empty array instance
*/
@SuppressWarnings("unchecked")
public static T[] newEmptyArrayInstance(final @NonNull T[] source)
{
return (T[])newArrayInstance(source.getClass().getComponentType(), source.length);
}
/**
* Copy the given array object and return a copy of it.
*
* @param
* the generic type
* @param source
* the source
* @return the copy of the given array object
*/
public static T[] copyArray(final @NonNull T[] source)
{
T[] destination = newEmptyArrayInstance(source);
for (int i = 0; i < Array.getLength(source); i++)
{
Array.set(destination, i, Array.get(source, i));
}
return destination;
}
/**
* Copies the field value of the given source object to the given target object.
*
* @param
* the generic type of the object
* @param source
* the source
* @param target
* the target
* @param fieldName
* the field name
* @throws NoSuchFieldException
* is thrown if no such field exists.
* @throws SecurityException
* is thrown if a security manager says no.
* @throws IllegalAccessException
* is thrown if an illegal on create an instance or access a method.
*/
public static void copyFieldValue(final @NonNull T source, final @NonNull T target,
final @NonNull String fieldName)
throws NoSuchFieldException, SecurityException, IllegalAccessException
{
setFieldValue(source, target, getDeclaredField(source, fieldName));
}
/**
* Sets the field value of the given source object over the field
*
* @param
* the generic type
* @param source
* the source object
* @param target
* the target
* @param sourceField
* the source field
* @throws IllegalAccessException
* is thrown if an illegal on create an instance or access a method
* @throws SecurityException
* is thrown if a security manager says no
*/
public static void setFieldValue(final @NonNull T source, final @NonNull T target,
final @NonNull Field sourceField) throws IllegalAccessException
{
sourceField.setAccessible(true);
final Object sourceValue = sourceField.get(source);
setFieldValue(target, sourceField, sourceValue);
}
/**
* Sets the field value of the given source object
*
* @param
* the generic type
* @param source
* the source object
* @param field
* the field
* @param newValue
* the new value
* @throws IllegalAccessException
* is thrown if an illegal on create an instance or access a method
*/
public static void setFieldValue(final T source, final Field field, final Object newValue)
throws IllegalAccessException
{
field.setAccessible(true);
field.set(source, newValue);
}
/**
* Gets the field value of the given source object over the field name.
*
* @param
* the generic type
* @param source
* the source
* @param fieldName
* the field name
* @return the field value
* @throws NoSuchFieldException
* is thrown if no such field exists.
* @throws SecurityException
* is thrown if a security manager says no.
* @throws IllegalAccessException
* is thrown if an illegal on create an instance or access a method.
*/
public static Object getFieldValue(final @NonNull T source, final @NonNull String fieldName)
throws NoSuchFieldException, SecurityException, IllegalAccessException
{
final Field sourceField = getDeclaredField(source, fieldName);
sourceField.setAccessible(true);
return sourceField.get(source);
}
/**
* Sets the field value of the given class object over the field name.
*
* @param
* the generic type
* @param cls
* The class
* @param fieldName
* the field name
* @param newValue
* the new value
* @throws NoSuchFieldException
* is thrown if no such field exists.
* @throws SecurityException
* is thrown if a security manager says no.
* @throws IllegalAccessException
* is thrown if an illegal on create an instance or access a method.
*/
public static void setFieldValue(final @NonNull Class> cls,
final @NonNull String fieldName, final Object newValue)
throws NoSuchFieldException, SecurityException, IllegalAccessException
{
final Field sourceField = getDeclaredField(cls, fieldName);
sourceField.setAccessible(true);
sourceField.set(null, newValue);
}
/**
* Gets all field names from the given class as an String list.
*
* @param cls
* The class object to get the field names.
*
* @return Gets all field names from the given class as an String list.
*/
public static List getFieldNames(final @NonNull Class> cls)
{
return Arrays.stream(cls.getDeclaredFields()).filter(ReflectionExtensions::isNotSynthetic)
.map(Field::getName).collect(Collectors.toList());
}
/**
* Gets all field names from the given class as an String list minus the given ignored field
* names
*
* @param cls
* The class object to get the field names
* @param ignoreFieldNames
* a list with field names that shell be ignored
*
* @return Gets all field names from the given class as an String list minus the given ignored
* field names
*/
public static List getFieldNames(final @NonNull Class> cls,
List ignoreFieldNames)
{
return Arrays.stream(cls.getDeclaredFields()).filter(ReflectionExtensions::isNotSynthetic)
.map(Field::getName).filter(name -> !ignoreFieldNames.contains(name))
.collect(Collectors.toList());
}
/**
* Gets all field names from the given class as an String list minus the given optional array of
* ignored field names
*
* @param cls
* The class object to get the field names
* @param ignoreFieldNames
* a optional array with the field names that shell be ignored
*
* @return Gets all field names from the given class as an String list minus the given optional
* array of ignored field names
*/
public static List getFieldNames(final @NonNull Class> cls,
String... ignoreFieldNames)
{
return getFieldNames(cls, Arrays.asList(ignoreFieldNames));
}
/**
* Gets all the declared field names from the given class object.
*
* Note: without the field names from any superclasses
*
* @param cls
* the class object
* @return all the declared field names from the given class as an String array
*/
public static String[] getDeclaredFieldNames(final @NonNull Class> cls)
{
return Arrays.stream(cls.getDeclaredFields()).filter(ReflectionExtensions::isNotSynthetic)
.map(Field::getName).toArray(String[]::new);
}
/**
* Gets all the declared field names from the given class object minus the given ignored field
* names
*
* Note: without the field names from any superclasses
*
* @param cls
* the class object
* @param ignoreFieldNames
* a optional array with the field names that shell be ignored
* @return all the declared field names from the given class as an String array minus the given
* optional array of ignored field names
*/
public static String[] getDeclaredFieldNames(final @NonNull Class> cls,
String... ignoreFieldNames)
{
return getDeclaredFieldNames(cls, Arrays.asList(ignoreFieldNames));
}
/**
* Gets all the declared field names from the given class object minus the given ignored field
* names
*
* Note: without the field names from any superclasses
*
* @param cls
* the class object
* @param ignoreFieldNames
* a list with field names that shell be ignored
* @return all the declared field names from the given class as an String array minus the given
* ignored field names
*/
public static String[] getDeclaredFieldNames(final @NonNull Class> cls,
List ignoreFieldNames)
{
return Arrays.stream(cls.getDeclaredFields()).filter(ReflectionExtensions::isNotSynthetic)
.map(Field::getName).filter(name -> !ignoreFieldNames.contains(name))
.toArray(String[]::new);
}
/**
* Checks if the given {@link Field} is not synthetic
*
* @param field
* the field
* @return true, if the given {@link Field} is not synthetic otherwise false
*/
public static boolean isNotSynthetic(@NonNull Field field)
{
return !field.isSynthetic();
}
/**
* Gets all method names from the given class as an String array.
*
* @param cls
* The class object to get the method names.
*
* @return Gets all method names from the given class as an String array.
*/
public static String[] getMethodNames(final @NonNull Class> cls)
{
final Method[] methods = cls.getDeclaredMethods();
final String[] methodNames = new String[methods.length];
for (int i = 0; i < methods.length; i++)
{
methodNames[i] = methods[i].getName();
}
return methodNames;
}
/**
* Generates a Map with the fieldName as key and the method as value. Concatenates the given
* prefix and the field name and puts the result into the map.
*
* @param fieldNames
* A list with the field names.
* @param prefix
* The prefix for the method name.
*
* @return the method names with prefix from field names
*/
public static Map getMethodNamesWithPrefixFromFieldNames(
final @NonNull List fieldNames, final String prefix)
{
final Map fieldNameMethodMapper = new HashMap<>();
for (final String fieldName : fieldNames)
{
final String firstCharacterToUpperCasefieldName = firstCharacterToUpperCase(fieldName);
final String methodName = prefix + firstCharacterToUpperCasefieldName;
fieldNameMethodMapper.put(fieldName, methodName);
}
return fieldNameMethodMapper;
}
/**
* Sets the first character from the given string to upper case and returns it. Example:
* Given fieldName: userName
* Result: UserName
*
* @param fieldName
* The String to modify.
* @return The modified string.
*/
public static String firstCharacterToUpperCase(final @NonNull String fieldName)
{
String firstCharacter = fieldName.substring(0, 1);
firstCharacter = firstCharacter.toUpperCase();
final char[] fc = firstCharacter.toCharArray();
final char[] fn = fieldName.toCharArray();
fn[0] = fc[0];
return new String(fn);
}
/**
* Gets the modifiers from the given Field as a list of String objects.
*
* @param field
* The field to get the modifiers.
* @return A list with the modifiers as String objects from the given Field.
*/
public static List getModifiers(final @NonNull Field field)
{
final String modifiers = Modifier.toString(field.getModifiers());
final String[] modifiersArray = modifiers.split(" ");
return Arrays.asList(modifiersArray);
}
/**
* Creates a new instance from the same type as the given object.
*
* @param
* the generic type
* @param object
* the object
* @return the new instance
*/
@SuppressWarnings("unchecked")
public static T newInstance(final @NonNull T object)
{
Class> clazz = object.getClass();
ClassType classType = ClassExtensions.getClassType(clazz);
switch (classType)
{
case ARRAY :
int length = Array.getLength(object);
return (T)Array.newInstance(clazz.getComponentType(), length);
default :
return newInstance((Class)object.getClass());
}
}
/**
* Factory method for create a new instance from the same type as the given {@link Class}. First
* try is over the class and second try is with objenesis.
*
* Note: if non of the tries no instance could created null will be returned.
*
* @param
* the generic type
* @param clazz
* the Class object
* @return the new instance
*/
public static T newInstance(final @NonNull Class clazz)
{
T newInstance = null;
Optional optionalNewInstance;
optionalNewInstance = forceNewInstanceWithClass(clazz);
if (optionalNewInstance.isPresent())
{
return optionalNewInstance.get();
}
optionalNewInstance = forceNewInstanceWithObjenesis(clazz);
if (optionalNewInstance.isPresent())
{
return optionalNewInstance.get();
}
return newInstance;
}
private static Optional forceNewInstanceWithClass(final @NonNull Class clazz)
{
Optional optionalNewInstance = Optional.empty();
try
{
optionalNewInstance = Optional.of(newInstanceWithClass(clazz));
}
catch (InstantiationException | IllegalAccessException e)
{
log.log(Level.INFO, "Failed to create new instance with method Class.newInstance()", e);
}
return optionalNewInstance;
}
private static Optional forceNewInstanceWithObjenesis(final @NonNull Class clazz)
{
Optional optionalNewInstance = Optional.empty();
try
{
optionalNewInstance = Optional.of(newInstanceWithObjenesis(clazz));
}
catch (Exception e)
{
log.log(Level.INFO,
"Failed to create new instance with Objenesis ObjectInstantiator.newInstance()", e);
}
return optionalNewInstance;
}
/**
* Creates a new instance from the same type as the given {@link Class}
*
* @param
* the generic type
* @param clazz
* the Class object
* @return the new instance
* @throws IllegalAccessException
* is thrown if the class or its default constructor is not accessible.
* @throws InstantiationException
* is thrown if this {@code Class} represents an abstract class, an interface, an
* array class, a primitive type, or void; or if the class has no default
* constructor; or if the instantiation fails for some other reason.
*/
public static T newInstanceWithClass(final @NonNull Class clazz)
throws InstantiationException, IllegalAccessException
{
return clazz.newInstance();
}
/**
* Creates a new instance from the same type as the given {@link Class}
*
* @param
* the generic type
* @param clazz
* the Class object
* @return the new instance
*/
public static T newInstanceWithObjenesis(final @NonNull Class clazz)
{
Objenesis objenesis = new ObjenesisStd();
ObjectInstantiator instantiator = objenesis.getInstantiatorOf(clazz);
return instantiator.newInstance();
}
/**
* Gets the {@link Field} that match to the given field name that exists in the given object.
*
* @param
* the generic type
* @param object
* the object
* @param fieldName
* the field name
* @return the declared field
* @throws NoSuchFieldException
* is thrown if no such field exists.
* @throws SecurityException
* is thrown if a security manager says no.
*/
public static Field getDeclaredField(@NonNull final T object,
final @NonNull String fieldName) throws NoSuchFieldException, SecurityException
{
return getDeclaredField(object.getClass(), fieldName);
}
/**
* Gets the {@link Field} that match to the given field name that exists in the given class.
*
* @param cls
* the class object
* @param fieldName
* the field name
* @return the declared field
* @throws NoSuchFieldException
* is thrown if no such field exists.
* @throws SecurityException
* is thrown if a security manager says no.
*/
public static Field getDeclaredField(final @NonNull Class> cls,
final @NonNull String fieldName) throws NoSuchFieldException, SecurityException
{
return cls.getDeclaredField(fieldName);
}
/**
* Gets all the declared fields including all fields from all super classes from the given class
* object minus the given ignored fields
*
* @param cls
* the class object
* @param ignoreFieldNames
* an optional array with field names that shell be ignored
* @return all the declared fields minus the given ignored field names
*/
public static Field[] getAllDeclaredFields(final @NonNull Class> cls,
final String... ignoreFieldNames)
{
return getAllDeclaredFields(cls, Arrays.asList(ignoreFieldNames));
}
/**
* Gets all the declared fields including all fields from all super classes from the given class
* object minus the given ignored fields
*
* @param cls
* the class object
* @param ignoreFieldNames
* a list with field names that shell be ignored
* @return all the declared fields minus the given ignored field names
*/
public static Field[] getAllDeclaredFields(final @NonNull Class> cls,
List ignoreFieldNames)
{
Field[] declaredFields = getDeclaredFields(cls, ignoreFieldNames);
Class> superClass = cls.getSuperclass();
if (superClass != null && superClass.equals(Object.class))
{
return declaredFields;
}
List fields = new ArrayList<>(Arrays.asList(declaredFields));
while ((superClass != null && superClass.getSuperclass() != null
&& superClass.getSuperclass().equals(Object.class)))
{
fields.addAll(Arrays.asList(getDeclaredFields(superClass, ignoreFieldNames)));
superClass = superClass.getSuperclass();
}
return fields.toArray(new Field[] { });
}
/**
* Gets all the declared field names including all fields from all super classes from the given
* class object
*
* @param cls
* the class object
* @return all the declared field names
*/
public static String[] getAllDeclaredFieldNames(final @NonNull Class> cls)
{
return Arrays.stream(getAllDeclaredFields(cls)).map(Field::getName).toArray(String[]::new);
}
/**
* Gets all the declared field names including all fields from all super classes from the given
* class object minus the given optional array of ignored field names
*
* @param cls
* the class object
* @param ignoreFieldNames
* an optional array with the field names that shell be ignored
* @return all the declared field names minus the given optional array of ignored field names
*/
public static String[] getAllDeclaredFieldNames(final @NonNull Class> cls,
String... ignoreFieldNames)
{
return getAllDeclaredFieldNames(cls, Arrays.asList(ignoreFieldNames));
}
/**
* Gets all the declared field names including all fields from all super classes from the given
* class object minus the given ignored field names
*
* @param cls
* the class object
* @param ignoreFieldNames
* a list with field names that shell be ignored
* @return all the declared field names minus the given ignored field names
*/
public static String[] getAllDeclaredFieldNames(final @NonNull Class> cls,
List ignoreFieldNames)
{
Field[] allDeclaredFields = getAllDeclaredFields(cls);
return Arrays.stream(allDeclaredFields).map(Field::getName)
.filter(name -> !ignoreFieldNames.contains(name)).toArray(String[]::new);
}
/**
* Gets the declared fields from the given class minus the given ignored field names
*
* @param cls
* the class object
* @param ignoreFieldNames
* a list with field names that shell be ignored
* @return the declared {@link Field} from the given class minus the given ignored field names
* @throws SecurityException
* is thrown if a security manager says no
*/
public static Field[] getDeclaredFields(final @NonNull Class> cls,
List ignoreFieldNames) throws SecurityException
{
return Arrays.stream(cls.getDeclaredFields())
.filter(field -> !ignoreFieldNames.contains(field.getName())).toArray(Field[]::new);
}
/**
* Gets the declared fields from the given class minus the given optional array of ignored field
* names
*
* @param cls
* the class object
* @param ignoreFieldNames
* a list with field names that shell be ignored
* @return the declared {@link Field} from the given class minus the given optional array of
* ignored field names
* @throws SecurityException
* is thrown if a security manager says no
*/
public static Field[] getDeclaredFields(final @NonNull Class> cls, String... ignoreFieldNames)
throws SecurityException
{
return getDeclaredFields(cls, Arrays.asList(ignoreFieldNames));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy