aboutsummaryrefslogtreecommitdiff
path: root/src/jdiff/CommentsHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdiff/CommentsHandler.java')
-rwxr-xr-xsrc/jdiff/CommentsHandler.java210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/jdiff/CommentsHandler.java b/src/jdiff/CommentsHandler.java
new file mode 100755
index 0000000..8061fbe
--- /dev/null
+++ b/src/jdiff/CommentsHandler.java
@@ -0,0 +1,210 @@
+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 http://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;
+
+}
+