package jdiff;
|
|
import java.io.*;
|
import java.util.*;
|
|
/* For SAX XML parsing */
|
import org.xml.sax.Attributes;
|
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXParseException;
|
import org.xml.sax.XMLReader;
|
import org.xml.sax.helpers.DefaultHandler;
|
|
/**
|
* Handle the parsing of an XML file and the generation of a Comments object.
|
*
|
* All HTML written for the comments sections in the report must
|
* use tags such as <p/> rather than just <p>, since the XML
|
* parser used requires that or matching end elements.
|
*
|
* From https://www.w3.org/TR/2000/REC-xhtml1-20000126:
|
* "Empty elements must either have an end tag or the start tag must end with /<".
|
*
|
* See the file LICENSE.txt for copyright details.
|
* @author Matthew Doar, mdoar@pobox.com
|
*/
|
class CommentsHandler extends DefaultHandler {
|
|
/** The Comments object which is populated from the XML file. */
|
public Comments comments_ = null;
|
|
/** The current SingleComment object being populated. */
|
private List currSingleComment_ = null; // SingleComment[]
|
|
/** Set if in text. */
|
private boolean inText = false;
|
|
/** The current text which is being assembled from chunks. */
|
private String currentText = null;
|
|
/** The stack of SingleComments still waiting for comment text. */
|
private LinkedList tagStack = null;
|
|
/** Default constructor. */
|
public CommentsHandler(Comments comments) {
|
comments_ = comments;
|
tagStack = new LinkedList();
|
}
|
|
public void startDocument() {
|
}
|
|
public void endDocument() {
|
if (trace)
|
comments_.dump();
|
}
|
|
public void startElement(java.lang.String uri, java.lang.String localName,
|
java.lang.String qName, Attributes attributes) {
|
// The change to JAXP compliance produced this change.
|
if (localName.equals(""))
|
localName = qName;
|
if (localName.compareTo("comments") == 0) {
|
String commentsName = attributes.getValue("name");
|
String version = attributes.getValue("jdversion"); // Not used yet
|
if (commentsName == null) {
|
System.out.println("Error: no identifier found in the comments XML file.");
|
System.exit(3);
|
}
|
// Check the given names against the names of the APIs
|
int idx1 = JDiff.oldFileName.lastIndexOf('.');
|
int idx2 = JDiff.newFileName.lastIndexOf('.');
|
String filename2 = JDiff.oldFileName.substring(0, idx1) +
|
"_to_" + JDiff.newFileName.substring(0, idx2);
|
if (filename2.compareTo(commentsName) != 0) {
|
System.out.println("Warning: API identifier in the comments XML file (" + filename2 + ") differs from the name of the file.");
|
}
|
} else if (localName.compareTo("comment") == 0) {
|
currSingleComment_ = new ArrayList(); // SingleComment[];
|
} else if (localName.compareTo("identifier") == 0) {
|
// May have multiple identifiers for one comment's text
|
String id = attributes.getValue("id");
|
SingleComment newComment = new SingleComment(id, null);
|
// Store it here until we can add text to it
|
currSingleComment_.add(newComment);
|
} else if (localName.compareTo("text") == 0) {
|
inText = true;
|
currentText = null;
|
} else {
|
if (inText) {
|
// Start of an element, probably an HTML element
|
addStartTagToText(localName, attributes);
|
} else {
|
System.out.println("Error: unknown element type: " + localName);
|
System.exit(-1);
|
}
|
}
|
}
|
|
public void endElement(java.lang.String uri, java.lang.String localName,
|
java.lang.String qName) {
|
if (localName.equals(""))
|
localName = qName;
|
if (localName.compareTo("text") == 0) {
|
inText = false;
|
addTextToComments();
|
} else if (inText) {
|
addEndTagToText(localName);
|
}
|
|
}
|
|
/** Deal with a chunk of text. The text may come in multiple chunks. */
|
public void characters(char[] ch, int start, int length) {
|
if (inText) {
|
String chunk = new String(ch, start, length);
|
if (currentText == null)
|
currentText = chunk;
|
else
|
currentText += chunk;
|
}
|
}
|
|
/**
|
* Trim the current text, check it is a sentence and add it to all
|
* the comments which are waiting for it.
|
*/
|
public void addTextToComments() {
|
// Eliminate any whitespace at each end of the text.
|
currentText = currentText.trim();
|
// Check that it is a sentence
|
if (!currentText.endsWith(".") &&
|
!currentText.endsWith("?") &&
|
!currentText.endsWith("!") &&
|
currentText.compareTo(Comments.placeHolderText) != 0) {
|
System.out.println("Warning: text of comment does not end in a period: " + currentText);
|
}
|
// Add this comment to all the SingleComments waiting for it
|
Iterator iter = currSingleComment_.iterator();
|
while (iter.hasNext()) {
|
SingleComment currComment = (SingleComment)(iter.next());
|
if (currComment.text_ == null)
|
currComment.text_ = currentText;
|
else
|
currComment.text_ += currentText;
|
comments_.addComment(currComment);
|
}
|
}
|
|
/**
|
* Add the start tag to the current comment text.
|
*/
|
public void addStartTagToText(String localName, Attributes attributes) {
|
// Need to insert the HTML tag into the current text
|
String currentHTMLTag = localName;
|
// Save the tag in a stack
|
tagStack.add(currentHTMLTag);
|
String tag = "<" + currentHTMLTag;
|
// Now add all the attributes into the current text
|
int len = attributes.getLength();
|
for (int i = 0; i < len; i++) {
|
String name = attributes.getLocalName(i);
|
String value = attributes.getValue(i);
|
tag += " " + name + "=\"" + value+ "\"";
|
}
|
|
// End the tag
|
if (Comments.isMinimizedTag(currentHTMLTag)) {
|
tag += "/>";
|
} else {
|
tag += ">";
|
}
|
// Now insert the HTML tag into the current text
|
if (currentText == null)
|
currentText = tag;
|
else
|
currentText += tag;
|
}
|
|
/**
|
* Add the end tag to the current comment text.
|
*/
|
public void addEndTagToText(String localName) {
|
// Close the current HTML tag
|
String currentHTMLTag = (String)(tagStack.removeLast());
|
if (!Comments.isMinimizedTag(currentHTMLTag))
|
currentText += "</" + currentHTMLTag + ">";
|
}
|
|
public void warning(SAXParseException e) {
|
System.out.println("Warning (" + e.getLineNumber() + "): parsing XML comments file:" + e);
|
e.printStackTrace();
|
}
|
|
public void error(SAXParseException e) {
|
System.out.println("Error (" + e.getLineNumber() + "): parsing XML comments file:" + e);
|
e.printStackTrace();
|
System.exit(1);
|
}
|
|
public void fatalError(SAXParseException e) {
|
System.out.println("Fatal Error (" + e.getLineNumber() + "): parsing XML comments file:" + e);
|
e.printStackTrace();
|
System.exit(1);
|
}
|
|
/** Set to enable increased logging verbosity for debugging. */
|
private static final boolean trace = false;
|
|
}
|