001: package org.uispec4j.xml;
002:
003: import junit.framework.Assert;
004: import org.xml.sax.Attributes;
005:
006: import java.io.Reader;
007: import java.io.StringReader;
008: import java.util.*;
009:
010: public class XmlAssert {
011:
012: private XmlAssert() {
013: // Static class
014: }
015:
016: public static void assertEquivalent(String xmlA, String xmlB) {
017: ComparableNode aNode = createXmlEquivalentComparableNode(new StringReader(
018: xmlA));
019: ComparableNode bNode = createXmlEquivalentComparableNode(new StringReader(
020: xmlB));
021: if (!aNode.equals(bNode)) {
022: Assert.assertEquals(prepareXmlString(xmlA),
023: prepareXmlString(xmlB));
024: }
025: }
026:
027: private static String prepareXmlString(String input) {
028: return input.replaceAll("[ ]+<", "<").replaceAll("\n", "")
029: .replaceAll("><", ">\n<").replace('\'', '"');
030: }
031:
032: public static void assertEquals(String xmlA, String xmlB) {
033: ComparableNode aNode = createXmlEqualComparableNode(new StringReader(
034: xmlA));
035: ComparableNode bNode = createXmlEqualComparableNode(new StringReader(
036: xmlB));
037: if (!aNode.equals(bNode)) {
038: Assert.assertEquals(prepareXmlString(xmlA),
039: prepareXmlString(xmlB));
040: }
041: }
042:
043: private static ComparableNode createXmlEqualComparableNode(
044: Reader reader) {
045: EqualComparator comparableNode = new EqualComparator();
046: new SaxParser().parse(comparableNode, reader);
047: return comparableNode;
048: }
049:
050: private static ComparableNode createXmlEquivalentComparableNode(
051: Reader reader) {
052: EquivalentComparator comparableNode = new EquivalentComparator();
053: new SaxParser().parse(comparableNode, reader);
054: return comparableNode;
055: }
056:
057: static abstract class ComparableNode implements Node {
058: String tag = "";
059: Map attributes;
060: Map childrenOccurences = new HashMap();
061: List children = new ArrayList();
062: String text = "";
063:
064: protected abstract boolean comparator(Object o);
065:
066: public ComparableNode(String tag, Attributes attributes) {
067: this .tag = tag;
068: this .attributes = map(attributes);
069: }
070:
071: public String toString() {
072: if ("root".equals(tag)) {
073: return childrenString();
074: } else if ((!childrenOccurences.isEmpty())
075: || (text.length() > 0)) {
076: return "<" + tag + attributeString() + ">"
077: + childrenString() + text + "</" + tag + ">";
078: } else {
079: return "<" + tag + attributeString() + "/>";
080: }
081: }
082:
083: public void setValue(String value) {
084: text = value.trim();
085: }
086:
087: public void complete() {
088: }
089:
090: public boolean equals(Object o) {
091: if (this == o)
092: return true;
093: if (!(o instanceof ComparableNode))
094: return false;
095: final ComparableNode comparableXml = (ComparableNode) o;
096:
097: if (attributes != null ? !attributes
098: .equals(comparableXml.attributes)
099: : comparableXml.attributes != null)
100: return false;
101: if (tag != null ? !tag.equals(comparableXml.tag)
102: : comparableXml.tag != null)
103: return false;
104: if (text != null ? !text.equals(comparableXml.text)
105: : comparableXml.text != null)
106: return false;
107:
108: return comparator(o);
109: }
110:
111: public int hashCode() {
112: int result = tag.hashCode();
113: result = 29 * result + attributes.hashCode();
114: return result;
115: }
116:
117: private Map map(Attributes xmlAttrs) {
118: Map map = new HashMap();
119: if (xmlAttrs == null) {
120: return map;
121: }
122: for (int i = 0; i < xmlAttrs.getLength(); i++) {
123: String localName = xmlAttrs.getLocalName(i);
124: map.put(localName, xmlAttrs.getValue(i));
125: }
126: return map;
127: }
128:
129: void addChild(Object child) {
130: int val = 1;
131: if (childrenOccurences.containsKey(child)) {
132: Object occurence = childrenOccurences.get(child);
133: if (occurence != null) {
134: val = Integer.valueOf((String) occurence)
135: .intValue() + 1;
136: }
137: }
138: childrenOccurences.put(child, Integer.toString(val));
139: children.add(child);
140: }
141:
142: private String childrenString() {
143: StringBuffer sb = new StringBuffer();
144: for (Iterator iterator = childrenOccurences.keySet()
145: .iterator(); iterator.hasNext();) {
146: ComparableNode node = (ComparableNode) iterator.next();
147: sb.append(node);
148: sb.append("\n");
149: }
150: return sb.toString();
151: }
152:
153: private String attributeString() {
154: StringBuffer sb = new StringBuffer();
155: for (Iterator iterator = attributes.entrySet().iterator(); iterator
156: .hasNext();) {
157: Map.Entry e = (Map.Entry) iterator.next();
158: sb.append(" " + e.getKey() + "=\"" + e.getValue()
159: + "\"");
160: }
161: return sb.toString();
162: }
163: }
164:
165: static class EquivalentComparator extends ComparableNode {
166: public EquivalentComparator(String tag, Attributes attributes) {
167: super (tag, attributes);
168: }
169:
170: public EquivalentComparator() {
171: super ("root", null);
172: }
173:
174: public Node getSubNode(String childName, Attributes xmlAttrs)
175: throws RuntimeException {
176: ComparableNode o = new EquivalentComparator(childName,
177: xmlAttrs);
178: addChild(o);
179: return o;
180: }
181:
182: protected boolean comparator(Object o) {
183: final ComparableNode comparableXml = (ComparableNode) o;
184: if (childrenOccurences != null ? !childrenOccurences
185: .equals(comparableXml.childrenOccurences)
186: : comparableXml.childrenOccurences != null)
187: return false;
188: return true;
189: }
190: }
191:
192: static class EqualComparator extends ComparableNode {
193: public EqualComparator(String tag, Attributes attributes) {
194: super (tag, attributes);
195: }
196:
197: public EqualComparator() {
198: super ("root", null);
199: }
200:
201: public Node getSubNode(String childName, Attributes xmlAttrs)
202: throws RuntimeException {
203: ComparableNode o = new EqualComparator(childName, xmlAttrs);
204: addChild(o);
205: return o;
206: }
207:
208: protected boolean comparator(Object o) {
209: final ComparableNode comparableXml = (ComparableNode) o;
210: if (children != null ? !children
211: .equals(comparableXml.children)
212: : comparableXml.children != null)
213: return false;
214: return true;
215: }
216: }
217: }
|