KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > util > diff > DifferenceBuilder


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.util.diff;
5
6 import org.apache.commons.lang.builder.EqualsBuilder;
7
8 import com.tc.util.Assert;
9 import com.tc.util.StandardStringifier;
10 import com.tc.util.Stringifier;
11
12 import java.lang.reflect.AccessibleObject JavaDoc;
13 import java.lang.reflect.Field JavaDoc;
14 import java.lang.reflect.Modifier JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 /**
20  * An object like {@link EqualsBuilder}, but for use building the implementation of
21  * {@link Differenceable.addDifferences}instead.
22  */

23 public class DifferenceBuilder {
24
25   // private static final String DIFFERENT_CLASS_CONTEXT = "#class";
26
private static final Stringifier DEFAULT_STRINGIFIER = StandardStringifier.INSTANCE;
27
28   public static String JavaDoc describeDifferences(Differenceable a, Differenceable b) {
29     return describeDifferences(a, b, DEFAULT_STRINGIFIER);
30   }
31   
32   public static String JavaDoc describeDifferences(Differenceable a, Differenceable b, Stringifier stringifier) {
33     Difference[] differences = getDifferencesAsArray(a, b);
34     if (differences.length == 0) return "";
35     
36     StringBuffer JavaDoc descrip = new StringBuffer JavaDoc();
37     descrip.append("differences are:\n");
38     for (int i = 0; i < differences.length; ++i) {
39       descrip.append(differences[i].toString());
40       descrip.append("\n");
41     }
42
43     return descrip.toString();
44   }
45
46   public static Iterator JavaDoc getDifferences(Differenceable a, Differenceable b, Stringifier stringifier) {
47     Assert.assertNotNull(a);
48     Assert.assertNotNull(b);
49
50     DifferenceContext context = DifferenceContext.createInitial(stringifier);
51
52     if (! (a.getClass().equals(b.getClass()))) {
53       context.addDifference(new BasicObjectDifference(context, a, b));
54     } else {
55       a.addDifferences(context, b);
56     }
57     
58     return context.getDifferences();
59   }
60
61   public static Iterator JavaDoc getDifferences(Differenceable a, Differenceable b) {
62     return getDifferences(a, b, DEFAULT_STRINGIFIER);
63   }
64
65   public static Difference[] getDifferencesAsArray(Differenceable a, Differenceable b) {
66     return getDifferencesAsArray(a, b, DEFAULT_STRINGIFIER);
67   }
68
69   public static Difference[] getDifferencesAsArray(Differenceable a, Differenceable b, Stringifier stringifier) {
70     List JavaDoc out = new ArrayList JavaDoc();
71     Iterator JavaDoc i = getDifferences(a, b, stringifier);
72     while (i.hasNext()) {
73       out.add(i.next());
74     }
75
76     return (Difference[]) out.toArray(new Difference[out.size()]);
77   }
78
79   private final DifferenceContext previous;
80
81   public DifferenceBuilder(DifferenceContext previous) {
82     Assert.assertNotNull(previous);
83
84     this.previous = previous;
85   }
86
87   public DifferenceBuilder reflectionDifference(Object JavaDoc a, Object JavaDoc b) {
88     Assert.assertNotNull(a);
89     Assert.assertNotNull(b);
90     Assert.eval(a instanceof Differenceable);
91     Assert.eval(b instanceof Differenceable);
92     Assert.eval(a.getClass().isInstance(b));
93
94     if (a == b) return this;
95
96     Field JavaDoc[] fields = a.getClass().getDeclaredFields();
97     AccessibleObject.setAccessible(fields, true);
98     for (int i = 0; i < fields.length; ++i) {
99       Field JavaDoc f = fields[i];
100       if (!Modifier.isStatic(f.getModifiers())) {
101         try {
102           doReflectiveAppend(f.getName(), f.get(a), f.get(b), f.getType());
103         } catch (IllegalAccessException JavaDoc iae) {
104           // We should've gotten a SecurityException above, instead.
105
throw Assert.failure("This should be impossible", iae);
106         }
107       }
108     }
109
110     return this;
111   }
112
113   private void doReflectiveAppend(String JavaDoc context, Object JavaDoc a, Object JavaDoc b, Class JavaDoc c) {
114     if (c.isPrimitive()) {
115       if (c.equals(Boolean.TYPE)) append(context, ((Boolean JavaDoc) a).booleanValue(), ((Boolean JavaDoc) b).booleanValue());
116       else if (c.equals(Character.TYPE)) append(context, ((Character JavaDoc) a).charValue(), ((Character JavaDoc) b).charValue());
117       else if (c.equals(Byte.TYPE)) append(context, ((Byte JavaDoc) a).byteValue(), ((Byte JavaDoc) b).byteValue());
118       else if (c.equals(Short.TYPE)) append(context, ((Short JavaDoc) a).shortValue(), ((Short JavaDoc) b).shortValue());
119       else if (c.equals(Integer.TYPE)) append(context, ((Integer JavaDoc) a).intValue(), ((Integer JavaDoc) b).intValue());
120       else if (c.equals(Long.TYPE)) append(context, ((Long JavaDoc) a).longValue(), ((Long JavaDoc) b).longValue());
121       else if (c.equals(Float.TYPE)) append(context, ((Float JavaDoc) a).floatValue(), ((Float JavaDoc) b).floatValue());
122       else if (c.equals(Double.TYPE)) append(context, ((Double JavaDoc) a).doubleValue(), ((Double JavaDoc) b).doubleValue());
123       else throw Assert.failure("Unknown primitive type " + c);
124     } else {
125       append(context, a, b);
126     }
127   }
128
129   public DifferenceBuilder append(String JavaDoc context, boolean a, boolean b) {
130     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
131     return this;
132   }
133
134   public DifferenceBuilder append(String JavaDoc context, char a, char b) {
135     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
136     return this;
137   }
138
139   public DifferenceBuilder append(String JavaDoc context, byte a, byte b) {
140     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
141     return this;
142   }
143
144   public DifferenceBuilder append(String JavaDoc context, short a, short b) {
145     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
146     return this;
147   }
148
149   public DifferenceBuilder append(String JavaDoc context, int a, int b) {
150     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
151     return this;
152   }
153
154   public DifferenceBuilder append(String JavaDoc context, long a, long b) {
155     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
156     return this;
157   }
158
159   public DifferenceBuilder append(String JavaDoc context, float a, float b) {
160     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
161     return this;
162   }
163
164   public DifferenceBuilder append(String JavaDoc context, double a, double b) {
165     if (a != b) add(new PrimitiveDifference(this.previous.sub(context), a, b));
166     return this;
167   }
168
169   public DifferenceBuilder append(String JavaDoc context, Object JavaDoc a, Object JavaDoc b) {
170     if (a != null && b != null) {
171       if ((a instanceof Differenceable) && (b instanceof Differenceable) &&
172           (a.getClass().equals(b.getClass()))) {
173         handleDifferenceables(context, a, b);
174       } else if (a.getClass().isArray() && b.getClass().isArray()) {
175         handleArrays(context, a, b);
176       } else if (!(a.equals(b))) {
177         add(new BasicObjectDifference(this.previous.sub(context), a, b));
178       }
179     } else if (a != null || b != null) {
180       add(new BasicObjectDifference(this.previous.sub(context), a, b));
181     }
182
183     return this;
184   }
185
186   private void handleArrays(String JavaDoc context, Object JavaDoc a, Object JavaDoc b) {
187     if ((a.getClass().getComponentType().isPrimitive() || b.getClass().getComponentType().isPrimitive())
188         && (!a.getClass().getComponentType().equals(b.getClass().getComponentType()))) {
189       add(new BasicObjectDifference(this.previous.sub(context), a, b));
190     }
191
192     if (a.getClass().getComponentType().isPrimitive()) {
193       if (a instanceof boolean[]) {
194         handleArrays(context, (boolean[]) a, (boolean[]) b);
195       } else if (a instanceof char[]) {
196         handleArrays(context, (char[]) a, (char[]) b);
197       } else if (a instanceof byte[]) {
198         handleArrays(context, (byte[]) a, (byte[]) b);
199       } else if (a instanceof short[]) {
200         handleArrays(context, (short[]) a, (short[]) b);
201       } else if (a instanceof int[]) {
202         handleArrays(context, (int[]) a, (int[]) b);
203       } else if (a instanceof long[]) {
204         handleArrays(context, (long[]) a, (long[]) b);
205       } else if (a instanceof float[]) {
206         handleArrays(context, (float[]) a, (float[]) b);
207       } else if (a instanceof double[]) {
208         handleArrays(context, (double[]) a, (double[]) b);
209       } else {
210         throw Assert.failure("Unknown primitive type " + a.getClass().getComponentType());
211       }
212     } else {
213       handleArrays(context, (Object JavaDoc[]) a, (Object JavaDoc[]) b);
214     }
215   }
216
217   private void handleArrays(String JavaDoc context, boolean[] a, boolean[] b) {
218     if (a.length != b.length) {
219       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
220     } else {
221       for (int i = 0; i < a.length; ++i) {
222         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
223       }
224     }
225   }
226
227   private void handleArrays(String JavaDoc context, char[] a, char[] b) {
228     if (a.length != b.length) {
229       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
230     } else {
231       for (int i = 0; i < a.length; ++i) {
232         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
233       }
234     }
235   }
236
237   private void handleArrays(String JavaDoc context, byte[] a, byte[] b) {
238     if (a.length != b.length) {
239       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
240     } else {
241       for (int i = 0; i < a.length; ++i) {
242         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
243       }
244     }
245   }
246
247   private void handleArrays(String JavaDoc context, short[] a, short[] b) {
248     if (a.length != b.length) {
249       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
250     } else {
251       for (int i = 0; i < a.length; ++i) {
252         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
253       }
254     }
255   }
256
257   private void handleArrays(String JavaDoc context, int[] a, int[] b) {
258     if (a.length != b.length) {
259       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
260     } else {
261       for (int i = 0; i < a.length; ++i) {
262         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
263       }
264     }
265   }
266
267   private void handleArrays(String JavaDoc context, long[] a, long[] b) {
268     if (a.length != b.length) {
269       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
270     } else {
271       for (int i = 0; i < a.length; ++i) {
272         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
273       }
274     }
275   }
276
277   private void handleArrays(String JavaDoc context, float[] a, float[] b) {
278     if (a.length != b.length) {
279       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
280     } else {
281       for (int i = 0; i < a.length; ++i) {
282         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
283       }
284     }
285   }
286
287   private void handleArrays(String JavaDoc context, double[] a, double[] b) {
288     if (a.length != b.length) {
289       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
290     } else {
291       for (int i = 0; i < a.length; ++i) {
292         if (a[i] != b[i]) add(new PrimitiveDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
293       }
294     }
295   }
296
297   private void handleArrays(String JavaDoc context, Object JavaDoc[] a, Object JavaDoc[] b) {
298     if (a.length != b.length) {
299       add(new PrimitiveDifference(this.previous.sub(context + ".length"), a.length, b.length));
300     } else {
301       for (int i = 0; i < a.length; ++i) {
302         if ((a[i] == null) != (b[i] == null)) {
303           add(new BasicObjectDifference(this.previous.sub(context + "[" + i + "]"), a[i], b[i]));
304         } else if (a[i] != null) {
305           this.append(context + "[" + i + "]", a[i], b[i]);
306         }
307       }
308     }
309   }
310
311   private void handleDifferenceables(String JavaDoc context, Object JavaDoc a, Object JavaDoc b) {
312     int preSize = countDifferences();
313     ((Differenceable) a).addDifferences(this.previous.sub(context), b);
314     boolean hadDifferences = (countDifferences() - preSize) > 0;
315
316     boolean equals = a.equals(b);
317     Assert.eval("differences added (" + hadDifferences + ") is not same as equals(" + equals + ")",
318                 hadDifferences != equals);
319   }
320
321   private void add(Difference difference) {
322     difference.where().addDifference(difference);
323   }
324
325   private int countDifferences() {
326     return this.previous.countDifferences();
327   }
328
329 }
Popular Tags