KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > xdoclet > retest > util > XMLComparator


1 package xdoclet.retest.util;
2
3 import org.w3c.dom.Document JavaDoc;
4 import org.w3c.dom.Element JavaDoc;
5 import org.w3c.dom.Node JavaDoc;
6 import org.w3c.dom.NamedNodeMap JavaDoc;
7
8 import java.util.Stack JavaDoc;
9
10 import xdoclet.XDocletException;
11 import xdoclet.retest.XDocletRetestMessages;
12
13 /**
14  * @author David Jencks (davidjencks@directvinternet.com)
15  * @created Mars 5, 2002
16  * @version $Revision: 1.5 $
17  */

18 public class XMLComparator
19         extends AbstractComparator
20 {
21
22     private Stack JavaDoc refStack = new Stack JavaDoc();
23     private Stack JavaDoc compStack = new Stack JavaDoc();
24     private Node JavaDoc one;
25     private Node JavaDoc two;
26     private boolean attributeValidation = true;
27
28     /**
29      * Define the Node names (eg <something>) that are rejected during the
30      * comparison.
31      * Rejected values are
32      * <ul>
33      * <li>&lt;description&gt; : EJB and web deployment descriptor does not need an
34      * equality to be equal
35      * </ul>
36      */

37     static final String JavaDoc[] REJECTED = {
38         "description"
39     };
40
41     /**
42      * Default constructor where you specify the two Node to compare
43      *
44      * @param one the first node
45      * @param two the second node
46      */

47     public XMLComparator( Node JavaDoc one, Node JavaDoc two )
48     {
49         this.one = one;
50         this.two = two;
51         resultSet = new ComparisonResultSet();
52     }
53
54     /**
55      * Start the comparison
56      *
57      * @return a <code>xdoclet.retest.utilComparisonResultSet</code> containing
58      * potential differences.
59      */

60     public ComparisonResultSet compare()
61     throws XDocletException
62     {
63         compare( one, two, new Counter() );
64         return resultSet;
65     }
66
67     /**
68      * In EJB deployment descripor we do not have to take care of Attribute
69      * value. Attribute is something like &lt;tag attribute=&quot;value&quot;&gt;
70      *
71      * @param value specify if you want attribute validation
72      */

73     public void setAttributeValidation(boolean value)
74     {
75         this.attributeValidation = value;
76     }
77
78     private boolean valueDiffers( String JavaDoc r, String JavaDoc c )
79     {
80         if( r == null && c == null )
81         {
82             return false;
83         }
84         if( r != null && c != null )
85         {
86             return !r.equals( c );
87         }
88         return true;
89     }
90
91     private Node JavaDoc skipEmpty( Node JavaDoc node )
92     {
93         Node JavaDoc n = node;
94
95         while( n != null && !nodeHasContentOrAttributes( n ) )
96         {
97             n = n.getNextSibling();
98         }
99         return n;
100     }
101
102     private boolean nodeHasContentOrAttributes( Node JavaDoc n )
103     {
104         if( n == null )
105         {
106             return false;
107         }
108         // The # test is to consider #text and #cdata-section like nothing
109
if( n.getNodeValue() != null
110                 && !n.getNodeValue().trim().equals( "" )
111                 && !n.getNodeName().equals("#cdata-section")
112                 && !n.getNodeName().equals("#comment"))
113
114         {
115             //System.out.println(n.getNodeName() + "---" + n.getNodeValue());
116
return true;
117         }
118
119         if (attributeValidation){
120             NamedNodeMap JavaDoc AttList = n.getAttributes();
121
122             if( AttList != null && AttList.getLength() > 0 )
123             {
124                 return true;
125             }
126         }
127
128         Node JavaDoc c = n.getFirstChild();
129
130         while( c != null )
131         {
132             if( nodeHasContentOrAttributes( c ) )
133             {
134                 //System.out.println("222 "+n.getNodeName() + "---" + n.getNodeValue());
135
return true;
136             }
137             c = c.getNextSibling();
138         }
139         return false;
140     }
141
142     private void compare( Node JavaDoc reference, Node JavaDoc comp, Counter c )
143     throws XDocletException
144     {
145         if( reference == null )
146         {
147             if( comp == null )
148             {
149                 return;
150             }
151             else
152             {
153                 logDifference( "null reference node unmatched" );
154                 return;
155             }
156         }
157         if( comp == null )
158         {
159             logDifference( "null comparison node unmatched" );
160             return;
161         }
162         if( reference instanceof Element JavaDoc )
163         {
164             refStack.push( ( ( Element JavaDoc ) reference ).getTagName() + c.incRefCount() );
165         }
166         if( comp instanceof Element JavaDoc )
167         {
168             compStack.push( ( ( Element JavaDoc ) comp ).getTagName() + c.incCompCount() );
169         }
170
171             if( valueDiffers( reference.getNodeName(), comp.getNodeName() ) )
172             {
173                 logDifference( "Mismatch NODE NAME, reference : " + reference.getNodeName() +
174                         " differs from new: " + comp.getNodeName() );
175             }
176
177         if ( ! rejectedNodeName(reference.getNodeName()) && ! rejectedNodeName(comp.getNodeName())){
178             if( valueDiffers( reference.getNodeValue(), comp.getNodeValue() ) )
179             {
180                 logDifference( "Mismatch NODE VALUE, reference : " + reference.getNodeName()+"."+reference.getNodeValue() +
181                     " differs from new: " + comp.getNodeName()+"."+comp.getNodeValue() );
182             }
183         }
184
185         if (attributeValidation)
186         {
187             NamedNodeMap JavaDoc refAttList = reference.getAttributes();
188             NamedNodeMap JavaDoc compAttList = comp.getAttributes();
189             int refAttListLength = ( refAttList == null ) ? 0 : refAttList.getLength();
190             int compAttListLength = ( compAttList == null ) ? 0 : compAttList.getLength();
191
192             if( refAttListLength != compAttListLength )
193             {
194                 logDifference( "Differing attribute count, reference : " + refAttListLength +
195                     " differs from new: " + compAttListLength );
196             }
197             for( int i = 0; i < Math.min( refAttListLength, compAttListLength ); i++ )
198             {
199                 compare( refAttList.item( i ), compAttList.item( i ), c );
200             }
201         }
202
203         Node JavaDoc refChild = skipEmpty( reference.getFirstChild() );
204         Node JavaDoc compChild = skipEmpty( comp.getFirstChild() );
205         Counter subC = new Counter();
206
207         while( refChild != null && compChild != null )
208         {
209             while( refChild != null && refChild.getNodeType() == 8)
210             {
211                 refChild = skipEmpty( refChild.getNextSibling() );
212             }
213
214             while( compChild != null && compChild.getNodeType() == 8)
215             {
216                 compChild = skipEmpty( compChild.getNextSibling() );
217             }
218
219             compare( refChild, compChild, subC );
220             if (refChild != null) refChild = skipEmpty( refChild.getNextSibling() );
221             if (compChild != null)compChild = skipEmpty( compChild.getNextSibling() );
222         }
223
224         while(refChild != null && refChild.getNodeType() == 8)
225         {
226             refChild = skipEmpty( refChild.getNextSibling() );
227         }
228
229         while( compChild != null && compChild.getNodeType() == 8)
230         {
231             compChild = skipEmpty( compChild.getNextSibling() );
232         }
233
234         //check for leftovers
235
while( refChild != null )
236         {
237             logDifference( "unmatched in reference : " + refChild );
238             refChild = skipEmpty( refChild.getNextSibling() );
239         }
240         while( compChild != null )
241         {
242             logDifference( "unmatched in compare : " + compChild );
243             compChild = skipEmpty( compChild.getNextSibling() );
244         }
245
246         if( reference instanceof Element JavaDoc )
247         {
248             refStack.pop();
249         }
250         if( comp instanceof Element JavaDoc )
251         {
252             compStack.pop();
253         }
254     }
255
256     private void logDifference( String JavaDoc message )
257     throws XDocletException
258     {
259         resultSet.addError(XDocletRetestMessages.XML_DIFF,new String JavaDoc[]{message});
260     }
261
262     private boolean rejectedNodeName(String JavaDoc s)
263     {
264         for (int i = 0 ; i < REJECTED.length ; i++)
265         {
266             if (s.equals(REJECTED[i])) return true;
267         }
268             return false;
269     }
270
271     private class Counter
272     {
273         private int refCount = 0;
274         private int compCount = 0;
275         int incRefCount()
276         {
277             return ++refCount;
278         }
279         int incCompCount()
280         {
281             return ++compCount;
282         }
283     }
284
285
286 }
287
Popular Tags