]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
b747cf3cfea0a89aeb55aee0a9a5012bf1d3a9df
[tmp/jakarta-migration.git] /
1 /**\r
2  * This document is a part of the source code and related artifacts\r
3  * for CollectionSpace, an open source collections management system\r
4  * for museums and related institutions:\r
5  *\r
6  * http://www.collectionspace.org\r
7  * http://wiki.collectionspace.org\r
8  *\r
9  * Copyright (c) 2009 Regents of the University of California\r
10  *\r
11  * Licensed under the Educational Community License (ECL), Version 2.0.\r
12  * You may not use this file except in compliance with this License.\r
13  *\r
14  * You may obtain a copy of the ECL 2.0 License at\r
15  * https://source.collectionspace.org/collection-space/LICENSE.txt\r
16  *\r
17  *  Unless required by applicable law or agreed to in writing, software\r
18  *  distributed under the License is distributed on an "AS IS" BASIS,\r
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
20  *  See the License for the specific language governing permissions and\r
21  *  limitations under the License.\r
22  */\r
23 package org.collectionspace.services.IntegrationTests.xmlreplay;\r
24 \r
25 import org.collectionspace.services.common.api.Tools;\r
26 import org.jdom.Document;\r
27 import org.jdom.Element;\r
28 import org.jdom.JDOMException;\r
29 import org.jdom.Namespace;\r
30 import org.jdom.input.SAXBuilder;\r
31 import org.jaxen.XPath;\r
32 import org.jaxen.jdom.JDOMXPath;\r
33 \r
34 \r
35 import java.io.IOException;\r
36 import java.io.StringReader;\r
37 import java.util.ArrayList;\r
38 import java.util.HashMap;\r
39 import java.util.List;\r
40 import java.util.Map;\r
41 \r
42 import org.collectionspace.services.IntegrationTests.xmlreplay.TreeWalkResults.TreeWalkEntry;\r
43 import org.jdom.output.XMLOutputter;\r
44 \r
45 /**\r
46  * User: laramie\r
47  * $LastChangedRevision:  $\r
48  * $LastChangedDate:  $\r
49  */\r
50 public class XmlCompareJdom {\r
51 \r
52 private static final String DEFAULT_SAX_DRIVER_CLASS = "org.apache.xerces.parsers.SAXParser";\r
53 \r
54     public static org.jdom.Document getDocumentFromContent(String source) throws IOException, JDOMException {\r
55         org.jdom.Document doc;\r
56         SAXBuilder builder;\r
57         builder = new SAXBuilder();\r
58         builder.setValidation(false); //has no effect, I think.\r
59         doc = builder.build(new StringReader(source));\r
60         return doc;\r
61     }\r
62 \r
63     public static TreeWalkResults compareParts(String expectedContent, String leftID, String actualPartContent, String rightID, String startElement){\r
64         TreeWalkResults list = new TreeWalkResults();\r
65         try {\r
66 \r
67             list.leftID = leftID;\r
68             list.rightID = rightID;\r
69             TreeWalkResults.TreeWalkEntry infoentry = new TreeWalkResults.TreeWalkEntry();\r
70             infoentry.expected = expectedContent;\r
71             infoentry.actual = actualPartContent;\r
72             infoentry.status = TreeWalkResults.TreeWalkEntry.STATUS.INFO;\r
73             infoentry.message = "\r\n    LEFT file: "+leftID+"\r\n    RIGHT file: "+rightID;\r
74             list.add(infoentry);\r
75             if (Tools.isEmpty(expectedContent)){\r
76                 TreeWalkEntry entry = new TreeWalkEntry();\r
77                 entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
78                 entry.errmessage = "L dom was empty.";\r
79                 list.add(entry);\r
80             } else if (Tools.isEmpty(actualPartContent)){\r
81                 TreeWalkEntry entry = new TreeWalkEntry();\r
82                 entry.errmessage = "R dom was empty.";\r
83                 entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
84                 list.add(entry);\r
85             } else {\r
86                 Document expected = getDocumentFromContent(expectedContent);\r
87                 Document actual = getDocumentFromContent(actualPartContent);\r
88                 treeWalk(expected, actual, list, startElement);\r
89             }\r
90         } catch (Throwable t){\r
91             String msg = "ERROR in XmlReplay.compareParts(): "+t;\r
92             System.out.println(msg);\r
93             TreeWalkEntry entry = new TreeWalkEntry();\r
94                 entry.status = TreeWalkEntry.STATUS.DOC_ERROR;\r
95                 entry.errmessage = msg;\r
96                 list.add(entry);\r
97         }\r
98         return list;\r
99     }\r
100 \r
101     public static List select(Element element, String xpathExpression, Namespace namespace) throws Exception {\r
102         XPath xpath = new JDOMXPath(xpathExpression);\r
103         String prefix = namespace.getPrefix();\r
104         String uri = namespace.getURI();\r
105         xpath.addNamespace(prefix, uri);\r
106         return xpath.selectNodes(element);\r
107     }\r
108 \r
109     public static Object selectSingleNode(Element element, String xpathExpression, Namespace namespace) throws Exception {\r
110         XPath xpath = new JDOMXPath(xpathExpression);\r
111         if (namespace != null) {\r
112             String prefix = namespace.getPrefix();\r
113             String uri = namespace.getURI();\r
114             xpath.addNamespace(prefix, uri);\r
115         }\r
116         return xpath.selectSingleNode(element);\r
117     }\r
118 \r
119     public static Object selectSingleNode(String docSource, String xpathExpression, Namespace namespace) throws Exception {\r
120         Document doc = getDocumentFromContent(docSource);\r
121         Element element = doc.getRootElement();\r
122         XPath xpath = new JDOMXPath(xpathExpression);\r
123         if (namespace != null) {\r
124             String prefix = namespace.getPrefix();\r
125             String uri = namespace.getURI();\r
126             xpath.addNamespace(prefix, uri);\r
127         }\r
128         return xpath.selectSingleNode(element);\r
129     }\r
130 \r
131     /*   MAYBE DEAL WITH NAMESPACES IN THIS KIND OF APPROACH.\r
132 \r
133     for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) {\r
134     if (el.getNamespace() != null) el.setNamespace(null);\r
135 \r
136     xpath.addNamespace("x", d.getRootElement().getNamespaceUri());\r
137     */\r
138     public static boolean treeWalk(Document left, Document right, TreeWalkResults list, String startElement) throws Exception {\r
139         Element leftElement = left.getRootElement();\r
140         Element rightElement = right.getRootElement();\r
141         if (Tools.notBlank(startElement)) {\r
142             XPath xpath = new JDOMXPath(startElement);\r
143             Object test = xpath.selectSingleNode(leftElement);\r
144             if (test!=null){\r
145                 leftElement = (Element)test;\r
146             }\r
147             Object rtest = xpath.selectSingleNode(rightElement);\r
148             if (rtest!=null){\r
149                 rightElement = (Element)rtest;\r
150             }\r
151         }\r
152         boolean res = treeWalk(leftElement, rightElement, "/", list);\r
153         return res;\r
154     }\r
155 \r
156     public static boolean treeWalk(Element left, Element right, String parentPath, TreeWalkResults msgList) throws Exception {\r
157         String SPACE = "     ";\r
158         if (left == null && right == null){\r
159             return true;\r
160         }\r
161         if (left == null){\r
162             return false;\r
163         }\r
164         if (right == null){\r
165             return false;\r
166         }\r
167         List l = left.getChildren();\r
168         Map foundRightMap = new HashMap();\r
169         List<String> foundRepeatingList = new ArrayList<String>();\r
170         boolean result = true;\r
171         for (Object o : l) {\r
172             if (!(o instanceof Element)){\r
173                 continue;\r
174             }\r
175             Element leftChild = (Element)o;\r
176             //String leftChildName = leftChild.getName();\r
177             String leftChildName = leftChild.getQualifiedName();\r
178             if (Tools.isEmpty(leftChildName)){\r
179                 continue;\r
180             }\r
181 \r
182             Namespace namespace =  leftChild.getNamespace();\r
183 \r
184             String leftChildPath = Tools.glue(parentPath, "/", leftChildName);\r
185 \r
186             if (foundRepeatingList.indexOf(leftChildPath)>=0){\r
187                 continue;\r
188             }\r
189             List leftlist = select(left, leftChildName, namespace);\r
190             if (leftlist != null && leftlist.size() > 1){\r
191                 //System.out.println("-----------------doRepeating------"+leftChildPath);\r
192                 foundRepeatingList.add(leftChildPath);\r
193                 boolean repeatingIdentical =\r
194                     doRepeatingFieldComparison(leftlist, leftChildPath, leftChildName, left, right, msgList, namespace) ; //todo: deal with foundRightMap in this repeating field block.\r
195                 if ( ! repeatingIdentical ){\r
196                     //System.out.println("\r\n\r\n\r\n*****************************\r\nOne repeating field failed: "+msgList);\r
197                     return false;\r
198                 }\r
199                 foundRightMap.put(leftChildName, "OK");\r
200             } else {\r
201                 Element rightChild  = (Element)selectSingleNode(right,leftChildName, namespace);\r
202                 if (rightChild == null){\r
203                     TreeWalkEntry entry = new TreeWalkEntry();\r
204                     entry.lpath = leftChildPath;                  //this works, but is questionable: selectSingleNode(right, "//*[local-name() = \"objectexit_common\"]")\r
205                     entry.status = TreeWalkEntry.STATUS.R_MISSING;\r
206                     msgList.add(entry);\r
207                     continue;\r
208                 }\r
209                 foundRightMap.put(leftChildName, "OK");\r
210                 String leftChildTextTrim = leftChild.getText().trim();\r
211                 String rightChildTextTrim = rightChild.getText().trim();\r
212                 TreeWalkEntry entry = new TreeWalkEntry();\r
213                 entry.ltextTrimmed = leftChildTextTrim;\r
214                 entry.rtextTrimmed = rightChildTextTrim;\r
215                 entry.lpath = leftChildPath;\r
216                 entry.rpath = leftChildPath; //same\r
217 \r
218                 if (leftChildTextTrim.equals(rightChildTextTrim)){\r
219                     entry.status = TreeWalkEntry.STATUS.MATCHED;\r
220                     msgList.add(entry);\r
221                 } else {\r
222                     entry.status = TreeWalkEntry.STATUS.TEXT_DIFFERENT;\r
223                     msgList.add(entry);\r
224                 }\r
225                 //============ DIVE !! =====================================================\r
226                 result = result && treeWalk( leftChild, rightChild, leftChildPath, msgList);\r
227             }\r
228         }\r
229         for (Object r : right.getChildren()){\r
230             if (!(r instanceof Element)){\r
231                 continue;\r
232             }\r
233             Element rightChild = (Element)r;\r
234             String rname = rightChild.getQualifiedName();\r
235             if (null==foundRightMap.get(rname)){\r
236                 String rightChildPath = Tools.glue(parentPath, "/", rname);\r
237 \r
238                 TreeWalkEntry entry = new TreeWalkEntry();\r
239                 entry.rpath = rightChildPath;\r
240                 entry.status = TreeWalkEntry.STATUS.R_ADDED;\r
241                 msgList.add(entry);\r
242             }\r
243         }\r
244         return true;\r
245     }\r
246 \r
247     private static void dumpXML_OUT(Element el) throws Exception {\r
248         XMLOutputter outputter = new XMLOutputter();\r
249         outputter.output(el, System.out);\r
250     }\r
251     private static String dumpXML(Element el) throws Exception {\r
252         XMLOutputter outputter = new XMLOutputter();\r
253         return outputter.outputString(el);\r
254     }\r
255 \r
256     public static boolean doRepeatingFieldComparison(List leftList, String leftChildPath, String leftChildName, Element left, Element right, TreeWalkResults msgList, Namespace namespace)\r
257     throws Exception {\r
258         //todo: deal with foundRightMap in this repeating field block.\r
259         List rightList = select(right, leftChildName, namespace);\r
260         if (rightList == null || rightList.size() == 0 || rightList.size() < leftList.size()){\r
261             TreeWalkEntry twe = new TreeWalkEntry();\r
262             twe.lpath = leftChildPath;\r
263             twe.status = TreeWalkEntry.STATUS.R_MISSING;\r
264             String rmsg = (rightList == null)\r
265                     ? " Right: 0"\r
266                     : " Right: "+rightList.size();\r
267             twe.message = "Repeating field count not matched. Field: "+leftChildPath+" Left: "+leftList.size()+rmsg;\r
268             msgList.add(twe);\r
269             return false;\r
270         }\r
271         if (rightList.size() > leftList.size()){\r
272             TreeWalkEntry twe = new TreeWalkEntry();\r
273             twe.lpath = leftChildPath;\r
274             twe.status = TreeWalkEntry.STATUS.R_ADDED;\r
275             twe.message = "Repeating field count not matched. Field: "+leftChildPath+" Left: "+leftList.size()+" Right: "+rightList.size();\r
276             msgList.add(twe);\r
277             return false;\r
278         }\r
279 \r
280         for (Object le : leftList){\r
281             boolean found = false;\r
282             Element leftEl = (Element)le;\r
283             //pl("left", leftEl);\r
284             for(Object re : rightList){\r
285                 Element rightEl = (Element)re;\r
286                 //pl("right", rightEl);\r
287                 TreeWalkResults msgListInner = new TreeWalkResults();\r
288                 treeWalk(leftEl, rightEl, leftChildPath, msgListInner);\r
289                 if (msgListInner.isStrictMatch()){\r
290                     found = true;\r
291                     TreeWalkEntry twe = new TreeWalkEntry();\r
292                     twe.lpath = leftChildPath;\r
293                     twe.status = TreeWalkEntry.STATUS.MATCHED;\r
294                     msgList.add(twe);\r
295                     //System.out.println("===========================\r\nfound match for "+leftEl+"\r\n===========================\r\n");\r
296                     rightList.remove(re); //found it, don't need to inspect this element again.  Since we are breaking from loop, removing element won't mess up iterator--we get a new one on the next loop.\r
297                     break;\r
298                 }\r
299             }\r
300             if ( ! found){\r
301                 TreeWalkEntry twe = new TreeWalkEntry();\r
302                 twe.lpath = leftChildPath;\r
303                 twe.status = TreeWalkEntry.STATUS.R_MISSING;\r
304                 twe.message = "Repeating field not matched. Source: {"+dumpXML(leftEl)+"}";\r
305                 msgList.add(twe);\r
306                 return false;\r
307             }\r
308         }\r
309         return true;\r
310     }\r
311 \r
312     private static void pl(String name, Element el) throws Exception {\r
313         Namespace namespace = el.getNamespace();\r
314         Object lobid = selectSingleNode(el, "@ID", namespace);\r
315         String lid = "";\r
316         if (lobid!=null){\r
317             lid = lobid.toString();\r
318         }\r
319 \r
320         System.out.println(name+": "+lid);\r
321         dumpXML_OUT(el);\r
322         System.out.println();\r
323 \r
324     }\r
325 }\r