Refactoring some code
This commit is contained in:
parent
25aba9758e
commit
cb03da8c67
6 changed files with 242 additions and 204 deletions
|
@ -24,7 +24,6 @@ import java.lang.reflect.Modifier;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -32,8 +31,7 @@ import java.util.Set;
|
|||
/**
|
||||
* Obtains all property descriptors from a bean (interface or implementation).
|
||||
* <p>
|
||||
* The java.beans.Introspector does not process the interfaces hierarchy chain,
|
||||
* this one does.
|
||||
* The java.beans.Introspector does not process the interfaces hierarchy chain, this one does.
|
||||
* <p>
|
||||
*
|
||||
* @author Alejandro Abdelnur
|
||||
|
@ -42,29 +40,98 @@ import java.util.Set;
|
|||
public class BeanIntrospector {
|
||||
|
||||
private static final Map<Class<?>, PropertyDescriptor[]> introspected = new HashMap<Class<?>, PropertyDescriptor[]>();
|
||||
private static final String SETTER = "set";
|
||||
private static final String GETTER = "get";
|
||||
private static final String BOOLEAN_GETTER = "is";
|
||||
|
||||
public static synchronized PropertyDescriptor[] getPropertyDescriptors(final Class<?> klass) throws IntrospectionException {
|
||||
PropertyDescriptor[] descriptors = introspected.get(klass);
|
||||
/**
|
||||
* Extract all {@link PropertyDescriptor}s for properties with getters and setters for the given class.
|
||||
*
|
||||
* @param clazz The class to extract the desired {@link PropertyDescriptor}s from
|
||||
* @return All {@link PropertyDescriptor} for properties with getters and setters for the given class.
|
||||
* @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s failed
|
||||
*/
|
||||
private static synchronized PropertyDescriptor[] getPropertyDescriptors(final Class<?> clazz) throws IntrospectionException {
|
||||
PropertyDescriptor[] descriptors = introspected.get(clazz);
|
||||
if (descriptors == null) {
|
||||
descriptors = getPDs(klass);
|
||||
introspected.put(klass, descriptors);
|
||||
descriptors = getPDs(clazz);
|
||||
introspected.put(clazz, descriptors);
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private static PropertyDescriptor[] getPDs(final Class<?> klass) throws IntrospectionException {
|
||||
final Method[] methods = klass.getMethods();
|
||||
final Map<String, PropertyDescriptor> getters = getPDs(methods, false);
|
||||
final Map<String, PropertyDescriptor> setters = getPDs(methods, true);
|
||||
final List<PropertyDescriptor> pds = merge(getters, setters);
|
||||
final PropertyDescriptor[] array = new PropertyDescriptor[pds.size()];
|
||||
pds.toArray(array);
|
||||
return array;
|
||||
/**
|
||||
* Extract all {@link PropertyDescriptor}s for properties with a getter that does not come from {@link Object} and does not accept parameters.
|
||||
*
|
||||
* @param clazz The class to extract the desired {@link PropertyDescriptor}s from
|
||||
* @return All {@link PropertyDescriptor}s for properties with a getter that does not come from {@link Object} and does not accept parameters.
|
||||
* @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s failed
|
||||
*/
|
||||
public static List<PropertyDescriptor> getPropertyDescriptorsWithGetters(final Class<?> clazz) throws IntrospectionException {
|
||||
|
||||
final List<PropertyDescriptor> relevantDescriptors = new ArrayList<PropertyDescriptor>();
|
||||
|
||||
final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
|
||||
if (propertyDescriptors != null) {
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final Method getter = propertyDescriptor.getReadMethod();
|
||||
final boolean getterExists = getter != null;
|
||||
|
||||
if (getterExists) {
|
||||
|
||||
final boolean getterFromObject = getter.getDeclaringClass() == Object.class;
|
||||
final boolean getterWithoutParams = getter.getParameterTypes().length == 0;
|
||||
|
||||
if (!getterFromObject && getterWithoutParams) {
|
||||
relevantDescriptors.add(propertyDescriptor);
|
||||
}
|
||||
|
||||
private static final String SETTER = "set";
|
||||
private static final String GETTER = "get";
|
||||
private static final String BOOLEAN_GETTER = "is";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return relevantDescriptors;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all {@link PropertyDescriptor}s for properties with a getter (that does not come from {@link Object} and does not accept parameters) and a
|
||||
* setter.
|
||||
*
|
||||
* @param clazz The class to extract the desired {@link PropertyDescriptor}s from
|
||||
* @return All {@link PropertyDescriptor}s for properties with a getter (that does not come from {@link Object} and does not accept parameters) and a
|
||||
* setter.
|
||||
* @throws IntrospectionException When the extraction of the desired {@link PropertyDescriptor}s failed
|
||||
*/
|
||||
public static List<PropertyDescriptor> getPropertyDescriptorsWithGettersAndSetters(final Class<?> clazz) throws IntrospectionException {
|
||||
|
||||
final List<PropertyDescriptor> relevantDescriptors = new ArrayList<PropertyDescriptor>();
|
||||
|
||||
final List<PropertyDescriptor> propertyDescriptors = getPropertyDescriptorsWithGetters(clazz);
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final Method setter = propertyDescriptor.getWriteMethod();
|
||||
final boolean setterExists = setter != null;
|
||||
|
||||
if (setterExists) {
|
||||
relevantDescriptors.add(propertyDescriptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return relevantDescriptors;
|
||||
|
||||
}
|
||||
|
||||
private static PropertyDescriptor[] getPDs(final Class<?> clazz) throws IntrospectionException {
|
||||
final Method[] methods = clazz.getMethods();
|
||||
final Map<String, PropertyDescriptor> getters = getPDs(methods, false);
|
||||
final Map<String, PropertyDescriptor> setters = getPDs(methods, true);
|
||||
final List<PropertyDescriptor> propertyDescriptors = merge(getters, setters);
|
||||
return propertyDescriptors.toArray(new PropertyDescriptor[propertyDescriptors.size()]);
|
||||
}
|
||||
|
||||
private static Map<String, PropertyDescriptor> getPDs(final Method[] methods, final boolean setters) throws IntrospectionException {
|
||||
final Map<String, PropertyDescriptor> pds = new HashMap<String, PropertyDescriptor>();
|
||||
|
@ -96,29 +163,30 @@ public class BeanIntrospector {
|
|||
|
||||
private static List<PropertyDescriptor> merge(final Map<String, PropertyDescriptor> getters, final Map<String, PropertyDescriptor> setters)
|
||||
throws IntrospectionException {
|
||||
|
||||
final List<PropertyDescriptor> props = new ArrayList<PropertyDescriptor>();
|
||||
final Set<String> processedProps = new HashSet<String>();
|
||||
final Iterator<String> gs = getters.keySet().iterator();
|
||||
while (gs.hasNext()) {
|
||||
final String name = gs.next();
|
||||
final PropertyDescriptor getter = getters.get(name);
|
||||
final PropertyDescriptor setter = setters.get(name);
|
||||
|
||||
for (final String propertyName : getters.keySet()) {
|
||||
final PropertyDescriptor getter = getters.get(propertyName);
|
||||
final PropertyDescriptor setter = setters.get(propertyName);
|
||||
if (setter != null) {
|
||||
processedProps.add(name);
|
||||
final PropertyDescriptor prop = new PropertyDescriptor(name, getter.getReadMethod(), setter.getWriteMethod());
|
||||
processedProps.add(propertyName);
|
||||
final PropertyDescriptor prop = new PropertyDescriptor(propertyName, getter.getReadMethod(), setter.getWriteMethod());
|
||||
props.add(prop);
|
||||
} else {
|
||||
props.add(getter);
|
||||
}
|
||||
}
|
||||
final Set<String> writeOnlyProps = new HashSet<String>(setters.keySet());
|
||||
writeOnlyProps.removeAll(processedProps);
|
||||
final Iterator<String> ss = writeOnlyProps.iterator();
|
||||
while (ss.hasNext()) {
|
||||
final String name = ss.next();
|
||||
final PropertyDescriptor setter = setters.get(name);
|
||||
|
||||
final Set<String> writeOnlyProperties = new HashSet<String>();
|
||||
writeOnlyProperties.removeAll(processedProps);
|
||||
|
||||
for (final String propertyName : writeOnlyProperties) {
|
||||
final PropertyDescriptor setter = setters.get(propertyName);
|
||||
props.add(setter);
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Collection;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
@ -162,35 +163,27 @@ public class CloneableBean implements Serializable, Cloneable {
|
|||
|
||||
final Object clonedBean = clazz.newInstance();
|
||||
|
||||
final PropertyDescriptor[] propertyDescriptors = BeanIntrospector.getPropertyDescriptors(clazz);
|
||||
if (propertyDescriptors != null) {
|
||||
final List<PropertyDescriptor> propertyDescriptors = BeanIntrospector.getPropertyDescriptorsWithGettersAndSetters(clazz);
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final String propertyName = propertyDescriptor.getName();
|
||||
|
||||
final boolean ignoredProperty = ignoreProperties.contains(propertyName);
|
||||
|
||||
if (!ignoredProperty) {
|
||||
|
||||
final Method getter = propertyDescriptor.getReadMethod();
|
||||
final Method setter = propertyDescriptor.getWriteMethod();
|
||||
final String propertyName = propertyDescriptor.getName();
|
||||
|
||||
final boolean getterExists = getter != null;
|
||||
final boolean setterExists = setter != null;
|
||||
final boolean ignoredProperty = ignoreProperties.contains(propertyName);
|
||||
|
||||
if (getterExists && setterExists && !ignoredProperty) {
|
||||
|
||||
final boolean getterFromObject = getter.getDeclaringClass() == Object.class;
|
||||
final boolean getterWithoutParams = getter.getParameterTypes().length == 0;
|
||||
|
||||
if (!getterFromObject && getterWithoutParams) {
|
||||
Object value = getter.invoke(obj, NO_PARAMS);
|
||||
if (value != null) {
|
||||
value = doClone(value);
|
||||
setter.invoke(clonedBean, new Object[] { value });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return clonedBean;
|
||||
|
||||
|
|
|
@ -26,22 +26,43 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.sun.syndication.feed.CopyFrom;
|
||||
|
||||
/**
|
||||
* @author Alejandro Abdelnur
|
||||
*/
|
||||
public class CopyFromHelper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CopyFromHelper.class);
|
||||
|
||||
private static final Set<Class<?>> BASIC_TYPES = new HashSet<Class<?>>();
|
||||
private static final Object[] NO_PARAMS = new Object[0];
|
||||
|
||||
private final Class<? extends CopyFrom<?>> beanInterfaceClass;
|
||||
private final Map<String, Class<?>> baseInterfaceMap; // ENTRIES(propertyName,interface.class)
|
||||
private final Map<Class<? extends CopyFrom<?>>, Class<?>> baseImplMap; // ENTRIES(interface.class,implementation.class)
|
||||
|
||||
static {
|
||||
BASIC_TYPES.add(Boolean.class);
|
||||
BASIC_TYPES.add(Byte.class);
|
||||
BASIC_TYPES.add(Character.class);
|
||||
BASIC_TYPES.add(Double.class);
|
||||
BASIC_TYPES.add(Float.class);
|
||||
BASIC_TYPES.add(Integer.class);
|
||||
BASIC_TYPES.add(Long.class);
|
||||
BASIC_TYPES.add(Short.class);
|
||||
BASIC_TYPES.add(String.class);
|
||||
BASIC_TYPES.add(Date.class);
|
||||
}
|
||||
|
||||
public CopyFromHelper(final Class<? extends CopyFrom<?>> beanInterfaceClass, final Map<String, Class<?>> basePropInterfaceMap,
|
||||
final Map<Class<? extends CopyFrom<?>>, Class<?>> basePropClassImplMap) {
|
||||
this.beanInterfaceClass = beanInterfaceClass;
|
||||
|
@ -50,47 +71,37 @@ public class CopyFromHelper {
|
|||
}
|
||||
|
||||
public void copy(final Object target, final Object source) {
|
||||
|
||||
try {
|
||||
final PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(beanInterfaceClass);
|
||||
if (pds != null) {
|
||||
for (final PropertyDescriptor pd : pds) {
|
||||
final String propertyName = pd.getName();
|
||||
final Method pReadMethod = pd.getReadMethod();
|
||||
final Method pWriteMethod = pd.getWriteMethod();
|
||||
if (pReadMethod != null && pWriteMethod != null && // ensure
|
||||
// it has
|
||||
// getter
|
||||
// and
|
||||
// setter
|
||||
// methods
|
||||
pReadMethod.getDeclaringClass() != Object.class && // filter
|
||||
// Object.class
|
||||
// getter
|
||||
// methods
|
||||
pReadMethod.getParameterTypes().length == 0 && // filter
|
||||
// getter
|
||||
// methods
|
||||
// that
|
||||
// take
|
||||
// parameters
|
||||
baseInterfaceMap.containsKey(propertyName)) { // only
|
||||
// copies
|
||||
// properties
|
||||
// defined
|
||||
// as
|
||||
// copyFrom-able
|
||||
Object value = pReadMethod.invoke(source, NO_PARAMS);
|
||||
|
||||
final List<PropertyDescriptor> propertyDescriptors = BeanIntrospector.getPropertyDescriptorsWithGettersAndSetters(beanInterfaceClass);
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final String propertyName = propertyDescriptor.getName();
|
||||
|
||||
if (baseInterfaceMap.containsKey(propertyName)) {
|
||||
|
||||
final Method getter = propertyDescriptor.getReadMethod();
|
||||
|
||||
// only copies properties defined as copyFrom-able
|
||||
Object value = getter.invoke(source, NO_PARAMS);
|
||||
if (value != null) {
|
||||
|
||||
final Method setter = propertyDescriptor.getWriteMethod();
|
||||
|
||||
final Class<?> baseInterface = baseInterfaceMap.get(propertyName);
|
||||
value = doCopy(value, baseInterface);
|
||||
pWriteMethod.invoke(target, new Object[] { value });
|
||||
setter.invoke(target, new Object[] { value });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Error while copying object", e);
|
||||
throw new RuntimeException("Could not do a copyFrom " + e, e);
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException("Could not do a copyFrom " + ex, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CopyFrom<?> createInstance(final Class<? extends CopyFrom<?>> interfaceClass) throws Exception {
|
||||
|
@ -170,21 +181,6 @@ public class CopyFromHelper {
|
|||
return newMap;
|
||||
}
|
||||
|
||||
private static final Set<Class<?>> BASIC_TYPES = new HashSet<Class<?>>();
|
||||
|
||||
static {
|
||||
BASIC_TYPES.add(Boolean.class);
|
||||
BASIC_TYPES.add(Byte.class);
|
||||
BASIC_TYPES.add(Character.class);
|
||||
BASIC_TYPES.add(Double.class);
|
||||
BASIC_TYPES.add(Float.class);
|
||||
BASIC_TYPES.add(Integer.class);
|
||||
BASIC_TYPES.add(Long.class);
|
||||
BASIC_TYPES.add(Short.class);
|
||||
BASIC_TYPES.add(String.class);
|
||||
BASIC_TYPES.add(Date.class);
|
||||
}
|
||||
|
||||
private boolean isBasicType(final Class<?> vClass) {
|
||||
return BASIC_TYPES.contains(vClass);
|
||||
}
|
||||
|
|
|
@ -20,23 +20,22 @@ import java.beans.PropertyDescriptor;
|
|||
import java.io.Serializable;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides deep <b>Bean</b> equals() and hashCode() functionality for Java
|
||||
* Beans.
|
||||
* Provides deep <b>Bean</b> equals() and hashCode() functionality for Java Beans.
|
||||
* <p>
|
||||
* It works on all read/write properties, recursively. It support all primitive
|
||||
* types, Strings, Collections, bean-like objects and multi-dimensional arrays
|
||||
* of any of them.
|
||||
* It works on all read/write properties, recursively. It support all primitive types, Strings, Collections, bean-like objects and multi-dimensional arrays of
|
||||
* any of them.
|
||||
* <p>
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String
|
||||
* representation.
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String representation.
|
||||
* <p>
|
||||
*
|
||||
* @author Alejandro Abdelnur
|
||||
*
|
||||
*/
|
||||
public class EqualsBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 9120107899175152601L;
|
||||
|
||||
private static final Object[] NO_PARAMS = new Object[0];
|
||||
|
@ -96,12 +95,10 @@ public class EqualsBean implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this object as defined
|
||||
* by the Object equals() method.
|
||||
* Indicates whether some other object is "equal to" this object as defined by the Object equals() method.
|
||||
* <p>
|
||||
* To be used by classes extending EqualsBean. Although it works also for
|
||||
* classes using EqualsBean in a delegation pattern, for correctness those
|
||||
* classes should use the
|
||||
* To be used by classes extending EqualsBean. Although it works also for classes using EqualsBean in a delegation pattern, for correctness those classes
|
||||
* should use the
|
||||
*
|
||||
* @see #beanEquals(Object) beanEquals method.
|
||||
* <p>
|
||||
|
@ -115,58 +112,53 @@ public class EqualsBean implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" the object passed in
|
||||
* the constructor, as defined by the Object equals() method.
|
||||
* Indicates whether some other object is "equal to" the object passed in the constructor, as defined by the Object equals() method.
|
||||
* <p>
|
||||
* To be used by classes using EqualsBean in a delegation pattern,
|
||||
*
|
||||
* @see #EqualsBean(Class,Object) constructor.
|
||||
* <p>
|
||||
* @param obj he reference object with which to compare.
|
||||
* @return <b>true</b> if the object passed in the constructor is equal to
|
||||
* the 'obj' object.
|
||||
* @return <b>true</b> if the object passed in the constructor is equal to the 'obj' object.
|
||||
*
|
||||
*/
|
||||
public boolean beanEquals(final Object obj) {
|
||||
|
||||
final Object bean1 = this.obj;
|
||||
final Object bean2 = obj;
|
||||
|
||||
boolean eq;
|
||||
if (bean1 == null && bean2 == null) {
|
||||
|
||||
if (bean1 == null && bean2 == null) { // both are null
|
||||
eq = true;
|
||||
} else if (bean1 == null || bean2 == null) {
|
||||
} else if (bean1 == null || bean2 == null) { // one of the objects is null
|
||||
eq = false;
|
||||
} else {
|
||||
if (!beanClass.isInstance(bean2)) {
|
||||
} else if (!beanClass.isInstance(bean2)) { // not of the same type
|
||||
eq = false;
|
||||
} else {
|
||||
eq = true;
|
||||
try {
|
||||
final PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(beanClass);
|
||||
if (pds != null) {
|
||||
for (int i = 0; eq && i < pds.length; i++) {
|
||||
final Method pReadMethod = pds[i].getReadMethod();
|
||||
if (pReadMethod != null && // ensure it has a getter
|
||||
// method
|
||||
pReadMethod.getDeclaringClass() != Object.class && // filter
|
||||
// Object.class
|
||||
// getter
|
||||
// methods
|
||||
pReadMethod.getParameterTypes().length == 0) { // filter
|
||||
// getter
|
||||
// methods
|
||||
// that
|
||||
// take
|
||||
// parameters
|
||||
final Object value1 = pReadMethod.invoke(bean1, NO_PARAMS);
|
||||
final Object value2 = pReadMethod.invoke(bean2, NO_PARAMS);
|
||||
|
||||
final List<PropertyDescriptor> propertyDescriptors = BeanIntrospector.getPropertyDescriptorsWithGetters(beanClass);
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final Method getter = propertyDescriptor.getReadMethod();
|
||||
|
||||
final Object value1 = getter.invoke(bean1, NO_PARAMS);
|
||||
final Object value2 = getter.invoke(bean2, NO_PARAMS);
|
||||
|
||||
eq = doEquals(value1, value2);
|
||||
|
||||
if (!eq) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (final Exception ex) {
|
||||
throw new RuntimeException("Could not execute equals()", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
|
@ -176,12 +168,10 @@ public class EqualsBean implements Serializable {
|
|||
* <p>
|
||||
* It follows the contract defined by the Object hashCode() method.
|
||||
* <p>
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String
|
||||
* representation.
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String representation.
|
||||
* <p>
|
||||
* To be used by classes extending EqualsBean. Although it works also for
|
||||
* classes using EqualsBean in a delegation pattern, for correctness those
|
||||
* classes should use the
|
||||
* To be used by classes extending EqualsBean. Although it works also for classes using EqualsBean in a delegation pattern, for correctness those classes
|
||||
* should use the
|
||||
*
|
||||
* @see #beanHashCode() beanHashCode method.
|
||||
* <p>
|
||||
|
@ -198,8 +188,7 @@ public class EqualsBean implements Serializable {
|
|||
* <p>
|
||||
* It follows the contract defined by the Object hashCode() method.
|
||||
* <p>
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String
|
||||
* representation.
|
||||
* The hashcode is calculated by getting the hashcode of the Bean String representation.
|
||||
* <p>
|
||||
* To be used by classes using EqualsBean in a delegation pattern,
|
||||
*
|
||||
|
|
|
@ -20,21 +20,17 @@ import java.io.Serializable;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Convenience class providing clone(), toString(), equals() and hashCode()
|
||||
* functionality for Java Beans.
|
||||
* Convenience class providing clone(), toString(), equals() and hashCode() functionality for Java Beans.
|
||||
* <p>
|
||||
* It works on all read/write properties, recursively.
|
||||
* <p>
|
||||
* It uses the CloneableBean, EqualsBean and ToStringBean classes in a
|
||||
* delegation pattern.
|
||||
* It uses the CloneableBean, EqualsBean and ToStringBean classes in a delegation pattern.
|
||||
* <p>
|
||||
* <h3>ObjectBean programming conventions</h3>
|
||||
* <P>
|
||||
* All ObjectBean subclasses having properties that return collections they
|
||||
* should never return null if the property has been set to <b>null</b> or if a
|
||||
* collection has not been set. They should create and return an empty
|
||||
* collection, this empty collection instance should also be set to the
|
||||
* corresponding property.
|
||||
* All ObjectBean subclasses having properties that return collections they should never return null if the property has been set to <b>null</b> or if a
|
||||
* collection has not been set. They should create and return an empty collection, this empty collection instance should also be set to the corresponding
|
||||
* property.
|
||||
* <P>
|
||||
* All ObjectBean subclasses properties should be live references.
|
||||
* <p>
|
||||
|
@ -43,7 +39,9 @@ import java.util.Set;
|
|||
*
|
||||
*/
|
||||
public class ObjectBean implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = -8784981605711980095L;
|
||||
|
||||
private final EqualsBean equalsBean;
|
||||
private final ToStringBean toStringBean;
|
||||
private final CloneableBean cloneableBean;
|
||||
|
@ -62,13 +60,9 @@ public class ObjectBean implements Serializable, Cloneable {
|
|||
/**
|
||||
* Constructor.
|
||||
* <p>
|
||||
* The property names in the ignoreProperties Set will not be copied into
|
||||
* the cloned instance. This is useful for cases where the Bean has
|
||||
* convenience properties (properties that are actually references to other
|
||||
* properties or properties of properties). For example SyndFeed and
|
||||
* SyndEntry beans have convenience properties, publishedDate, author,
|
||||
* copyright and categories all of them mapped to properties in the DC
|
||||
* Module.
|
||||
* The property names in the ignoreProperties Set will not be copied into the cloned instance. This is useful for cases where the Bean has convenience
|
||||
* properties (properties that are actually references to other properties or properties of properties). For example SyndFeed and SyndEntry beans have
|
||||
* convenience properties, publishedDate, author, copyright and categories all of them mapped to properties in the DC Module.
|
||||
* <p>
|
||||
*
|
||||
* @param beanClass the class/interface to be used for property scanning.
|
||||
|
@ -86,8 +80,7 @@ public class ObjectBean implements Serializable, Cloneable {
|
|||
* <p>
|
||||
*
|
||||
* @return a clone of the object.
|
||||
* @throws CloneNotSupportedException thrown if an element of the object
|
||||
* cannot be cloned.
|
||||
* @throws CloneNotSupportedException thrown if an element of the object cannot be cloned.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
|
@ -96,8 +89,7 @@ public class ObjectBean implements Serializable, Cloneable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this one as defined by
|
||||
* the Object equals() method.
|
||||
* Indicates whether some other object is "equal to" this one as defined by the Object equals() method.
|
||||
* <p>
|
||||
*
|
||||
* @param other he reference object with which to compare.
|
||||
|
|
|
@ -22,15 +22,18 @@ import java.lang.reflect.Array;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Provides deep <b>Bean</b> toString support.
|
||||
* <p>
|
||||
* It works on all read/write properties, recursively. It support all primitive
|
||||
* types, Strings, Collections, ToString objects and multi-dimensional arrays of
|
||||
* It works on all read/write properties, recursively. It support all primitive types, Strings, Collections, ToString objects and multi-dimensional arrays of
|
||||
* any of them.
|
||||
* <p>
|
||||
*
|
||||
|
@ -38,7 +41,9 @@ import java.util.Stack;
|
|||
*
|
||||
*/
|
||||
public class ToStringBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5850496718959612854L;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ToStringBean.class);
|
||||
|
||||
private static final ThreadLocal<Stack<String[]>> PREFIX_TL = new ThreadLocal<Stack<String[]>>() {
|
||||
@Override
|
||||
|
@ -63,8 +68,7 @@ public class ToStringBean implements Serializable {
|
|||
* To be used by classes extending ToStringBean only.
|
||||
* <p>
|
||||
*
|
||||
* @param beanClass indicates the class to scan for properties, normally an
|
||||
* interface class.
|
||||
* @param beanClass indicates the class to scan for properties, normally an interface class.
|
||||
*
|
||||
*/
|
||||
protected ToStringBean(final Class<?> beanClass) {
|
||||
|
@ -93,8 +97,7 @@ public class ToStringBean implements Serializable {
|
|||
* </code>
|
||||
* <p>
|
||||
*
|
||||
* @param beanClass indicates the class to scan for properties, normally an
|
||||
* interface class.
|
||||
* @param beanClass indicates the class to scan for properties, normally an interface class.
|
||||
* @param obj object bean to create String representation.
|
||||
*
|
||||
*/
|
||||
|
@ -141,32 +144,29 @@ public class ToStringBean implements Serializable {
|
|||
*
|
||||
*/
|
||||
private String toString(final String prefix) {
|
||||
|
||||
final StringBuffer sb = new StringBuffer(128);
|
||||
|
||||
try {
|
||||
final PropertyDescriptor[] pds = BeanIntrospector.getPropertyDescriptors(beanClass);
|
||||
if (pds != null) {
|
||||
for (final PropertyDescriptor pd : pds) {
|
||||
final String pName = pd.getName();
|
||||
final Method pReadMethod = pd.getReadMethod();
|
||||
if (pReadMethod != null && // ensure it has a getter method
|
||||
pReadMethod.getDeclaringClass() != Object.class && // filter
|
||||
// Object.class
|
||||
// getter
|
||||
// methods
|
||||
pReadMethod.getParameterTypes().length == 0) { // filter
|
||||
// getter
|
||||
// methods
|
||||
// that
|
||||
// take
|
||||
// parameters
|
||||
final Object value = pReadMethod.invoke(obj, NO_PARAMS);
|
||||
printProperty(sb, prefix + "." + pName, value);
|
||||
|
||||
final List<PropertyDescriptor> propertyDescriptors = BeanIntrospector.getPropertyDescriptorsWithGetters(beanClass);
|
||||
for (final PropertyDescriptor propertyDescriptor : propertyDescriptors) {
|
||||
|
||||
final String propertyName = propertyDescriptor.getName();
|
||||
final Method getter = propertyDescriptor.getReadMethod();
|
||||
|
||||
final Object value = getter.invoke(obj, NO_PARAMS);
|
||||
printProperty(sb, prefix + "." + propertyName, value);
|
||||
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
LOG.error("Error while generating toString", e);
|
||||
final Class<? extends Object> clazz = obj.getClass();
|
||||
final String errorMessage = e.getMessage();
|
||||
sb.append(String.format("\n\nEXCEPTION: Could not complete %s.toString(): %s\n", clazz, errorMessage));
|
||||
}
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
sb.append("\n\nEXCEPTION: Could not complete " + obj.getClass() + ".toString(): " + ex.getMessage() + "\n");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue