]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
fd49f9358a50990f62c30cf81f077ba2aee5f798
[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, TreeWalkResults.MatchSpec matchSpec){\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, matchSpec);\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, TreeWalkResults.MatchSpec matchSpec) 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, matchSpec);\r
153         return res;\r
154     }\r
155 \r
156     public static boolean treeWalk(Element left, Element right, String parentPath, TreeWalkResults msgList, TreeWalkResults.MatchSpec matchSpec) 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, matchSpec) ; //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, matchSpec);\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,\r
257                                                                                      String leftChildPath,\r
258                                                                                      String leftChildName,\r
259                                                                                      Element left,\r
260                                                                                      Element right,\r
261                                                                                      TreeWalkResults msgList,\r
262                                                                                      Namespace namespace,\r
263                                                                                      TreeWalkResults.MatchSpec matchSpec)\r
264     throws Exception {\r
265         //todo: deal with foundRightMap in this repeating field block.\r
266         List rightList = select(right, leftChildName, namespace);\r
267         if (rightList == null || rightList.size() == 0 || rightList.size() < leftList.size()){\r
268             TreeWalkEntry twe = new TreeWalkEntry();\r
269             twe.lpath = leftChildPath;\r
270             twe.status = TreeWalkEntry.STATUS.R_MISSING;\r
271             String rmsg = (rightList == null)\r
272                     ? " Right: 0"\r
273                     : " Right: "+rightList.size();\r
274             twe.message = "Repeating field count not matched. Field: "+leftChildPath+" Left: "+leftList.size()+rmsg;\r
275             msgList.add(twe);\r
276             return false;\r
277         }\r
278         if (rightList.size() > leftList.size()){\r
279             TreeWalkEntry twe = new TreeWalkEntry();\r
280             twe.lpath = leftChildPath;\r
281             twe.status = TreeWalkEntry.STATUS.R_ADDED;\r
282             twe.message = "Repeating field count not matched. Field: "+leftChildPath+" Left: "+leftList.size()+" Right: "+rightList.size();\r
283             msgList.add(twe);\r
284             //LC 20110429 return false;\r
285         }\r
286 \r
287         for (Object le : leftList){\r
288             boolean found = false;\r
289             Element leftEl = (Element)le;\r
290             //pl("left", leftEl);\r
291             for(Object re : rightList){\r
292                 Element rightEl = (Element)re;\r
293                 //pl("right", rightEl);\r
294                 TreeWalkResults msgListInner = new TreeWalkResults();\r
295                 //========== DIVE !!! =======================\r
296                 treeWalk(leftEl, rightEl, leftChildPath, msgListInner, matchSpec);\r
297                 //========================================\r
298 \r
299                 if (msgListInner.treesMatch(matchSpec)){   //if (msgListInner.isStrictMatch()){\r
300                     found = true;\r
301                     TreeWalkEntry twe = new TreeWalkEntry();\r
302                     twe.lpath = leftChildPath;\r
303                     twe.status = TreeWalkEntry.STATUS.MATCHED;\r
304                     msgList.add(twe);\r
305                     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
306                     break;\r
307                 } else {\r
308                     TreeWalkEntry twe = new TreeWalkEntry();\r
309                     twe.lpath = leftChildPath;\r
310                     twe.status = TreeWalkEntry.STATUS.NESTED_ERROR;\r
311                     twe.nested = msgListInner;\r
312                     msgList.add(twe);\r
313                     //String line = "\r\n\r\n*********************************\r\n";\r
314                     //System.out.println(line+"TreeWalkResults: from walking rightEl: "+rightEl+" leftEl: "+leftEl + " msgListInner:"+ msgListInner+line);\r
315                 }\r
316             }  // END for(rightList)\r
317             if ( ! found){\r
318                 TreeWalkEntry twe = new TreeWalkEntry();\r
319                 twe.lpath = leftChildPath;\r
320                 twe.status = TreeWalkEntry.STATUS.R_MISSING;\r
321                 twe.message = "Repeating field not matched. Source: {"+dumpXML(leftEl)+"}";\r
322                 msgList.add(twe);\r
323                 return false;\r
324             }\r
325         }  // END for(leftLlist)\r
326         return true;\r
327     }\r
328 \r
329     private static void pl(String name, Element el) throws Exception {\r
330         Namespace namespace = el.getNamespace();\r
331         Object lobid = selectSingleNode(el, "@ID", namespace);\r
332         String lid = "";\r
333         if (lobid!=null){\r
334             lid = lobid.toString();\r
335         }\r
336 \r
337         System.out.println(name+": "+lid);\r
338         dumpXML_OUT(el);\r
339         System.out.println();\r
340 \r
341     }\r
342 }\r