grails.util.GrailsClassUtils Maven / Gradle / Ivy
Show all versions of grace-util Show documentation
/*
* Copyright 2004-2023 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
*
* https://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 grails.util;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import groovy.lang.AdaptingMetaClass;
import groovy.lang.ExpandoMetaClass;
import groovy.lang.ExpandoMetaClassCreationHandle;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import groovy.lang.MetaClassRegistry;
import groovy.lang.MetaProperty;
import groovy.util.ConfigObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Utility methods for dealing with Grails class artifacts.
*
* @author Graeme Rocher
*/
public final class GrailsClassUtils {
private static final Log logger = LogFactory.getLog(GrailsClassUtils.class);
public static final Map, Class>> PRIMITIVE_TYPE_COMPATIBLE_CLASSES = new HashMap<>();
/**
* Just add two entries to the class compatibility map
* @param left
* @param right
*/
private static void registerPrimitiveClassPair(Class> left, Class> right) {
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(left, right);
PRIMITIVE_TYPE_COMPATIBLE_CLASSES.put(right, left);
}
static {
registerPrimitiveClassPair(Boolean.class, boolean.class);
registerPrimitiveClassPair(Integer.class, int.class);
registerPrimitiveClassPair(Short.class, short.class);
registerPrimitiveClassPair(Byte.class, byte.class);
registerPrimitiveClassPair(Character.class, char.class);
registerPrimitiveClassPair(Long.class, long.class);
registerPrimitiveClassPair(Float.class, float.class);
registerPrimitiveClassPair(Double.class, double.class);
}
private GrailsClassUtils() {
}
/**
* Return all interfaces that the given instance implements as array,
* including ones implemented by superclasses.
* @param instance the instance to analyze for interfaces
* @return all interfaces that the given instance implements as array
*/
public static Class[] getAllInterfaces(Object instance) {
Assert.notNull(instance, "Instance must not be null");
return getAllInterfacesForClass(instance.getClass());
}
/**
* Return all interfaces that the given class implements as array,
* including ones implemented by superclasses.
* If the class itself is an interface, it gets returned as sole interface.
* @param clazz the class to analyze for interfaces
* @return all interfaces that the given object implements as array
*/
public static Class>[] getAllInterfacesForClass(Class> clazz) {
return getAllInterfacesForClass(clazz, null);
}
/**
* Return all interfaces that the given class implements as array,
* including ones implemented by superclasses.
*
If the class itself is an interface, it gets returned as sole interface.
* @param clazz the class to analyze for interfaces
* @param classLoader the ClassLoader that the interfaces need to be visible in
* (may be {@code null} when accepting all declared interfaces)
* @return all interfaces that the given object implements as array
*/
public static Class>[] getAllInterfacesForClass(Class> clazz, ClassLoader classLoader) {
Set ifcs = getAllInterfacesForClassAsSet(clazz, classLoader);
return ifcs.toArray(new Class[0]);
}
/**
* Return all interfaces that the given instance implements as Set,
* including ones implemented by superclasses.
* @param instance the instance to analyze for interfaces
* @return all interfaces that the given instance implements as Set
*/
public static Set getAllInterfacesAsSet(Object instance) {
Assert.notNull(instance, "Instance must not be null");
return getAllInterfacesForClassAsSet(instance.getClass());
}
/**
* Return all interfaces that the given class implements as Set,
* including ones implemented by superclasses.
* If the class itself is an interface, it gets returned as sole interface.
* @param clazz the class to analyze for interfaces
* @return all interfaces that the given object implements as Set
*/
public static Set getAllInterfacesForClassAsSet(Class clazz) {
return getAllInterfacesForClassAsSet(clazz, null);
}
/**
* Return all interfaces that the given class implements as Set,
* including ones implemented by superclasses.
* If the class itself is an interface, it gets returned as sole interface.
* @param clazz the class to analyze for interfaces
* @param classLoader the ClassLoader that the interfaces need to be visible in
* (may be {@code null} when accepting all declared interfaces)
* @return all interfaces that the given object implements as Set
*/
public static Set getAllInterfacesForClassAsSet(Class clazz, ClassLoader classLoader) {
Assert.notNull(clazz, "Class must not be null");
Set interfaces = new LinkedHashSet<>();
while (clazz != null) {
Class>[] ifcs = clazz.getInterfaces();
for (Class> ifc : ifcs) {
interfaces.add(ifc);
interfaces.addAll(getAllInterfacesForClassAsSet(ifc, classLoader));
}
clazz = clazz.getSuperclass();
}
return interfaces;
}
/**
* Check whether the given class is visible in the given ClassLoader.
* @param clazz the class to check (typically an interface)
* @param classLoader the ClassLoader to check against (may be {@code null},
* in which case this method will always return {@code true})
*/
public static boolean isVisible(Class> clazz, ClassLoader classLoader) {
if (classLoader == null) {
return true;
}
try {
Class> actualClass = classLoader.loadClass(clazz.getName());
return (clazz == actualClass);
// Else: different interface class found...
}
catch (ClassNotFoundException ex) {
// No interface class found...
return false;
}
}
/**
* Returns true if the specified property in the specified class is of the specified type
*
* @param clazz The class which contains the property
* @param propertyName The property name
* @param type The type to check
*
* @return A boolean value
*/
public static boolean isPropertyOfType(Class> clazz, String propertyName, Class> type) {
try {
Class> propType = getPropertyType(clazz, propertyName);
return propType != null && propType.equals(type);
}
catch (Exception e) {
return false;
}
}
/**
* Returns the value of the specified property and type from an instance of the specified Grails class
*
* @param clazz The name of the class which contains the property
* @param propertyName The property name
* @param propertyType The property type
*
* @return The value of the property or null if none exists
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Object getPropertyValueOfNewInstance(Class clazz, String propertyName, Class> propertyType) {
// validate
if (clazz == null || !StringUtils.hasText(propertyName)) {
return null;
}
try {
return getPropertyOrStaticPropertyOrFieldValue(BeanUtils.instantiateClass(clazz), propertyName);
}
catch (BeanInstantiationException e) {
return null;
}
}
/**
* Returns the value of the specified property and type from an instance of the specified Grails class
*
* @param clazz The name of the class which contains the property
* @param propertyName The property name
*
* @return The value of the property or null if none exists
*/
public static Object getPropertyValueOfNewInstance(Class> clazz, String propertyName) {
// validate
if (clazz == null || !StringUtils.hasText(propertyName)) {
return null;
}
try {
return getPropertyOrStaticPropertyOrFieldValue(BeanUtils.instantiateClass(clazz), propertyName);
}
catch (BeanInstantiationException e) {
return null;
}
}
/**
* Retrieves a PropertyDescriptor for the specified instance and property value
*
* @param instance The instance
* @param propertyValue The value of the property
* @return The PropertyDescriptor
*/
public static PropertyDescriptor getPropertyDescriptorForValue(Object instance, Object propertyValue) {
if (instance == null || propertyValue == null) {
return null;
}
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(instance.getClass());
for (PropertyDescriptor pd : descriptors) {
if (isAssignableOrConvertibleFrom(pd.getPropertyType(), propertyValue.getClass())) {
Object value;
try {
ReflectionUtils.makeAccessible(pd.getReadMethod());
value = pd.getReadMethod().invoke(instance);
}
catch (Exception e) {
throw new FatalBeanException("Problem calling readMethod of " + pd, e);
}
if (propertyValue.equals(value)) {
return pd;
}
}
}
return null;
}
/**
* Returns the type of the given property contained within the specified class
*
* @param clazz The class which contains the property
* @param propertyName The name of the property
*
* @return The property type or null if none exists
*/
public static Class> getPropertyType(Class> clazz, String propertyName) {
if (clazz == null || !StringUtils.hasText(propertyName)) {
return null;
}
try {
PropertyDescriptor desc = BeanUtils.getPropertyDescriptor(clazz, propertyName);
if (desc != null) {
return desc.getPropertyType();
}
return null;
}
catch (Exception e) {
// if there are any errors in instantiating just return null for the moment
return null;
}
}
/**
* Retrieves all the properties of the given class for the given type
*
* @param clazz The class to retrieve the properties from
* @param propertyType The type of the properties you wish to retrieve
*
* @return An array of PropertyDescriptor instances
*/
public static PropertyDescriptor[] getPropertiesOfType(Class> clazz, Class> propertyType) {
if (clazz == null || propertyType == null) {
return new PropertyDescriptor[0];
}
Set properties = new HashSet<>();
PropertyDescriptor descriptor = null;
try {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz);
for (PropertyDescriptor propertyDescriptor : descriptors) {
descriptor = propertyDescriptor;
Class> currentPropertyType = descriptor.getPropertyType();
if (isTypeInstanceOfPropertyType(propertyType, currentPropertyType)) {
properties.add(descriptor);
}
}
}
catch (Exception e) {
if (descriptor == null) {
logger.error(String.format("Got exception while checking property descriptors for class %s", clazz.getName()), e);
}
else {
logger.error(String.format("Got exception while checking PropertyDescriptor.propertyType for field %s.%s",
clazz.getName(), descriptor.getName()), e);
}
// if there are any errors in instantiating just return null for the moment
return new PropertyDescriptor[0];
}
return properties.toArray(new PropertyDescriptor[0]);
}
private static boolean isTypeInstanceOfPropertyType(Class> type, Class> propertyType) {
return propertyType.isAssignableFrom(type) && !propertyType.equals(Object.class);
}
/**
* Retrieves all the properties of the given class which are assignable to the given type
*
* @param clazz The class to retrieve the properties from
* @param propertySuperType The type of the properties you wish to retrieve
* @return An array of PropertyDescriptor instances
*/
public static PropertyDescriptor[] getPropertiesAssignableToType(Class> clazz, Class> propertySuperType) {
if (clazz == null || propertySuperType == null) {
return new PropertyDescriptor[0];
}
Set properties = new HashSet<>();
PropertyDescriptor descriptor = null;
try {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz);
for (PropertyDescriptor propertyDescriptor : descriptors) {
descriptor = propertyDescriptor;
Class> currentPropertyType = descriptor.getPropertyType();
if (propertySuperType.isAssignableFrom(descriptor.getPropertyType())) {
properties.add(descriptor);
}
}
}
catch (Exception e) {
if (descriptor == null) {
logger.error(String.format("Got exception while checking property descriptors for class %s", clazz.getName()), e);
}
else {
logger.error(String.format("Got exception while checking PropertyDescriptor.propertyType for field %s.%s",
clazz.getName(), descriptor.getName()), e);
}
return new PropertyDescriptor[0];
}
return properties.toArray(new PropertyDescriptor[0]);
}
/**
* Retrieves a property of the given class of the specified name and type
* @param clazz The class to retrieve the property from
* @param propertyName The name of the property
* @param propertyType The type of the property
*
* @return A PropertyDescriptor instance or null if none exists
*/
public static PropertyDescriptor getProperty(Class> clazz, String propertyName, Class> propertyType) {
if (clazz == null || propertyName == null || propertyType == null) {
return null;
}
try {
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, propertyName);
if (pd != null && pd.getPropertyType().equals(propertyType)) {
return pd;
}
return null;
}
catch (Exception e) {
// if there are any errors in instantiating just return null for the moment
return null;
}
}
/**
* Retrieves a property of the given class of the specified name and type
* @param clazz The class to retrieve the property from
* @param propertyName The name of the property
*
* @return A PropertyDescriptor instance or null if none exists
*/
public static PropertyDescriptor getProperty(Class> clazz, String propertyName) {
if (clazz == null || propertyName == null) {
return null;
}
try {
return BeanUtils.getPropertyDescriptor(clazz, propertyName);
}
catch (Exception e) {
// if there are any errors in instantiating just return null for the moment
return null;
}
}
/**
* Convenience method for converting a collection to an Object[]
* @param c The collection
* @return An object array
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Object[] collectionToObjectArray(Collection c) {
if (c == null) {
return new Object[0];
}
return c.toArray(new Object[0]);
}
/**
* Detect if left and right types are matching types. In particular,
* test if one is a primitive type and the other is the corresponding
* Java wrapper type. Primitive and wrapper classes may be passed to
* either arguments.
*
* @param leftType
* @param rightType
* @return true if one of the classes is a native type and the other the object representation
* of the same native type
*/
@SuppressWarnings("rawtypes")
public static boolean isMatchBetweenPrimativeAndWrapperTypes(Class leftType, Class rightType) {
if (leftType == null) {
throw new NullPointerException("Left type is null!");
}
if (rightType == null) {
throw new NullPointerException("Right type is null!");
}
Class> r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(leftType);
return r == rightType;
}
/**
* Tests whether or not the left hand type is compatible with the right hand type in Groovy
* terms, i.e. can the left type be assigned a value of the right hand type in Groovy.
* This handles Java primitive type equivalence and uses isAssignableFrom for all other types,
* with a bit of magic for native types and polymorphism i.e. Number assigned an int.
* If either parameter is null an exception is thrown
*
* @param leftType The type of the left hand part of a notional assignment
* @param rightType The type of the right hand part of a notional assignment
* @return true if values of the right hand type can be assigned in Groovy to variables of the left hand type.
*/
public static boolean isGroovyAssignableFrom(Class> leftType, Class> rightType) {
if (leftType == null) {
throw new NullPointerException("Left type is null!");
}
if (rightType == null) {
throw new NullPointerException("Right type is null!");
}
if (leftType == Object.class) {
return true;
}
if (leftType == rightType) {
return true;
}
// check for primitive type equivalence
Class> r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(leftType);
boolean result = r == rightType;
if (!result) {
// If no primitive <-> wrapper match, it may still be assignable
// from polymorphic primitives i.e. Number -> int (AKA Integer)
if (rightType.isPrimitive()) {
// see if incompatible
r = PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(rightType);
if (r != null) {
result = leftType.isAssignableFrom(r);
}
}
else {
// Otherwise it may just be assignable using normal Java polymorphism
result = leftType.isAssignableFrom(rightType);
}
}
return result;
}
/**
* Work out if the specified property is readable and static. Java introspection does not
* recognize this concept of static properties but Groovy does. We also consider public static fields
* as static properties with no getters/setters
*
* @param clazz The class to check for static property
* @param propertyName The property name
* @return true if the property with name propertyName has a static getter method
*/
@SuppressWarnings("rawtypes")
public static boolean isStaticProperty(Class clazz, String propertyName) {
Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(propertyName), (Class[]) null);
if (getter != null) {
return isPublicStatic(getter);
}
try {
Field f = clazz.getDeclaredField(propertyName);
if (f != null) {
return isPublicStatic(f);
}
}
catch (NoSuchFieldException ignored) {
}
return false;
}
/**
* Determine whether the method is declared public static
* @param m
* @return true if the method is declared public static
*/
public static boolean isPublicStatic(Method m) {
int modifiers = m.getModifiers();
return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers);
}
/**
* Determine whether the field is declared public static
* @param f
* @return true if the field is declared public static
*/
public static boolean isPublicStatic(Field f) {
int modifiers = f.getModifiers();
return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers);
}
/**
* Calculate the name for a getter method to retrieve the specified property
* @param propertyName
* @return The name for the getter method for this property, if it were to exist, i.e. getConstraints
*/
public static String getGetterName(String propertyName) {
return GrailsNameUtils.getGetterName(propertyName);
}
/**
* Get a static field value.
*
* @param clazz The class to check for static property
* @param name The field name
* @return The value if there is one, or null if unset OR there is no such field
*/
public static Object getStaticFieldValue(Class> clazz, String name) {
Field field = ReflectionUtils.findField(clazz, name);
if (field != null) {
ReflectionUtils.makeAccessible(field);
try {
return field.get(clazz);
}
catch (IllegalAccessException ignored) {
}
}
return null;
}
/**
* Get a static property value, which has a public static getter or is just a public static field.
*
* @param clazz The class to check for static property
* @param name The property name
* @return The value if there is one, or null if unset OR there is no such property
*/
public static Object getStaticPropertyValue(Class> clazz, String name) {
Method getter = BeanUtils.findDeclaredMethod(clazz, getGetterName(name), (Class[]) null);
try {
if (getter != null) {
ReflectionUtils.makeAccessible(getter);
return getter.invoke(clazz);
}
return getStaticFieldValue(clazz, name);
}
catch (Exception ignored) {
}
return null;
}
/**
* Looks for a property of the reference instance with a given name.
* If found its value is returned. We follow the Java bean conventions with augmentation for groovy support
* and static fields/properties. We will therefore match, in this order:
*
*
* - Standard public bean property (with getter or just public field, using normal introspection)
*
- Public static property with getter method
*
- Public static field
*
*
* @return property value or null if no property found
*/
public static Object getPropertyOrStaticPropertyOrFieldValue(Object obj, String name) throws BeansException {
BeanWrapper ref = new BeanWrapperImpl(obj);
return getPropertyOrStaticPropertyOrFieldValue(ref, obj, name);
}
public static Object getPropertyOrStaticPropertyOrFieldValue(BeanWrapper ref, Object obj, String name) {
if (ref.isReadableProperty(name)) {
return ref.getPropertyValue(name);
}
// Look for public fields
if (isPublicField(obj, name)) {
return getFieldValue(obj, name);
}
// Look for statics
Class> clazz = obj.getClass();
if (isStaticProperty(clazz, name)) {
return getStaticPropertyValue(clazz, name);
}
return null;
}
/**
* Get the value of a declared field on an object
*
* @param obj
* @param name
* @return The object value or null if there is no such field or access problems
*/
public static Object getFieldValue(Object obj, String name) {
Class> clazz = obj.getClass();
try {
Field f = clazz.getDeclaredField(name);
return f.get(obj);
}
catch (Exception e) {
return null;
}
}
/**
* Work out if the specified object has a public field with the name supplied.
*
* @param obj
* @param name
* @return true if a public field with the name exists
*/
public static boolean isPublicField(Object obj, String name) {
Class> clazz = obj.getClass();
try {
Field f = clazz.getDeclaredField(name);
return Modifier.isPublic(f.getModifiers());
}
catch (NoSuchFieldException e) {
return false;
}
}
/**
* Checks whether the specified property is inherited from a super class
*
* @param clz The class to check
* @param propertyName The property name
* @return true if the property is inherited
*/
@SuppressWarnings("rawtypes")
public static boolean isPropertyInherited(Class clz, String propertyName) {
if (clz == null) {
return false;
}
Assert.isTrue(StringUtils.hasText(propertyName), "Argument [propertyName] cannot be null or blank");
Class> superClass = clz.getSuperclass();
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(superClass, propertyName);
if (pd != null && pd.getReadMethod() != null) {
return true;
}
return false;
}
/**
* Check whether the specified method is a property getter
*
* @param method The method
* @return true if the method is a property getter
*/
public static boolean isPropertyGetter(Method method) {
return !Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers()) &&
GrailsNameUtils.isGetter(method.getName(), method.getReturnType(), method.getParameterTypes());
}
/**
* Creates a concrete collection for the suppied interface
* @param interfaceType The interface
* @return ArrayList for List, TreeSet for SortedSet, HashSet for Set etc.
*/
@SuppressWarnings("rawtypes")
public static Collection createConcreteCollection(Class interfaceType) {
Collection elements;
if (interfaceType.equals(List.class) || interfaceType.equals(Collection.class)) {
elements = new ArrayList();
}
else if (interfaceType.equals(SortedSet.class)) {
elements = new TreeSet();
}
else {
elements = new HashSet();
}
return elements;
}
/**
* Returns true if the name of the method specified and the number of arguments make it a javabean property setter.
* The name is assumed to be a valid Java method name, that is not verified.
*
* @param name The name of the method
* @param args The arguments
* @return true if it is a javabean property setter
*/
@SuppressWarnings("rawtypes")
public static boolean isSetter(String name, Class[] args) {
if (!StringUtils.hasText(name) || args == null) {
return false;
}
if (name.startsWith("set")) {
if (args.length != 1) {
return false;
}
return GrailsNameUtils.isPropertyMethodSuffix(name.substring(3));
}
return false;
}
@SuppressWarnings("rawtypes")
public static MetaClass getExpandoMetaClass(Class clazz) {
MetaClassRegistry registry = GroovySystem.getMetaClassRegistry();
Assert.isTrue(registry.getMetaClassCreationHandler() instanceof ExpandoMetaClassCreationHandle,
"Grails requires an instance of [ExpandoMetaClassCreationHandle] to be set in Groovy's MetaClassRegistry! (current is : " +
registry.getMetaClassCreationHandler() + ")");
MetaClass mc = registry.getMetaClass(clazz);
AdaptingMetaClass adapter = null;
if (mc instanceof AdaptingMetaClass) {
adapter = (AdaptingMetaClass) mc;
mc = ((AdaptingMetaClass) mc).getAdaptee();
}
if (!(mc instanceof ExpandoMetaClass)) {
// removes cached version
registry.removeMetaClass(clazz);
mc = registry.getMetaClass(clazz);
if (adapter != null) {
adapter.setAdaptee(mc);
}
}
Assert.isTrue(mc instanceof ExpandoMetaClass, "BUG! Method must return an instance of [ExpandoMetaClass]!");
return mc;
}
/**
* Returns true if the specified clazz parameter is either the same as, or is a superclass or superinterface
* of, the specified type parameter. Converts primitive types to compatible class automatically.
*
* @param clazz
* @param type
* @return true if the class is a taglib
* @see java.lang.Class#isAssignableFrom(Class)
*/
public static boolean isAssignableOrConvertibleFrom(Class> clazz, Class> type) {
if (type == null || clazz == null) {
return false;
}
if (type.isPrimitive()) {
// convert primitive type to compatible class
Class> primitiveClass = GrailsClassUtils.PRIMITIVE_TYPE_COMPATIBLE_CLASSES.get(type);
if (primitiveClass == null) {
// no compatible class found for primitive type
return false;
}
return clazz.isAssignableFrom(primitiveClass);
}
return clazz.isAssignableFrom(type);
}
/**
* Retrieves a boolean value from a Map for the given key
*
* @param key The key that references the boolean value
* @param map The map to look in
* @return A boolean value which will be false if the map is null, the map doesn't contain the key or the value is false
*/
public static boolean getBooleanFromMap(String key, Map, ?> map) {
boolean defaultValue = false;
return getBooleanFromMap(key, map, defaultValue);
}
/**
* Retrieves a boolean value from a Map for the given key
*
* @param key The key that references the boolean value
* @param map The map to look in
* @return A boolean value which will be false if the map is null, the map doesn't contain the key or the value is false
*/
public static boolean getBooleanFromMap(String key, Map, ?> map, boolean defaultValue) {
if (map == null) {
return defaultValue;
}
if (map.containsKey(key)) {
Object o = map.get(key);
if (o == null) {
return defaultValue;
}
if (o instanceof Boolean) {
return (Boolean) o;
}
return Boolean.parseBoolean(o.toString());
}
return defaultValue;
}
/**
* Locates the name of a property for the given value on the target object using Groovy's meta APIs.
* Note that this method uses the reference so the incorrect result could be returned for two properties
* that refer to the same reference. Use with caution.
*
* @param target The target
* @param obj The property value
* @return The property name or null
*/
public static String findPropertyNameForValue(Object target, Object obj) {
MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(target.getClass());
List metaProperties = mc.getProperties();
for (MetaProperty metaProperty : metaProperties) {
if (isAssignableOrConvertibleFrom(metaProperty.getType(), obj.getClass())) {
Object val = metaProperty.getProperty(target);
if (val != null && val.equals(obj)) {
return metaProperty.getName();
}
}
}
return null;
}
/**
* Retrieves the name of a setter for the specified property name
* @param propertyName The property name
* @return The setter equivalent
*/
public static String getSetterName(String propertyName) {
return GrailsNameUtils.getSetterName(propertyName);
}
/**
* Returns true if the name of the method specified and the number of arguments make it a javabean property getter.
* The name is assumed to be a valid Java method name, that is not verified.
*
* @param name The name of the method
* @param args The arguments
* @return true if it is a javabean property getter
* @deprecated use {@link #isGetter(String, Class, Class[])} instead because this method has a defect for "is.." method with Boolean return types.
*/
@Deprecated
public static boolean isGetter(String name, Class>[] args) {
return GrailsNameUtils.isGetter(name, boolean.class, args);
}
/**
* Returns true if the name of the method specified and the number of arguments make it a javabean property getter.
* The name is assumed to be a valid Java method name, that is not verified.
*
* @param name The name of the method
* @param returnType The return type of the method
* @param args The arguments
* @return true if it is a javabean property getter
*/
public static boolean isGetter(String name, Class returnType, Class>[] args) {
return GrailsNameUtils.isGetter(name, returnType, args);
}
/**
* Returns a property name equivalent for the given getter name or null if it is not a valid getter. If not null
* or empty the getter name is assumed to be a valid identifier.
*
* @param getterName The getter name
* @return The property name equivalent
* @deprecated Use {@link #getPropertyForGetter(String, Class)} instead
* because this method has a defect for "is.." method with Boolean return types.
*/
@Deprecated
public static String getPropertyForGetter(String getterName) {
return GrailsNameUtils.getPropertyForGetter(getterName);
}
/**
* Returns a property name equivalent for the given getter name and return type or null if it is not a valid getter. If not null
* or empty the getter name is assumed to be a valid identifier.
*
* @param getterName The getter name
* @param returnType The type the method returns
* @return The property name equivalent
*/
public static String getPropertyForGetter(String getterName, Class returnType) {
return GrailsNameUtils.getPropertyForGetter(getterName, returnType);
}
/**
* Returns a property name equivalent for the given getter name and return type or null if it is not a valid getter. If not null
* or empty the getter name is assumed to be a valid identifier.
*
* @param getterName The getter name
* @param returnType The class name the method returns
* @return The property name equivalent
*/
public static String getPropertyForGetter(String getterName, String returnType) {
return GrailsNameUtils.getPropertyForGetter(getterName, returnType);
}
/**
* Returns a property name equivalent for the given setter name or null if it is not a valid setter. If not null
* or empty the setter name is assumed to be a valid identifier.
*
* @param setterName The setter name, must be null or empty or a valid identifier name
* @return The property name equivalent
*/
public static String getPropertyForSetter(String setterName) {
return GrailsNameUtils.getPropertyForSetter(setterName);
}
/**
* Returns whether the specified class is either within one of the specified packages or
* within a subpackage of one of the packages
*
* @param theClass The class
* @param packageList The list of packages
* @return true if it is within the list of specified packages
*/
public static boolean isClassBelowPackage(Class> theClass, List> packageList) {
String classPackage = theClass.getPackage().getName();
for (Object packageName : packageList) {
if (packageName != null) {
if (classPackage.startsWith(packageName.toString())) {
return true;
}
}
}
return false;
}
@SuppressWarnings("unchecked")
public static Object instantiateFromConfig(ConfigObject config, String configKey, String defaultClassName)
throws InstantiationException, IllegalAccessException, ClassNotFoundException,
LinkageError, InvocationTargetException, NoSuchMethodException {
return instantiateFromFlatConfig(config.flatten(), configKey, defaultClassName);
}
public static Object instantiateFromFlatConfig(Map flatConfig, String configKey, String defaultClassName)
throws InstantiationException, IllegalAccessException, ClassNotFoundException,
LinkageError, NoSuchMethodException, InvocationTargetException {
String className = defaultClassName;
Object configName = flatConfig.get(configKey);
if (configName instanceof CharSequence) {
className = configName.toString();
}
Class> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
return ReflectionUtils.accessibleConstructor(clazz).newInstance();
}
}