Source Code Cross Referenced for Diff.java in  » Testing » XMLUnit » org » custommonkey » xmlunit » 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 » XMLUnit » org.custommonkey.xmlunit 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         ******************************************************************
003:        Copyright (c) 2001-2007, Jeff Martin, Tim Bacon
004:        All rights reserved.
005:
006:        Redistribution and use in source and binary forms, with or without
007:        modification, are permitted provided that the following conditions
008:        are met:
009:
010:         * Redistributions of source code must retain the above copyright
011:              notice, this list of conditions and the following disclaimer.
012:         * Redistributions in binary form must reproduce the above
013:              copyright notice, this list of conditions and the following
014:              disclaimer in the documentation and/or other materials provided
015:              with the distribution.
016:         * Neither the name of the xmlunit.sourceforge.net nor the names
017:              of its contributors may be used to endorse or promote products
018:              derived from this software without specific prior written
019:              permission.
020:
021:        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
022:        "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
023:        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
024:        FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
025:        COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
026:        INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
027:        BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
028:        LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
029:        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
030:        LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
031:        ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
032:        POSSIBILITY OF SUCH DAMAGE.
033:
034:         ******************************************************************
035:         */
036:
037:        package org.custommonkey.xmlunit;
038:
039:        import java.io.IOException;
040:        import java.io.Reader;
041:        import java.io.StringReader;
042:        import javax.xml.transform.TransformerException;
043:        import javax.xml.transform.dom.DOMSource;
044:
045:        import org.custommonkey.xmlunit.exceptions.XMLUnitRuntimeException;
046:
047:        import org.w3c.dom.Document;
048:        import org.w3c.dom.Node;
049:        import org.xml.sax.InputSource;
050:        import org.xml.sax.SAXException;
051:
052:        /**
053:         * Compares and describes any difference between XML documents.
054:         * Two documents are either:
055:         * <br /><ul>
056:         * <li><i>identical</i>: the content and sequence of the nodes in the documents
057:         * are exactly the same</li>
058:         * <li><i>similar</i>: the content of the nodes in the documents are the same,
059:         * but minor differences exist e.g. sequencing of sibling elements, values of
060:         * namespace prefixes, use of implied attribute values</li>
061:         * <li><i>different</i>: the contents of the documents are fundamentally
062:         * different</li>
063:         * </ul>
064:         * <br />
065:         * The difference between compared documents is contained in a  message buffer
066:         * held in this class, accessible either through the  <code>appendMessage</code>
067:         * or <code>toString</code> methods.  NB: When comparing documents, the
068:         * comparison is halted as soon as the  status (identical / similar / different)
069:         * is known with certainty. For a  list of all differences between the documents
070:         * an instance of  {@link DetailedDiff the DetailedDiff class} can be used
071:         * instead.
072:         * <br />Examples and more at <a href="http://xmlunit.sourceforge.net"/>xmlunit.sourceforge.net</a>
073:         */
074:        public class Diff implements  DifferenceListener, ComparisonController {
075:            private final Document controlDoc;
076:            private final Document testDoc;
077:            private boolean similar = true;
078:            private boolean identical = true;
079:            private boolean compared = false;
080:            private boolean haltComparison = false;
081:            private StringBuffer messages;
082:            private DifferenceEngine differenceEngine;
083:            private DifferenceListener differenceListenerDelegate;
084:            private ElementQualifier elementQualifierDelegate;
085:
086:            /**
087:             * Construct a Diff that compares the XML in two Strings
088:             */
089:            public Diff(String control, String test) throws SAXException,
090:                    IOException {
091:                this (new StringReader(control), new StringReader(test));
092:            }
093:
094:            /**
095:             * Construct a Diff that compares the XML read from two Readers
096:             */
097:            public Diff(Reader control, Reader test) throws SAXException,
098:                    IOException {
099:                this (
100:                        XMLUnit.buildDocument(XMLUnit.newControlParser(),
101:                                control), XMLUnit.buildDocument(XMLUnit
102:                                .newTestParser(), test));
103:            }
104:
105:            /**
106:             * Construct a Diff that compares the XML in two Documents
107:             */
108:            public Diff(Document controlDoc, Document testDoc) {
109:                this (controlDoc, testDoc, (DifferenceEngine) null);
110:            }
111:
112:            /**
113:             * Construct a Diff that compares the XML in a control Document against the
114:             * result of a transformation
115:             */
116:            public Diff(String control, Transform testTransform)
117:                    throws IOException, TransformerException, SAXException {
118:                this (XMLUnit.buildControlDocument(control), testTransform
119:                        .getResultDocument());
120:            }
121:
122:            /**
123:             * Construct a Diff that compares the XML read from two JAXP InputSources
124:             */
125:            public Diff(InputSource control, InputSource test)
126:                    throws SAXException, IOException {
127:                this (
128:                        XMLUnit.buildDocument(XMLUnit.newControlParser(),
129:                                control), XMLUnit.buildDocument(XMLUnit
130:                                .newTestParser(), test));
131:            }
132:
133:            /**
134:             * Construct a Diff that compares the XML in two JAXP DOMSources
135:             */
136:            public Diff(DOMSource control, DOMSource test) {
137:                this (control.getNode().getOwnerDocument(), test.getNode()
138:                        .getOwnerDocument());
139:            }
140:
141:            /**
142:             * Construct a Diff that compares the XML in two Documents using a specific
143:             * DifferenceEngine
144:             */
145:            public Diff(Document controlDoc, Document testDoc,
146:                    DifferenceEngine comparator) {
147:                this (controlDoc, testDoc, comparator,
148:                        new ElementNameQualifier());
149:            }
150:
151:            /**
152:             * Construct a Diff that compares the XML in two Documents using a specific
153:             * DifferenceEngine and ElementQualifier
154:             */
155:            public Diff(Document controlDoc, Document testDoc,
156:                    DifferenceEngine comparator,
157:                    ElementQualifier elementQualifier) {
158:                this .controlDoc = getManipulatedDocument(controlDoc);
159:                this .testDoc = getManipulatedDocument(testDoc);
160:                this .elementQualifierDelegate = elementQualifier;
161:                this .differenceEngine = comparator;
162:                this .messages = new StringBuffer();
163:            }
164:
165:            /**
166:             * Construct a Diff from a prototypical instance.
167:             * Used by extension subclasses
168:             * @param prototype a prototypical instance
169:             */
170:            protected Diff(Diff prototype) {
171:                this (prototype.controlDoc, prototype.testDoc,
172:                        prototype.differenceEngine,
173:                        prototype.elementQualifierDelegate);
174:                this .differenceListenerDelegate = prototype.differenceListenerDelegate;
175:            }
176:
177:            /**
178:             * If {@link XMLUnit#getIgnoreWhitespace whitespace is ignored} in
179:             * differences then manipulate the content to strip the redundant
180:             * whitespace
181:             * @param originalDoc a document making up one half of this difference
182:             * @return the original document with redundant whitespace removed if
183:             *  differences ignore whitespace
184:             */
185:            private Document getWhitespaceManipulatedDocument(
186:                    Document originalDoc) {
187:                if (!XMLUnit.getIgnoreWhitespace()) {
188:                    return originalDoc;
189:                }
190:                try {
191:                    Transform whitespaceStripper = XMLUnit
192:                            .getStripWhitespaceTransform(originalDoc);
193:                    return whitespaceStripper.getResultDocument();
194:                } catch (TransformerException e) {
195:                    throw new XMLUnitRuntimeException(e.getMessage(), e
196:                            .getCause());
197:                }
198:            }
199:
200:            /**
201:             * Manipulates the given document according to the setting in the
202:             * XMLUnit class.
203:             *
204:             * <p>This may involve:</p>
205:             * <ul>
206:             *   <li>{@link XMLUnit.setIgnoreWhitespace stripping redundant
207:             *   whitespace}</li>
208:             *   <li>{@link XMLUnit.setIgnoreComments stripping comments}</li>
209:             *   <li>{@link XMLUnit.setNormalize normalizing Text nodes}</li>
210:             * </ul>
211:             *     
212:             * @param orig a document making up one half of this difference
213:             * @return manipulated doc
214:             */
215:            private Document getManipulatedDocument(Document orig) {
216:                return getNormalizedDocument(getCommentlessDocument(getWhitespaceManipulatedDocument(orig)));
217:            }
218:
219:            /**
220:             * Removes all comment nodes if {@link XMLUnit.getIgnoreComments
221:             * comments are ignored}.
222:             *     
223:             * @param originalDoc a document making up one half of this difference
224:             * @return manipulated doc
225:             */
226:            private Document getCommentlessDocument(Document orig) {
227:                if (!XMLUnit.getIgnoreComments()) {
228:                    return orig;
229:                }
230:                try {
231:                    Transform commentStripper = XMLUnit
232:                            .getStripCommentsTransform(orig);
233:                    return commentStripper.getResultDocument();
234:                } catch (TransformerException e) {
235:                    throw new XMLUnitRuntimeException(e.getMessage(), e
236:                            .getCause());
237:                }
238:            }
239:
240:            private Document getNormalizedDocument(Document orig) {
241:                if (!XMLUnit.getNormalize()) {
242:                    return orig;
243:                }
244:                Document d = (Document) orig.cloneNode(true);
245:                d.normalize();
246:                return d;
247:            }
248:
249:            /**
250:             * Top of the recursive comparison execution tree
251:             */
252:            protected final void compare() {
253:                if (compared) {
254:                    return;
255:                }
256:                getDifferenceEngine().compare(controlDoc, testDoc, this ,
257:                        elementQualifierDelegate);
258:                compared = true;
259:            }
260:
261:            /**
262:             * Return the result of a comparison. Two documents are considered
263:             * to be "similar" if they contain the same elements and attributes
264:             * regardless of order.
265:             */
266:            public boolean similar() {
267:                compare();
268:                return similar;
269:            }
270:
271:            /**
272:             * Return the result of a comparison. Two documents are considered
273:             * to be "identical" if they contain the same elements and attributes
274:             * in the same order.
275:             */
276:            public boolean identical() {
277:                compare();
278:                return identical;
279:            }
280:
281:            /**
282:             * Append a meaningful message to the buffer of messages
283:             * @param appendTo the messages buffer
284:             * @param expected
285:             * @param actual
286:             * @param control
287:             * @param test
288:             * @param difference
289:             */
290:            private void appendDifference(StringBuffer appendTo,
291:                    Difference difference) {
292:                appendTo.append(' ').append(difference).append('\n');
293:            }
294:
295:            /**
296:             * DifferenceListener implementation.
297:             * If the {@link Diff#overrideDifferenceListener overrideDifferenceListener} 
298:             * method has been called then the interpretation of the difference
299:             * will be delegated.
300:             * @param difference
301:             * @return a DifferenceListener.RETURN_... constant indicating how the
302:             *    difference was interpreted. 
303:             * Always RETURN_ACCEPT_DIFFERENCE if the call is not delegated.
304:             */
305:            public int differenceFound(Difference difference) {
306:                int returnValue = RETURN_ACCEPT_DIFFERENCE;
307:                if (differenceListenerDelegate != null) {
308:                    returnValue = differenceListenerDelegate
309:                            .differenceFound(difference);
310:                }
311:
312:                switch (returnValue) {
313:                case RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL:
314:                    return returnValue;
315:                case RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR:
316:                    identical = false;
317:                    haltComparison = false;
318:                    break;
319:                case RETURN_ACCEPT_DIFFERENCE:
320:                    identical = false;
321:                    if (difference.isRecoverable()) {
322:                        haltComparison = false;
323:                    } else {
324:                        similar = false;
325:                        haltComparison = true;
326:                    }
327:                    break;
328:                default:
329:                    throw new IllegalArgumentException(
330:                            returnValue
331:                                    + " is not a defined DifferenceListener.RETURN_... value");
332:                }
333:                if (haltComparison) {
334:                    messages.append("\n[different]");
335:                } else {
336:                    messages.append("\n[not identical]");
337:                }
338:                appendDifference(messages, difference);
339:                return returnValue;
340:            }
341:
342:            /**
343:             * DifferenceListener implementation.
344:             * If the {@link Diff#overrideDifferenceListener  overrideDifferenceListener} 
345:             * method has been called then the call will be delegated 
346:             * otherwise a message is printed to <code>System.err</code>.
347:             * @param control
348:             * @param test
349:             */
350:            public void skippedComparison(Node control, Node test) {
351:                if (differenceListenerDelegate != null) {
352:                    differenceListenerDelegate.skippedComparison(control, test);
353:                } else {
354:                    System.err.println("DifferenceListener.skippedComparison: "
355:                            + "unhandled control node type=" + control
356:                            + ", unhandled test node type=" + test);
357:                }
358:            }
359:
360:            /**
361:             * ComparisonController implementation.
362:             * @param afterDifference
363:             * @return true if the difference is not recoverable and 
364:             * the comparison should be halted, or false if the difference 
365:             * is recoverable and the comparison can continue
366:             */
367:            public boolean haltComparison(Difference afterDifference) {
368:                return haltComparison;
369:            }
370:
371:            /**
372:             * Append the message from the result of this Diff instance to a specified
373:             *  StringBuffer
374:             * @param toAppendTo
375:             * @return specified StringBuffer with message appended
376:             */
377:            public StringBuffer appendMessage(StringBuffer toAppendTo) {
378:                compare();
379:                if (messages.length() == 0) {
380:                    messages.append("[identical]");
381:                }
382:                // fix for JDK1.4 backwards incompatibility
383:                return toAppendTo.append(messages.toString());
384:            }
385:
386:            /**
387:             * Get the result of this Diff instance as a String
388:             * @return result of this Diff
389:             */
390:            public String toString() {
391:                StringBuffer buf = new StringBuffer(getClass().getName());
392:                appendMessage(buf);
393:                return buf.toString();
394:            }
395:
396:            /**
397:             * Override the <code>DifferenceListener</code> used to determine how 
398:             * to handle differences that are found.
399:             * @param delegate the DifferenceListener instance to delegate handling to.
400:             */
401:            public void overrideDifferenceListener(DifferenceListener delegate) {
402:                this .differenceListenerDelegate = delegate;
403:            }
404:
405:            /**
406:             * Override the <code>ElementQualifier</code> used to determine which
407:             * control and test nodes are comparable for this difference comparison. 
408:             * @param delegate the ElementQualifier instance to delegate to.
409:             */
410:            public void overrideElementQualifier(ElementQualifier delegate) {
411:                this .elementQualifierDelegate = delegate;
412:            }
413:
414:            /**
415:             * Lazily initializes the difference engine if it hasn't been set
416:             * via a constructor.
417:             */
418:            private DifferenceEngine getDifferenceEngine() {
419:                return differenceEngine == null ? new DifferenceEngine(this)
420:                        : differenceEngine;
421:            }
422:
423:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.