001: package com.bm.utils;
002:
003: import java.lang.reflect.Field;
004: import java.util.ArrayList;
005: import java.util.Arrays;
006: import java.util.Date;
007: import java.util.HashSet;
008: import java.util.List;
009: import java.util.Set;
010:
011: import junit.framework.Assert;
012:
013: import com.bm.datagen.utils.BaseRandomDataGenerator;
014: import com.bm.introspectors.Property;
015:
016: /**
017: * This class tests simple Bean-Classes automatically. Every Bean class must
018: * have a parameterless constructor. We are using a random data generator
019: * automatically generate N beans.
020: *
021: * @author Daniel Wiese
022: * @since 09.02.2006
023: */
024: public final class AutomaticBeanEqualsTester extends Assert {
025:
026: /**
027: * Executes the automatic eauals test.
028: *
029: * @author Daniel Wiese
030: * @since 09.02.2006
031: * @param <T> -
032: * the type of the bean
033: * @param beanToTest -
034: * the class of the bean
035: * @param keyProperties -
036: * the names of the key properties, which are important for equal
037: */
038: public static <T> void assertEqualsImplementation(
039: Class<? extends T> beanToTest, String... keyProperties) {
040: final List<Property> fields = getClassKeyProperties(beanToTest,
041: keyProperties);
042: final Object[] lastGeneratedValues = new Object[fields.size()];
043: for (int i = 0; i < 50; i++) {
044: try {
045: final T instance = beanToTest.newInstance();
046: // set the key properties randomly
047: for (int j = 0; j < fields.size(); j++) {
048: final Property current = fields.get(j);
049: lastGeneratedValues[j] = setRandomValue(instance,
050: current);
051: }
052: // create equal clone
053: final T cloneInstance = beanToTest.newInstance();
054: copyProperties(cloneInstance, fields,
055: lastGeneratedValues);
056:
057: // now change k times exactly one property value (k=key property
058: // size)
059: for (int k = 0; k < fields.size(); k++) {
060: final T differentInstance = beanToTest
061: .newInstance();
062: copyProperties(differentInstance, fields,
063: lastGeneratedValues);
064: changeOnePropertyValue(differentInstance,
065: lastGeneratedValues, fields, k);
066:
067: // NOW DO THE MAIN EQUALS TEST
068: new EqualsTester(instance, cloneInstance,
069: differentInstance, null, false);
070: }
071:
072: } catch (InstantiationException e) {
073: fail("Canīt instatiate bean :" + e.getMessage());
074: } catch (IllegalAccessException e) {
075: fail("Canīt instatiate bean :" + e.getMessage());
076: }
077: }
078:
079: }
080:
081: private static <T> void copyProperties(T cloneInstance,
082: List<Property> fields, Object[] lastGeneratedValues) {
083: for (int j = 0; j < fields.size(); j++) {
084: final Property current = fields.get(j);
085: try {
086: current.setField(cloneInstance, lastGeneratedValues[j]);
087: } catch (IllegalAccessException e) {
088: fail("Cant set the value (" + lastGeneratedValues[j]
089: + ") of property (" + current + ")");
090: }
091: }
092: }
093:
094: private static <T> void changeOnePropertyValue(T differentInstance,
095: Object[] lastGeneratedValues, List<Property> fields,
096: int indexToChange) {
097: // try to change 100 times (100 random values) and hope one is different
098: boolean changeSuccessfull = false;
099: for (int i = 0; i < 100; i++) {
100: final Property current = fields.get(indexToChange);
101: final Object newValue = setRandomValue(differentInstance,
102: current);
103: if (!newValue.equals(lastGeneratedValues[indexToChange])) {
104: changeSuccessfull = true;
105: break;
106: }
107: }
108:
109: if (!changeSuccessfull) {
110: fail("Canīt generate a object with one different value");
111: }
112:
113: }
114:
115: private static <T> List<Property> getClassKeyProperties(
116: Class<? extends T> beanToTest, String... keyProperties) {
117: final Set<String> propertiesSet = new HashSet<String>(Arrays
118: .asList(keyProperties));
119: final List<Property> back = new ArrayList<Property>();
120: Field[] fields = Ejb3Utils.getAllFields(beanToTest);
121: for (Field current : fields) {
122: final String name = current.getName();
123: if (propertiesSet.contains(name)) {
124: // the field is a key property
125: Property toAdd = new Property(current);
126: back.add(toAdd);
127: }
128: }
129: return back;
130: }
131:
132: private static <T> Object setRandomValue(T instance,
133: Property forField) {
134: Object back = null;
135: if (Ejb3Utils.getNonPrimitiveType(forField) == String.class) {
136: back = BaseRandomDataGenerator.getValueString(255, false);
137: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Date.class) {
138: back = BaseRandomDataGenerator.getValueDate();
139: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Boolean.class) {
140: back = BaseRandomDataGenerator.getValueBoolean();
141: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Character.class) {
142: back = BaseRandomDataGenerator.getValueChar();
143: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Double.class) {
144: back = BaseRandomDataGenerator.getValueDouble();
145: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Float.class) {
146: back = BaseRandomDataGenerator.getValueFloat();
147: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Integer.class) {
148: back = BaseRandomDataGenerator.getValueInt();
149: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Long.class) {
150: back = BaseRandomDataGenerator.getValueLong();
151: } else if (Ejb3Utils.getNonPrimitiveType(forField) == Short.class) {
152: back = BaseRandomDataGenerator.getValueShort();
153: }
154:
155: if (back != null) {
156: try {
157: forField.setField(instance, back);
158: } catch (IllegalAccessException e) {
159: fail("Cant set the random value (" + back
160: + ") of property (" + forField + ")");
161: }
162: } else {
163: // back is null
164: fail("Cant create bean instance, because the field ("
165: + forField.getName() + ") of type ("
166: + forField.getType()
167: + ") is currently not supported");
168: }
169:
170: return back;
171: }
172:
173: }
|