001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */package com.tc.test.collections;
004:
005: import com.tc.util.Assert;
006: import com.tc.util.EqualityComparator;
007: import com.tc.util.Stringifier;
008:
009: import java.util.ArrayList;
010: import java.util.Collection;
011: import java.util.Iterator;
012: import java.util.List;
013:
014: /**
015: * An object that knows how to compare collections of objects for equality. Unlike using the simple
016: * {@link Collection.equals(Object)}method, this class (or subclasses) can compare collections under various
017: * constraints (e.g., must be the same, but without regard to order; must have the same objects, but number of
018: * repetitions of those objects is irrelevant; etc.). Also, this class reports mismatches between collections in a
019: * uniform, object-oriented way, such that they can be easily printed out, compared themselves, and so on.
020: */
021: public abstract class CollectionComparer {
022:
023: private final EqualityComparator comparator;
024: private final Stringifier describer;
025:
026: public CollectionComparer(EqualityComparator comparator,
027: Stringifier describer) {
028: Assert.assertNotNull(comparator);
029: Assert.assertNotNull(describer);
030:
031: this .comparator = comparator;
032: this .describer = describer;
033: }
034:
035: public CollectionMismatch[] getMismatches(
036: Object collectionOneObject, Object collectionTwoObject) {
037: Assert.assertNotNull(collectionOneObject);
038: Assert.assertNotNull(collectionTwoObject);
039:
040: Object[] collectionOne = getCollection(collectionOneObject);
041: Object[] collectionTwo = getCollection(collectionTwoObject);
042:
043: return doComparison(collectionOne, collectionTwo);
044: }
045:
046: protected abstract CollectionMismatch[] doComparison(
047: Object[] collectionOne, Object[] collectionTwo);
048:
049: protected final Stringifier describer() {
050: return this .describer;
051: }
052:
053: protected final boolean isEqual(Object firstObject,
054: boolean firstIsOne, Object secondObject,
055: boolean secondIsOne, int oneIndex, int twoIndex) {
056: boolean isEqual = this .comparator.isEquals(firstObject,
057: secondObject);
058: boolean flipEqual = this .comparator.isEquals(secondObject,
059: firstObject);
060:
061: if (isEqual != flipEqual) {
062: // formatting
063: throw new IllegalStateException(
064: "Your comparator is broken; it claimed that collection "
065: + (firstIsOne ? "one" : "two") + ", index "
066: + oneIndex + " ("
067: + this .describer.toString(firstObject)
068: + ") was " + (isEqual ? "" : "not ")
069: + "equal to collection "
070: + (secondIsOne ? "one" : "two")
071: + ", index " + twoIndex + " ("
072: + (this .describer.toString(secondObject))
073: + "), but the reverse "
074: + "comparison gave the opposite result.");
075: }
076:
077: return isEqual;
078: }
079:
080: private Object[] getCollection(Object o) {
081: Assert.assertNotNull(o);
082:
083: if (o instanceof Object[])
084: return (Object[]) o;
085: else if (o instanceof byte[]) {
086: return getCollection((byte[]) o);
087: } else if (o instanceof char[]) {
088: return getCollection((char[]) o);
089: } else if (o instanceof short[]) {
090: return getCollection((short[]) o);
091: } else if (o instanceof int[]) {
092: return getCollection((int[]) o);
093: } else if (o instanceof long[]) {
094: return getCollection((long[]) o);
095: } else if (o instanceof boolean[]) {
096: return getCollection((boolean[]) o);
097: } else if (o instanceof float[]) {
098: return getCollection((float[]) o);
099: } else if (o instanceof double[]) {
100: return getCollection((double[]) o);
101: } else if (o instanceof Iterator) {
102: return getCollection((Iterator) o);
103: } else if (o instanceof Collection) {
104: return getCollection((Collection) o);
105: } else {
106: throw new IllegalArgumentException(
107: "This object, "
108: + o
109: + ", is of class '"
110: + o.getClass().getName()
111: + "'; "
112: + "that is not a recognized type of collection or other aggregate.");
113: }
114: }
115:
116: private Object[] getCollection(byte[] b) {
117: Object[] o = new Object[b.length];
118: for (int i = 0; i < o.length; ++i) {
119: o[i] = new Byte(b[i]);
120: }
121: return o;
122: }
123:
124: private Object[] getCollection(char[] c) {
125: Object[] o = new Object[c.length];
126: for (int i = 0; i < o.length; ++i) {
127: o[i] = new Character(c[i]);
128: }
129: return o;
130: }
131:
132: private Object[] getCollection(short[] s) {
133: Object[] o = new Object[s.length];
134: for (int i = 0; i < o.length; ++i) {
135: o[i] = new Short(s[i]);
136: }
137: return o;
138: }
139:
140: private Object[] getCollection(int[] iarr) {
141: Object[] o = new Object[iarr.length];
142: for (int i = 0; i < o.length; ++i) {
143: o[i] = new Integer(iarr[i]);
144: }
145: return o;
146: }
147:
148: private Object[] getCollection(long[] l) {
149: Object[] o = new Object[l.length];
150: for (int i = 0; i < o.length; ++i) {
151: o[i] = new Long(l[i]);
152: }
153: return o;
154: }
155:
156: private Object[] getCollection(boolean[] b) {
157: Object[] o = new Object[b.length];
158: for (int i = 0; i < o.length; ++i) {
159: o[i] = b[i] ? Boolean.TRUE : Boolean.FALSE;
160: }
161: return o;
162: }
163:
164: private Object[] getCollection(float[] f) {
165: Object[] o = new Object[f.length];
166: for (int i = 0; i < o.length; ++i) {
167: o[i] = new Float(f[i]);
168: }
169: return o;
170: }
171:
172: private Object[] getCollection(double[] d) {
173: Object[] o = new Object[d.length];
174: for (int i = 0; i < o.length; ++i) {
175: o[i] = new Double(d[i]);
176: }
177: return o;
178: }
179:
180: private Object[] getCollection(Iterator i) {
181: List out = new ArrayList();
182: while (i.hasNext())
183: out.add(i.next());
184: return out.toArray(new Object[out.size()]);
185: }
186:
187: private Object[] getCollection(Collection c) {
188: return c.toArray(new Object[c.size()]);
189: }
190:
191: }
|