blob: 29de48e1054bb886a0c01d297b5928cdfc6f29be [file] [log] [blame]
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.ejte.ccl.reporter;
import org.xml.sax.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.*;
import java.io.*;
import java.util.*;
public class ParseML{
private String vendorParserClass =
"org.apache.xerces.parsers.SAXParser";
public static boolean debug = false;
boolean inTestcase = false;
boolean inTestcaseID = false;
boolean gotStatus = false;
static Hashtable hash = null;
static Vector[] fileDiffs = null;
String key = "";
String value = "";
public static void main(String args[]){
ParseML pml = new ParseML();
if(args.length<2){
pml.usage();
}
hash = new Hashtable();
int no_of_files = args.length;
if(debug){
System.out.println("number of files:"+no_of_files);
}
Hashtable[] filehash = new Hashtable[no_of_files];
fileDiffs = new Vector[no_of_files];
for(int i = 0; i<args.length; i++){
filehash[i] = new Hashtable();
fileDiffs[i] = new Vector();
fileDiffs[i].add("</u><b>File:"+args[i]+"</b></u><br>\n"); // add the filename to the vector
System.out.println("parsing file #"+i);
filehash[i] = pml.buildTree(args[i]);
hash = null;
hash = new Hashtable();
if(debug){
System.out.print("========================");
System.out.println("Displaying hashtable # "+i);
pml.displayHash(filehash[i]);
}
}
pml.diffHash(filehash);
pml.displayVectorArr(fileDiffs);
System.out.print("writing diffs to file...");
pml.writeDiffs(fileDiffs);
System.out.println("done");
}
public Hashtable buildTree(String xmlURI){
//hash = null;
try{
//Initialize a reader
XMLReader reader =
XMLReaderFactory.createXMLReader(vendorParserClass);
//Register Content Handler
ContentHandler myContentHandler = new MyContentHandler();
reader.setContentHandler(myContentHandler);
//Parse
InputSource inputSource =
new InputSource(new java.io.FileInputStream(new java.io.File(xmlURI)));
reader.parse(inputSource);
} catch(Throwable th){
th.printStackTrace();
}
return hash;
}
class MyContentHandler implements ContentHandler{
private Locator locator;
public void setDocumentLocator(Locator locator){
this.locator = locator;
}
public void startDocument() throws SAXException{
//initialize a 2D vector here
}
public void endDocument() throws SAXException{
}
public void processingInstruction(String target, String data)
throws SAXException{
// add target and data to the 2D vector
}
public void startPrefixMapping(String prefix, String uri){
}
public void endPrefixMapping(String prefix){
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException{
// add the local name into vector
if(localName.equals("testcase")){
inTestcase = true;
}
if(localName.equals("id") && (inTestcase)){
inTestcaseID = true;
if(debug){
System.out.println("inside testcase id.");
}
}
// assuming that when its time to get the status, the value for the keys would have been obtained.
if(localName.equals("status") && (inTestcase)){
//get attributes: pass/fail
if(debug){
System.out.println("getting testcase status...");
}
value = atts.getValue(0).trim();
if((key!=null) && (!(key.equals(""))) && (value!=null) && (!value.equals(""))){
if(debug){
System.out.println("Key["+key+"] has value["+value+"]");
}
hash.put(key,value);
gotStatus = true;
key = "";
value = "";
}
else{
if(key == null || key.equals("")){
System.out.println("invalid key!");
}
if(value== null || value.equals("")){
System.out.println("invalid value!");
}
}
}
}
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException{
if(localName.equals("testcase")){
inTestcase = false;
if(debug){
System.out.println("Outside testcase tag");
}
}
if(localName.equals("id") && (inTestcase)){
inTestcaseID = false;
if(debug){
System.out.println("Outside testcase-ID tag");
} /*
key = key.trim();
value = value.trim();
if((key!=null) && (value!=null) &&
(!(value.equals(""))) && (!(key.equals("")))){
} */
}
}
public void characters(char[] ch, int start, int length)
throws SAXException{
String s = new String(ch, start, length);
if(debug){
System.out.print("\nvalue of start index= "+start+", ");
System.out.print("length of charectars = "+length+", ");
System.out.println("string = ["+s+"]");
}
if(inTestcaseID){
key += s.trim();
if((key!=null) && (!key.equals(""))){
if(debug){
System.out.println("TestCase ID:"+key);
}
}
}
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException{
}
public void skippedEntity(String name) throws SAXException{
System.out.println("Skipped entity is:"+name);
}
}
/*======= End of Inner Class Definition ================*/
public void displayHash(Hashtable hashtable){
for (Enumeration e = hashtable.keys() ; e.hasMoreElements() ;) {
String keyval = (String)e.nextElement();
System.out.println(keyval +":"+hashtable.get(keyval));
}
}
public void displayVector(Vector v){
for(int i=0; i<v.size(); i++){
System.out.println((String)v.get(i));
}
}
public void displayVectorArr(Vector[] v){
for (int i = 0; i<v.length; i++){
displayVector(v[i]);
}
}
public void writeDiffs(Vector[] v){
try{
File inputfile = new File("fileDiffs.html");
FileWriter fw = new FileWriter(inputfile);
String filecontent = "<h3>File Diff Output</h3><hr>\n";
for(int i = 0; i<v.length ; i++){
for(int j = 0; j<v[i].size(); j++){
filecontent += v[i].get(j)+"<br>\n";
}
filecontent += "<hr>\n";
}
fw.write(filecontent);
fw.close();
} catch(FileNotFoundException fnfe){
System.out.println("File is not present. \n"+
"Please check the file name and try again");
} catch(Exception ex){
ex.printStackTrace();
}
}
public Vector getKeyList(Hashtable[] hashes){
int hashtables = hashes.length;
Vector allkeys= new Vector();
Vector[] hashVecs = new Vector[hashtables];
for(int i=0; i<hashtables; i++){
hashVecs[i] = new Vector((Collection)hashes[i].keySet());
}
allkeys = getUnion(hashVecs);
return allkeys;
}
public Vector getUnion(Vector[] v){
Vector union = new Vector();
for(int i=0; i<v.length; i++){
for(int j=0; j<v[i].size(); j++){
if(!union.contains(v[i].get(j))){
union.add(v[i].get(j));
}//end if
}//end inner-for
}// end outer-for
return union;
}// end method getUnion
public void diffHash(Hashtable[] hashes){
int hashtables = hashes.length;
if(debug){
System.out.println("total hashtables to diff:"+hashtables);
}
int bigHash = 0; // take the first hashtable as the golden file.
/*Get a list of most keys*/
Vector keylist = new Vector();
keylist = getKeyList(hashes);
/*Start comparing all other hashtable elements to this golden list of testcases*/
int totalkeys = keylist.size();
if(debug){
System.out.println("Total number of testcases gathered: "+totalkeys);
}
for(int keyno=0; keyno<totalkeys; keyno++){
String keyObj = (String)keylist.get(keyno);
Object val = null;
Object bigHashVal = null;
// for all hashtables in the array...
if(debug){
System.out.println("checking out key:"+keyObj);
}
for(int i = 0; i<hashtables ; i++){
if(i==bigHash){
continue;
}
// key exists
if((bigHashVal=hashes[bigHash].get(keyObj))!=null){ // key exists in bigHash
if((val = hashes[i].get(keyObj))!=null){
if (val.equals(bigHashVal)){
// key and value pair match the golden file
continue;
} else {
// key exists but the values are different
// add it into both the vectors, if not already there.
String diffObj = "<font color=blue>"+keyObj+
" has an inconsistent status:"+(String)val+
"</font>";
String bigdiffObj = "<font color=blue>"+keyObj+
" has an inconsistent status:"+(String)bigHashVal+
"</font>";
if(!fileDiffs[i].contains(diffObj)){
fileDiffs[i].add(diffObj);
}
if(!fileDiffs[bigHash].contains(bigdiffObj)){
fileDiffs[bigHash].add(bigdiffObj);
}
}
} else {
// key doesn't exist
/*add it into the vector for smaller tables, if not already there.*/
String diffObj = "<font color=red>"+keyObj+
" testcase is missing </font>";
if(!fileDiffs[i].contains(diffObj)){
fileDiffs[i].add(diffObj);
}// end missing-key if
} // end missing-key else
// end key-exists if in bighash
} else {
// add the missing key into the vector for bighash
String bigdiffObj = "<font color=red>"+keyObj+
" testcase is missing </font>";
if(!fileDiffs[bigHash].contains(bigdiffObj)){
fileDiffs[bigHash].add(bigdiffObj);
}// end missing-key if
}
} // end for-loop for going through the hashtable array
} // end for-loop for keys in the bigHash hashtable
} // end diff-hash method
public void usage(){
String usageStr = "Usage:\n java ParseML <xml_file_1> <xml_file_2> <xml_file_3>..."+
"\n\tThis Utility will let you 'diff' multiple xml"+
"\n\t files and produce a fileDiff.html file in the "+
"\n\t directory where this file is run from."+
"\n\tDiff results are produced only by matching the contents "+
"\n\tof the xml trees and not by comparing text characters."+
"\n\n\tThis program takes arguments of two or more 'well_formed_xml' files.";
System.out.println(usageStr);
System.exit(0);
}
}