Source Code Cross Referenced for ReflectionComparator.java in  » Testing » unitils » org » unitils » reflectionassert » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » unitils » org.unitils.reflectionassert 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2006-2007,  Unitils.org
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.unitils.reflectionassert;
017:
018:        import org.unitils.core.UnitilsException;
019:
020:        import static java.lang.Boolean.TRUE;
021:        import java.util.HashMap;
022:        import java.util.Iterator;
023:        import java.util.Map;
024:        import java.util.Stack;
025:
026:        /**
027:         * Abstract superclass that defines a template for sub implementations that can compare objects of a certain kind.
028:         * Different instances of different subtypes will be chained to obtain a reflection comparator chain. This chain
029:         * will compare two objects with eachother through reflection. Depending on the composition of the chain, a number
030:         * of 'leniency levels' are in operation.
031:         * <p/>
032:         * If the check indicates that both objects are not equal, the first (and only the first!) found difference is returned.
033:         * The actual difference can then be retrieved by the fieldStack, leftValue and rightValue properties.
034:         *
035:         * @author Tim Ducheyne
036:         * @author Filip Neven
037:         */
038:        abstract public class ReflectionComparator {
039:
040:            /**
041:             * Root of the comparator chain. Comparisons must start with calling the getDifference method of this object
042:             */
043:            protected ReflectionComparator rootComparator;
044:
045:            /**
046:             * Next element in the comparator chain.
047:             */
048:            protected ReflectionComparator chainedComparator;
049:
050:            /**
051:             * Constructs a new instance, with the given comparator as the next element in the chain. Makes sure that this
052:             * instance is registered as root comparator of the given chained comparator. Setting the root comparator gets
053:             * propagated to all elements in the chain. This way, all comparators share the same root at all times.
054:             *
055:             * @param chainedComparator The next comparator in the chain
056:             */
057:            public ReflectionComparator(ReflectionComparator chainedComparator) {
058:                this .chainedComparator = chainedComparator;
059:                setRootComparator(this );
060:            }
061:
062:            /**
063:             * Sets the root comparator. This operation is propagated to all comparators in the chain. This way, all comparators
064:             * share the same root at all times.
065:             *
066:             * @param rootComparator The root comparator, i.e. the first comparator in the chain
067:             */
068:            protected void setRootComparator(ReflectionComparator rootComparator) {
069:                this .rootComparator = rootComparator;
070:                if (chainedComparator != null) {
071:                    chainedComparator.setRootComparator(rootComparator);
072:                }
073:            }
074:
075:            /**
076:             * Indicates whether this ReflectionComparator is able to check whether their is a difference in the given left
077:             * and right objects or not.
078:             *
079:             * @param left  The left object
080:             * @param right The right object
081:             * @return true if this ReflectionComparator is able to check whether their is a difference in the given left
082:             *         and right objects, false otherwise
083:             */
084:            abstract public boolean canHandle(Object left, Object right);
085:
086:            /**
087:             * Checks whether there is a difference between the left and right objects. Whether there is a difference, depends
088:             * on the concrete comparators in the chain.
089:             *
090:             * @param left  the left instance
091:             * @param right the right instance
092:             * @return the difference, null if there is no difference
093:             */
094:            public Difference getDifference(Object left, Object right) {
095:                return getDifference(left, right, new Stack<String>(),
096:                        new HashMap<TraversedInstancePair, Boolean>());
097:            }
098:
099:            /**
100:             * If this ReflectionComparator is able to check whether their is a difference in the given left
101:             * and right objects (i.e. {@link #canHandle(Object,Object)} returns true), the objects are compared.
102:             *
103:             * @param left                   The left instance
104:             * @param right                  The right instance
105:             * @param fieldStack             Stack indicating the path from the root of the object structure to the object that is currently
106:             *                               compared
107:             * @param traversedInstancePairs Set with pairs of objects that have been compared with eachother. A pair of two
108:             * @return The difference, null if there is no difference
109:             */
110:            protected Difference getDifference(Object left, Object right,
111:                    Stack<String> fieldStack,
112:                    Map<TraversedInstancePair, Boolean> traversedInstancePairs) {
113:                if (isTraversedInstancePairEqual(left, right,
114:                        traversedInstancePairs)) {
115:                    return null;
116:                }
117:
118:                if (canHandle(left, right)) {
119:                    registerTraversedInstancePair(left, right, true,
120:                            traversedInstancePairs);
121:                    Difference difference = doGetDifference(left, right,
122:                            fieldStack, traversedInstancePairs);
123:                    registerTraversedInstancePair(left, right,
124:                            (difference == null), traversedInstancePairs);
125:                    return difference;
126:                } else {
127:                    if (chainedComparator == null) {
128:                        throw new UnitilsException(
129:                                "No ReflectionComparator found for objects "
130:                                        + left + " and" + right + " at "
131:                                        + fieldStack.toString());
132:                    } else {
133:                        return chainedComparator.getDifference(left, right,
134:                                fieldStack, traversedInstancePairs);
135:                    }
136:                }
137:            }
138:
139:            /**
140:             * Abstract method that makes up the core of a reflection comparator. Implementations should return a concrete
141:             * {@link Difference} object when left and right are different, or null otherwise. This method will only be called
142:             * if {@link #canHandle(Object,Object)} returns true. An implementation doesn't have to take care of chaining or
143:             * circular references.
144:             *
145:             * @param left                   The left instance
146:             * @param right                  The right instance
147:             * @param fieldStack             Stack indicating the path from the root of the object structure to the object that is currently
148:             *                               compared
149:             * @param traversedInstancePairs Set with pairs of objects that have been compared with eachother. A pair of two
150:             * @return The difference, null if there is no difference
151:             */
152:            abstract protected Difference doGetDifference(Object left,
153:                    Object right, Stack<String> fieldStack,
154:                    Map<TraversedInstancePair, Boolean> traversedInstancePairs);
155:
156:            /**
157:             * Checks whether there is no difference between the left and right objects. The meaning of no difference is
158:             * determined by the set comparator modes. See class javadoc for more info.
159:             *
160:             * @param left  the left instance
161:             * @param right the right instance
162:             * @return true if there is no difference, false otherwise
163:             */
164:            public boolean isEqual(Object left, Object right) {
165:                Difference difference = rootComparator.getDifference(left,
166:                        right);
167:                return difference == null;
168:            }
169:
170:            /**
171:             * Registers the fact that the given left and right object have been compared, to make sure the same two objects
172:             * will not be compared again (to avoid infinite loops in case of circular references)
173:             *
174:             * @param left                   The left instance
175:             * @param right                  The right instance
176:             * @param outcome                The outcome of the comparison
177:             * @param traversedInstancePairs Map with pairs of objects that have been compared with each other.
178:             */
179:            protected void registerTraversedInstancePair(Object left,
180:                    Object right, boolean outcome,
181:                    Map<TraversedInstancePair, Boolean> traversedInstancePairs) {
182:                if (left == null || right == null) {
183:                    return;
184:                }
185:                traversedInstancePairs.put(new TraversedInstancePair(left,
186:                        right), outcome);
187:            }
188:
189:            /**
190:             * Checks whether the given left and right object have already been compared, according to the given set of
191:             * traversedInstancePairs. If so, this will return the outcome of the comparison. False will be returned
192:             * if the pair was not yet compared or is being compared.
193:             *
194:             * @param left                   the left instance
195:             * @param right                  the right instance
196:             * @param traversedInstancePairs Map with pairs of objects that have been compared with each other.
197:             * @return true if already compared and equal, false otherwise
198:             */
199:            protected boolean isTraversedInstancePairEqual(Object left,
200:                    Object right,
201:                    Map<TraversedInstancePair, Boolean> traversedInstancePairs) {
202:                if (left == null || right == null) {
203:                    return false;
204:                }
205:                return traversedInstancePairs.get(new TraversedInstancePair(
206:                        left, right)) == TRUE;
207:            }
208:
209:            /**
210:             * A class for holding the difference between two objects.
211:             */
212:            public static class Difference {
213:
214:                /* A message describing the difference */
215:                protected String message;
216:
217:                /* When isEquals is false this will contain the stack of the fieldnames where the difference was found. <br>
218:                 * The inner most field will be the top of the stack, eg "primitiveFieldInB", "fieldBinA", "fieldA". */
219:                protected Stack<String> fieldStack;
220:
221:                /* When isEquals is false this will contain the left value of the field where the difference was found. */
222:                protected Object leftValue;
223:
224:                /* When isEquals is false, this will contain the right value of the field where the difference was found. */
225:                protected Object rightValue;
226:
227:                /**
228:                 * Creates a difference.
229:                 *
230:                 * @param message    a message describing the difference
231:                 * @param leftValue  the left instance
232:                 * @param rightValue the right instance
233:                 * @param fieldStack the current field names
234:                 */
235:                public Difference(String message, Object leftValue,
236:                        Object rightValue, Stack<String> fieldStack) {
237:                    this .message = message;
238:                    this .leftValue = leftValue;
239:                    this .rightValue = rightValue;
240:                    this .fieldStack = fieldStack;
241:                }
242:
243:                /**
244:                 * Gets a string representation of the field stack.
245:                 * Eg primitiveFieldInB.fieldBinA.fieldA
246:                 * The top-level element is an empty string.
247:                 *
248:                 * @return the field names as sting
249:                 */
250:                public String getFieldStackAsString() {
251:                    String result = "";
252:                    Iterator<?> iterator = fieldStack.iterator();
253:                    while (iterator.hasNext()) {
254:                        result += iterator.next();
255:                        if (iterator.hasNext()) {
256:                            result += ".";
257:                        }
258:                    }
259:                    return result;
260:                }
261:
262:                /**
263:                 * Gets the message indicating the kind of difference.
264:                 *
265:                 * @return the message
266:                 */
267:                public String getMessage() {
268:                    return message;
269:                }
270:
271:                /**
272:                 * Gets the stack of the fieldnames where the difference was found.
273:                 * The inner most field will be the top of the stack, eg "primitiveFieldInB", "fieldBinA", "fieldA".
274:                 * The top-level element has an empty stack.
275:                 *
276:                 * @return the stack of field names, not null
277:                 */
278:                public Stack<String> getFieldStack() {
279:                    return fieldStack;
280:                }
281:
282:                /**
283:                 * Gets the left value of the field where the difference was found.
284:                 *
285:                 * @return the value
286:                 */
287:                public Object getLeftValue() {
288:                    return leftValue;
289:                }
290:
291:                /**
292:                 * Gets the right value of the field where the difference was found.
293:                 *
294:                 * @return the value
295:                 */
296:                public Object getRightValue() {
297:                    return rightValue;
298:                }
299:            }
300:
301:            /**
302:             * Value object that represents a pair of objects that have been compared with eachother. Two instances of this
303:             * class are equal when the leftObject and rightObject fields reference the same instances.
304:             */
305:            protected static class TraversedInstancePair {
306:
307:                /* The left object */
308:                private Object leftObject;
309:
310:                /* The right object */
311:                private Object rightObject;
312:
313:                /**
314:                 * Constructs a new instance with the given left and right object
315:                 *
316:                 * @param leftObject  the left instance
317:                 * @param rightObject the right instance
318:                 */
319:                public TraversedInstancePair(Object leftObject,
320:                        Object rightObject) {
321:                    this .leftObject = leftObject;
322:                    this .rightObject = rightObject;
323:                }
324:
325:                /**
326:                 * @return The left instance
327:                 */
328:                public Object getLeftObject() {
329:                    return leftObject;
330:                }
331:
332:                /**
333:                 * @return The right instance
334:                 */
335:                public Object getRightObject() {
336:                    return rightObject;
337:                }
338:
339:                /**
340:                 * @param o Another object
341:                 * @return true when the other object is a TraversedInstancePair with the same left and right object instances.
342:                 */
343:                @Override
344:                public boolean equals(Object o) {
345:                    if (this  == o)
346:                        return true;
347:                    if (o == null || getClass() != o.getClass())
348:                        return false;
349:
350:                    TraversedInstancePair that = (TraversedInstancePair) o;
351:
352:                    if (!(leftObject == that.leftObject))
353:                        return false;
354:                    return rightObject == that.rightObject;
355:                }
356:
357:                /**
358:                 * @return This object's hashcode
359:                 */
360:                @Override
361:                public int hashCode() {
362:                    int result;
363:                    result = leftObject.hashCode();
364:                    result = 31 * result + rightObject.hashCode();
365:                    return result;
366:                }
367:            }
368:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.