1 package xdoclet.retest.util; 2 3 import org.w3c.dom.Document ; 4 import org.w3c.dom.Element ; 5 import org.w3c.dom.Node ; 6 import org.w3c.dom.NamedNodeMap ; 7 8 import java.util.Stack ; 9 10 import xdoclet.XDocletException; 11 import xdoclet.retest.XDocletRetestMessages; 12 13 18 public class XMLComparator 19 extends AbstractComparator 20 { 21 22 private Stack refStack = new Stack (); 23 private Stack compStack = new Stack (); 24 private Node one; 25 private Node two; 26 private boolean attributeValidation = true; 27 28 37 static final String [] REJECTED = { 38 "description" 39 }; 40 41 47 public XMLComparator( Node one, Node two ) 48 { 49 this.one = one; 50 this.two = two; 51 resultSet = new ComparisonResultSet(); 52 } 53 54 60 public ComparisonResultSet compare() 61 throws XDocletException 62 { 63 compare( one, two, new Counter() ); 64 return resultSet; 65 } 66 67 73 public void setAttributeValidation(boolean value) 74 { 75 this.attributeValidation = value; 76 } 77 78 private boolean valueDiffers( String r, String 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 skipEmpty( Node node ) 92 { 93 Node 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 n ) 103 { 104 if( n == null ) 105 { 106 return false; 107 } 108 if( n.getNodeValue() != null 110 && !n.getNodeValue().trim().equals( "" ) 111 && !n.getNodeName().equals("#cdata-section") 112 && !n.getNodeName().equals("#comment")) 113 114 { 115 return true; 117 } 118 119 if (attributeValidation){ 120 NamedNodeMap AttList = n.getAttributes(); 121 122 if( AttList != null && AttList.getLength() > 0 ) 123 { 124 return true; 125 } 126 } 127 128 Node c = n.getFirstChild(); 129 130 while( c != null ) 131 { 132 if( nodeHasContentOrAttributes( c ) ) 133 { 134 return true; 136 } 137 c = c.getNextSibling(); 138 } 139 return false; 140 } 141 142 private void compare( Node reference, Node 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 ) 163 { 164 refStack.push( ( ( Element ) reference ).getTagName() + c.incRefCount() ); 165 } 166 if( comp instanceof Element ) 167 { 168 compStack.push( ( ( Element ) 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 refAttList = reference.getAttributes(); 188 NamedNodeMap 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 refChild = skipEmpty( reference.getFirstChild() ); 204 Node 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 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 ) 247 { 248 refStack.pop(); 249 } 250 if( comp instanceof Element ) 251 { 252 compStack.pop(); 253 } 254 } 255 256 private void logDifference( String message ) 257 throws XDocletException 258 { 259 resultSet.addError(XDocletRetestMessages.XML_DIFF,new String []{message}); 260 } 261 262 private boolean rejectedNodeName(String 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 |