All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.exparity.stub.bean.BeanBuilder Maven / Gradle / Ivy

Go to download

A Java library to support creation of test stubs. The library can create complete object graphs populated completely randomly, or can be populated with a mix of random and configured values.

There is a newer version: 2.0.8
Show newest version
package org.exparity.stub.bean;

import static java.lang.System.identityHashCode;
import static org.apache.commons.lang.StringUtils.lowerCase;
import static org.exparity.beans.Type.type;
import static org.exparity.stub.core.ValueFactories.aNewInstanceOf;
import static org.exparity.stub.core.ValueFactories.aNullValue;
import static org.exparity.stub.core.ValueFactories.aRandomBoolean;
import static org.exparity.stub.core.ValueFactories.aRandomByte;
import static org.exparity.stub.core.ValueFactories.aRandomChar;
import static org.exparity.stub.core.ValueFactories.aRandomDate;
import static org.exparity.stub.core.ValueFactories.aRandomDecimal;
import static org.exparity.stub.core.ValueFactories.aRandomDouble;
import static org.exparity.stub.core.ValueFactories.aRandomEnum;
import static org.exparity.stub.core.ValueFactories.aRandomFloat;
import static org.exparity.stub.core.ValueFactories.aRandomInteger;
import static org.exparity.stub.core.ValueFactories.aRandomLong;
import static org.exparity.stub.core.ValueFactories.aRandomShort;
import static org.exparity.stub.core.ValueFactories.aRandomString;
import static org.exparity.stub.core.ValueFactories.oneOf;
import static org.exparity.stub.core.ValueFactories.theValue;

import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.exparity.beans.Type;
import org.exparity.beans.core.BeanNamingStrategy;
import org.exparity.beans.core.BeanPropertyPath;
import org.exparity.beans.core.TypeProperty;
import org.exparity.beans.core.naming.ForceRootNameNamingStrategy;
import org.exparity.beans.core.naming.LowerCaseNamingStrategy;
import org.exparity.stub.core.ValueFactory;
import org.exparity.stub.random.RandomBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Builder object for instantiating and populating objects which follow the Java
 * beans standards conventions for getter/setters
 * 
 * @author Stewart Bissett
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class BeanBuilder {

	private static final Logger LOG = LoggerFactory.getLogger(BeanBuilder.class);

	/**
	 * Return an instance of a {@link BeanBuilder} for the given type which can
	 * then be populated with values either manually or automatically. For
	 * example:
	 * 
	 * 
	 * 
	 * Person aPerson = BeanBuilder.anInstanceOf(Person.class)
	 * 		.path("person.firstName", "Bob")
	 * 		.build()
	 * 
* * @param type * the type to return the {@link BeanBuilder} for */ public static BeanBuilder anInstanceOf(final Class type) { return new BeanBuilder(type, BeanBuilderType.NULL, new LowerCaseNamingStrategy()); } /** * Return an instance of a {@link BeanBuilder} for the given type which can * then be populated with values either manually or automatically. For * example: * *
	 * Person aPerson = BeanBuilder.anInstanceOf(Person.class, "instance")
	 *                        .path("instance.firstName", "Bob")
	 *                        .build()
	 * 
* * @param type * the type to return the {@link BeanBuilder} for * @param rootName * the name give to the root entity when referencing paths */ public static BeanBuilder anInstanceOf(final Class type, final String rootName) { return new BeanBuilder(type, BeanBuilderType.NULL, new ForceRootNameNamingStrategy( new LowerCaseNamingStrategy(), rootName)); } /** * Return an instance of a {@link BeanBuilder} for the given type which is * populated with empty objects but collections, maps, etc which have empty * objects. For example: * *
	 * 
	 * Person aPerson = BeanBuilder.anEmptyInstanceOf(Person.class).path("person.firstName", "Bob").build();
	 * 
* * @param type * the type to return the {@link BeanBuilder} for */ public static BeanBuilder anEmptyInstanceOf(final Class type) { return new BeanBuilder(type, BeanBuilderType.EMPTY, new LowerCaseNamingStrategy()); } /** * Return an instance of a {@link BeanBuilder} for the given type which is * populated with empty objects but collections, maps, etc which have empty * objects. For example: * *
	 * Person aPerson = BeanBuilder.anEmptyInstanceOf(Person.class, "instance")
	 *                        .path("instance.firstName", "Bob")
	 *                        .build()
	 * 
* * @param type * the type to return the {@link BeanBuilder} for * @param rootName * the name give to the root entity when referencing paths */ public static BeanBuilder anEmptyInstanceOf(final Class type, final String rootName) { return new BeanBuilder(type, BeanBuilderType.EMPTY, new ForceRootNameNamingStrategy( new LowerCaseNamingStrategy(), rootName)); } /** * Return an instance of a {@link BeanBuilder} for the given type which is * populated with random values. For example: * *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 * 		.path("person.firstName", "Bob")
	 * 		.build()
	 * 
* * @param type * the type to return the {@link BeanBuilder} for */ public static BeanBuilder aRandomInstanceOf(final Class type) { return new BeanBuilder(type, BeanBuilderType.RANDOM, new LowerCaseNamingStrategy()); } /** * Return an instance of a {@link BeanBuilder} for the given type which is * populated with random values. For example: * *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class,"instance")
	 *                        .path("instance.firstName", "Bob")
	 *                        .build()
	 * 
* * @param type * the type to return the {@link BeanBuilder} for */ public static BeanBuilder aRandomInstanceOf(final Class type, final String rootName) { return new BeanBuilder(type, BeanBuilderType.RANDOM, new ForceRootNameNamingStrategy( new LowerCaseNamingStrategy(), rootName)); } private final Set excludedProperties = new HashSet(); private final Set excludedPaths = new HashSet(); private final Map paths = new HashMap(); private final Map properties = new HashMap(); private final Map, ValueFactory> types = new HashMap, ValueFactory>(); private final Class type; private final BeanBuilderType builderType; private final BeanNamingStrategy naming;; private CollectionSize defaultCollectionSize = new CollectionSize(1, 5); private final Map collectionSizeForPaths = new HashMap(); private final Map collectionSizeForProperties = new HashMap(); private BeanBuilder(final Class type, final BeanBuilderType builderType, final BeanNamingStrategy naming) { this.type = type; this.builderType = builderType; this.naming = naming; } /** * Configure the builder to populate the given property or path with the * supplied value. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .with("firstName", "Bob")
	 *                        .build()
	 * 
* * @param propertyOrPathName * the property or path name to set the value on * @param value * the value to assign the property or path */ public BeanBuilder with(final String propertyOrPathName, final Object value) { return with(propertyOrPathName, theValue(value)); } /** * Configure the builder to populate any properties of the given type with a * value created by the supplied value factory. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .with(Date.class, ValueFactories.oneOf(APR(5,1975), APR(5,1985)))
	 *                        .build()
	 * 
* * @param type * the type of property to use the factory for * @param factory * the factory to use to create the value */ public BeanBuilder with(final Class type, final ValueFactory factory) { this.types.put(type, factory); return this; } /** * Configure the builder to populate the given property or path with a value * created by the supplied value factory. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .with("firstName", ValueFactories.oneOf("Bob", "Alice"))
	 *                        .build()
	 * 
* * @param propertyOrPathName * the property or path name to set the value on * @param factory * the factory to use to create the value */ public BeanBuilder with(final String propertyOrPathName, final ValueFactory factory) { path(propertyOrPathName, factory); property(propertyOrPathName, factory); return this; } /** * Configure the builder to populate the given property with the supplied * value. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .property("firstName", "Bob")
	 *                        .build()
	 * 
* * @param propertyName * the property to set the value on * @param value * the value to assign the property */ public BeanBuilder property(final String propertyName, final Object value) { return property(propertyName, theValue(value)); } /** * Configure the builder to populate the given property with a value created * by the supplied value factory. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .property("firstName", ValueFactories.oneOf("Bob", "Alice"))
	 *                        .build()
	 * 
* * @param propertyName * the property to set the value on * @param factory * the factory to use to create the value */ public BeanBuilder property(final String propertyName, final ValueFactory factory) { properties.put(lowerCase(propertyName), factory); return this; } /** * Configure the builder to populate any properties of the given type with a * value created by the supplied value factory. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .factory(Date.class, ValueFactories.oneOf(APR(5,1975), APR(5,1985)))
	 *                        .build()
	 * 
* * @param type * the type of property to use the factory for * @param factory * the factory to use to create the value */ public BeanBuilder factory(final Class type, final ValueFactory factory) { types.put(type, factory); return this; } /** * Configure the builder to exclude the given property from being populated. * For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .excludeProperty("firstName")
	 *                        .build()
	 * 
* * @param propertyName * the property to exclude */ public BeanBuilder excludeProperty(final String propertyName) { this.excludedProperties.add(lowerCase(propertyName)); return this; } /** * Configure the builder to populate the given path with the supplied value. * For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .path("person.firstName", "Bob")
	 *                        .build()
	 * 
* * @param path * the path to set the value on * @param value * the value to assign the path */ public BeanBuilder path(final String path, final Object value) { return path(path, theValue(value)); } /** * Configure the builder to populate the given path with a value created by * the supplied value factory. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .path("person.firstName", ValueFactories.oneOf("Bob", "Alice"))
	 *                        .build()
	 * 
* * @param path * the path to set the value on * @param factory * the factory to use to create the value */ public BeanBuilder path(final String path, final ValueFactory factory) { this.paths.put(lowerCase(path), factory); return this; } /** * Configure the builder to exclude the given path from being populated. For * example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .excludeProperty("person.firstName")
	 *                        .build()
	 * 
* * @param path * the path to exclude */ public BeanBuilder excludePath(final String path) { this.excludedPaths.add(lowerCase(path)); return this; } /** * Configure the builder to set the size of a collections. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeOf(5)
	 *                        .build()
	 * 
* * @param size * the size to create the collections */ public BeanBuilder collectionSizeOf(final int size) { return collectionSizeRangeOf(size, size); } /** * Configure the builder to set the size of a collections to within a given * range. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeRangeOf(2,10)
	 *                        .build()
	 * 
* * @param min * the minimum size to create the collections * @param max * the maximum size to create the collections */ public BeanBuilder collectionSizeRangeOf(final int min, final int max) { this.defaultCollectionSize = new CollectionSize(min, max); return this; } /** * Configure the builder to set the size of a collection at a path to within * a given range. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeRangeForPropertyOf("sublings", 1,3)
	 *                        .build()
	 * 
* * @param property * the name of the property to limit the collection size of * @param min * the minimum size to create the collections * @param max * the maximum size to create the collections */ public BeanBuilder collectionSizeRangeForPropertyOf(final String property, final int min, final int max) { this.collectionSizeForProperties.put(property, new CollectionSize(min, max)); return this; } /** * Configure the builder to set the size of a collection at a path. For * example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeForPropertyOf("sublings", 3)
	 *                        .build()
	 * 
* * @param property * the name of the property to limit the collection size of * @param size * the size to create the collection */ public BeanBuilder collectionSizeForPropertyOf(final String property, final int size) { return collectionSizeRangeForPropertyOf(property, size, size); } /** * Configure the builder to set the size of a collection for a path to * within a given range. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeForPathOf("person.sublings", 1, 3)
	 *                        .build()
	 * 
* * @param path * the path to limit the collection size of * @param size * the size to create the collection */ public BeanBuilder collectionSizeForPathOf(final String path, final int size) { return collectionSizeRangeForPathOf(path, size, size); } /** * Configure the builder to set the size of a collection at a path to within * a given range. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .collectionSizeRangeForPathOf("person.siblings", 1,3)
	 *                        .build()
	 * 
* * @param path * the name of the path to limit the collection size of * @param min * the minimum size to create the collection * @param max * the maximum size to create the collection */ public BeanBuilder collectionSizeRangeForPathOf(final String path, final int min, final int max) { this.collectionSizeForPaths.put(path, new CollectionSize(min, max)); return this; } /** * Configure the builder to use a particular subtype when instantiating a * super type. For example

* *
	 * ShapeSorter aSorter = BeanBuilder.aRandomInstanceOf(ShapeSorter.class)
	 *                        .subtype(Shape.class, Square.class)
	 *                        .build()
	 * 
* * @param supertype * the type of the super type * @param subtype * the subtype to use when instantiating the super type */ public BeanBuilder subtype(final Class supertype, final Class subtype) { return with(supertype, oneOf(createInstanceOfFactoriesForTypes(subtype))); } /** * Configure the builder to use any of of a particular subtype when * instantiating a super type. For example

* *
	 * ShapeSorter aSorter = BeanBuilder.aRandomInstanceOf(ShapeSorter.class)
	 *                        .subtype(Shape.class, Square.class, Circle.class, Triangle.class)
	 *                        .build()
	 * 
* * @param supertype * the type of the super type * @param subtypes * the subtypes to pick from when instantiating the super type */ public BeanBuilder subtype(final Class supertype, final Class... subtypes) { return with(supertype, oneOf(createInstanceOfFactoriesForTypes(subtypes))); } /** * Build the configured instance. For example

* *
	 * Person aPerson = BeanBuilder.aRandomInstanceOf(Person.class)
	 *                        .path("person.firstName", "Bob")
	 *                        .path("person.age", oneOf(25,35))
	 *                        .build()
	 * 
*/ public T build() { return populate(createNewInstance(), new BeanPropertyPath(naming.describeRoot(type)), new Stack(type(type))); } private I populate(final I instance, final BeanPropertyPath path, final Stack stack) { if (instance != null) { for (TypeProperty property : type(instance, naming).propertyList()) { populateProperty(instance, property, path.append(property.getName()), stack); } return instance; } else { return instance; } } private void populateProperty(final Object instance, final TypeProperty property, final BeanPropertyPath path, final Stack stack) { if (isExcludedPath(path) || isExcludedProperty(property)) { LOG.trace("Ignore [{}]. Explicity excluded", path); return; } ValueFactory factory = factoryForPath(property, path); if (factory != null) { assignValue(instance, property, path, createValue(factory, type), stack); return; } if (isPropertySet(instance, property) || isChildOfAssignedPath(path) || isOverflowing(property, path, stack)) { return; } if (property.isArray()) { property.setValue(instance, createArray(property.getType().getComponentType(), path, stack)); } else { java.lang.reflect.Type[] params = property.getMutator().getGenericParameterTypes(); java.lang.reflect.Type firstParam = params[0]; Class typeParameter = getActualType(firstParam); if (property.isMap()) { property.setValue( instance, createMap(typeParameter, property.getTypeParameter(1), collectionSize(path), path, stack)); } else if (property.isSet()) { property.setValue(instance, createSet(typeParameter, collectionSize(path), path, stack)); } else if (property.isList() || property.isCollection()) { property.setValue(instance, createList(typeParameter, collectionSize(path), path, stack)); } else { assignValue(instance, property, path, createValue(property.getType()), stack); } } } private Class getActualType(java.lang.reflect.Type type) { if (type instanceof Class) { return (Class) type; } else if (type instanceof ParameterizedType) { return getActualType(((ParameterizedType) type).getActualTypeArguments()[0]); } else { throw new IllegalArgumentException("Unknown type subclass '" + type.getClass()); } } private boolean isPropertySet(final Object instance, final TypeProperty property) { if (property.getValue(instance) == null) { return false; } else if (property.isCollection()) { return !property.getValue(instance, Collection.class).isEmpty(); } else if (property.isMap()) { return !property.getValue(instance, Map.class).isEmpty(); } else { return true; } } private boolean isOverflowing(final TypeProperty property, final BeanPropertyPath path, final Stack stack) { if (stack.contains(property.getType())) { LOG.trace("Ignore {}. Avoids stack overflow caused by type {}", path, property.getTypeSimpleName()); return true; } for (Class genericType : property.getTypeParameters()) { if (stack.contains(genericType)) { LOG.trace("Ignore {}. Avoids stack overflow caused by type {}", path, genericType.getSimpleName()); return true; } } return false; } private ValueFactory factoryForPath(final TypeProperty property, final BeanPropertyPath path) { return selectNotNull( paths.get(path.fullPath()), paths.get(path.fullPathWithNoIndexes()), properties.get(property.getName())); } private boolean isExcludedProperty(final TypeProperty property) { return excludedProperties.contains(property.getName()); } private boolean isExcludedPath(final BeanPropertyPath path) { return excludedPaths.contains(path.fullPath()) || excludedPaths.contains(path.fullPathWithNoIndexes()); } private boolean isChildOfAssignedPath(final BeanPropertyPath path) { for (String assignedPath : paths.keySet()) { if (path.startsWith(assignedPath + ".")) { LOG.trace("Ignore {}. Child of assigned path {}", path, assignedPath); return true; } } return false; } private void assignValue(final Object instance, final TypeProperty property, final BeanPropertyPath path, final Object value, final Stack stack) { if (value != null) { LOG.trace("Assign {} value [{}:{}]", new Object[] { path, value.getClass().getSimpleName(), identityHashCode(value) }); property.setValue(instance, populate(value, path, stack.append(type(value)))); } else { LOG.trace("Assign {} value [null]", path); } } private E createValue(final Class type) { for (Entry, ValueFactory> keyedFactory : types.entrySet()) { if (type.isAssignableFrom(keyedFactory.getKey())) { ValueFactory factory = keyedFactory.getValue(); return (E) createValue(factory, type); } } switch (builderType) { case RANDOM: { ValueFactory factory = RANDOM_FACTORIES.get(type); if (factory != null) { return (E) createValue(factory, type); } else if (type.isEnum()) { return createValue(aRandomEnum(type), type); } else { return createValue(aNewInstanceOf(type), type); } } case EMPTY: { ValueFactory factory = EMPTY_FACTORIES.get(type); if (factory != null) { return (E) createValue(factory, type); } else if (type.isEnum()) { return null; } else { return createValue(aNewInstanceOf(type), type); } } default: return null; } } private E createValue(final ValueFactory factory, final Class type) { E value = factory != null ? factory.createValue() : null; LOG.trace("Create Value [{}] for Type [{}]", value, type(type).simpleName()); return value; } private Object createArray(final Class type, final BeanPropertyPath path, final Stack stack) { switch (builderType) { case EMPTY: case RANDOM: Object array = Array.newInstance(type, collectionSize(path)); for (int i = 0; i < Array.getLength(array); ++i) { Array.set(array, i, populate(createValue(type), path.appendIndex(i), stack.append(type))); } return array; default: return null; } } private Set createSet(final Class type, final int length, final BeanPropertyPath path, final Stack stack) { switch (builderType) { case EMPTY: case RANDOM: Set set = new HashSet(); for (int i = 0; i < length; ++i) { E value = populate(createValue(type), path.appendIndex(i), stack.append(type)); if (value != null) { set.add(value); } } return set; default: return null; } } private List createList(final Class type, final int length, final BeanPropertyPath path, final Stack stack) { switch (builderType) { case EMPTY: case RANDOM: List list = new ArrayList(); for (int i = 0; i < length; ++i) { E value = populate(createValue(type), path.appendIndex(i), stack.append(type)); if (value != null) { list.add(value); } } return list; default: return null; } } private Map createMap(final Class keyType, final Class valueType, final int length, final BeanPropertyPath path, final Stack stack) { switch (builderType) { case EMPTY: case RANDOM: Map map = new HashMap(); for (int i = 0; i < length; ++i) { K key = populate(createValue(keyType), path.appendIndex(i), stack.append(keyType).append(valueType)); if (key != null) { map.put(key, createValue(valueType)); } } return map; default: return null; } } private T createNewInstance() { try { return type.newInstance(); } catch (InstantiationException e) { throw new BeanBuilderException("Failed to instantiate '" + type + "'. Error [" + e.getMessage() + "]", e); } catch (IllegalAccessException e) { throw new BeanBuilderException("Failed to instantiate '" + type + "'. Error [" + e.getMessage() + "]", e); } } private int collectionSize(final BeanPropertyPath path) { return selectNotNull( collectionSizeForPaths.get(path.fullPath()), collectionSizeForPaths.get(path.fullPathWithNoIndexes()), collectionSizeForProperties.get(propertyName(path)), defaultCollectionSize).aRandomSize(); } private String propertyName(final BeanPropertyPath path) { return StringUtils.substringAfterLast(path.fullPathWithNoIndexes(), "."); } private List> createInstanceOfFactoriesForTypes(final Class... subtypes) { List> factories = new ArrayList>(); for (Class subtype : subtypes) { factories.add((ValueFactory) aNewInstanceOf(subtype)); } return factories; } private static class Stack { private final Type[] stack; private Stack(final Type type) { this(new Type[] { type }); } private Stack(final Type[] stack) { this.stack = stack; } public boolean contains(final Class type) { int hits = 0; for (Type entry : stack) { if (entry.is(type)) { if ((++hits) > 1) { return true; } } } return false; } public Stack append(final Class value) { return append(type(value)); } public Stack append(final Type value) { Type[] newStack = Arrays.copyOf(stack, stack.length + 1); newStack[stack.length] = value; return new Stack(newStack); } } private static class CollectionSize { private final int min, max; public CollectionSize(final int min, final int max) { this.min = min; this.max = max; } public int aRandomSize() { if (min == max) { return min; } else { return RandomBuilder.aRandomInteger(min, max); } } } @SuppressWarnings("serial") private static final Map, ValueFactory> RANDOM_FACTORIES = new HashMap, ValueFactory>() { { put(Short.class, aRandomShort()); put(short.class, aRandomShort()); put(Integer.class, aRandomInteger()); put(int.class, aRandomInteger()); put(Long.class, aRandomLong()); put(long.class, aRandomLong()); put(Double.class, aRandomDouble()); put(double.class, aRandomDouble()); put(Float.class, aRandomFloat()); put(float.class, aRandomFloat()); put(Boolean.class, aRandomBoolean()); put(boolean.class, aRandomBoolean()); put(Byte.class, aRandomByte()); put(byte.class, aRandomByte()); put(Character.class, aRandomChar()); put(char.class, aRandomChar()); put(String.class, aRandomString()); put(BigDecimal.class, aRandomDecimal()); put(Date.class, aRandomDate()); } }; private static final Map, ValueFactory> EMPTY_FACTORIES = new HashMap, ValueFactory>() { private static final long serialVersionUID = 1L; { put(Short.class, aNullValue()); put(short.class, theValue((short) 0)); put(Integer.class, aNullValue()); put(int.class, theValue(0)); put(Long.class, aNullValue()); put(long.class, theValue(0)); put(Double.class, aNullValue()); put(double.class, theValue(0.0)); put(Float.class, aNullValue()); put(float.class, theValue((float) 0.0)); put(Boolean.class, aNullValue()); put(boolean.class, theValue(false)); put(Byte.class, aNullValue()); put(byte.class, theValue((byte) 0)); put(Character.class, aNullValue()); put(char.class, theValue((char) 0)); put(String.class, aNullValue()); put(BigDecimal.class, aNullValue()); put(Date.class, aNullValue()); } }; private static enum BeanBuilderType { RANDOM, EMPTY, NULL } private O selectNotNull(final O... options) { for (O option : options) { if (option != null) { return option; } } return null; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy