KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jdiff > APIHandler


1 package jdiff;
2
3 import java.io.*;
4 import java.util.*;
5
6 /* For SAX parsing in APIHandler */
7 import org.xml.sax.Attributes JavaDoc;
8 import org.xml.sax.SAXException JavaDoc;
9 import org.xml.sax.SAXParseException JavaDoc;
10 import org.xml.sax.XMLReader JavaDoc;
11 import org.xml.sax.helpers.DefaultHandler JavaDoc;
12
13 /**
14  * Handle the parsing of an XML file and the generation of an API object.
15  *
16  * See the file LICENSE.txt for copyright details.
17  * @author Matthew Doar, doar@pobox.com
18  */

19 class APIHandler extends DefaultHandler JavaDoc {
20
21     /** The API object which is populated from the XML file. */
22     public API api_;
23
24     /** Default constructor. */
25     public APIHandler(API api, boolean createGlobalComments) {
26         api_ = api;
27         createGlobalComments_ = createGlobalComments;
28         tagStack = new LinkedList();
29     }
30
31     /** If set, then check that each comment is a sentence. */
32     public static boolean checkIsSentence = false;
33
34     /**
35      * Contains the name of the current package element type
36      * where documentation is being added. Also used as the level
37      * at which to add documentation into an element, i.e. class-level
38      * or package-level.
39      */

40     private String JavaDoc currentElement = null;
41
42     /** If set, then create the global list of comments. */
43     private boolean createGlobalComments_ = false;
44
45     /** Set if inside a doc element. */
46     private boolean inDoc = false;
47
48     /** The current comment text being assembled. */
49     private String JavaDoc currentText = null;
50
51     /** The current text from deprecation, null if empty. */
52     private String JavaDoc currentDepText = null;
53
54     /**
55      * The stack of SingleComment objects awaiting the comment text
56      * currently being assembled.
57      */

58     private LinkedList tagStack = null;
59
60     /** Called at the start of the document. */
61     public void startDocument() {
62     }
63     
64     /** Called when the end of the document is reached. */
65     public void endDocument() {
66         if (trace)
67             api_.dump();
68         System.out.println(" finished");
69     }
70
71     /** Called when a new element is started. */
72     public void startElement(java.lang.String JavaDoc uri, java.lang.String JavaDoc localName,
73                              java.lang.String JavaDoc qName, Attributes JavaDoc attributes) {
74      // The change to JAXP compliance produced this change.
75
if (localName.equals(""))
76         localName = qName;
77         if (localName.compareTo("api") == 0) {
78             String JavaDoc apiName = attributes.getValue("name");
79             String JavaDoc version = attributes.getValue("jdversion"); // Not used yet
80
XMLToAPI.nameAPI(apiName);
81         } else if (localName.compareTo("package") == 0) {
82             currentElement = localName;
83             String JavaDoc pkgName = attributes.getValue("name");
84             XMLToAPI.addPackage(pkgName);
85         } else if (localName.compareTo("class") == 0) {
86             currentElement = localName;
87             String JavaDoc className = attributes.getValue("name");
88             String JavaDoc parentName = attributes.getValue("extends");
89             boolean isAbstract = false;
90             if (attributes.getValue("abstract").compareTo("true") == 0)
91                 isAbstract = true;
92             XMLToAPI.addClass(className, parentName, isAbstract, getModifiers(attributes));
93         } else if (localName.compareTo("interface") == 0) {
94             currentElement = localName;
95             String JavaDoc className = attributes.getValue("name");
96             String JavaDoc parentName = attributes.getValue("extends");
97             boolean isAbstract = false;
98             if (attributes.getValue("abstract").compareTo("true") == 0)
99                 isAbstract = true;
100             XMLToAPI.addInterface(className, parentName, isAbstract, getModifiers(attributes));
101         } else if (localName.compareTo("implements") == 0) {
102             String JavaDoc interfaceName = attributes.getValue("name");
103             XMLToAPI.addImplements(interfaceName);
104         } else if (localName.compareTo("constructor") == 0) {
105             currentElement = localName;
106             String JavaDoc ctorType = attributes.getValue("type");
107             XMLToAPI.addCtor(ctorType, getModifiers(attributes));
108         } else if (localName.compareTo("method") == 0) {
109             currentElement = localName;
110             String JavaDoc methodName = attributes.getValue("name");
111             String JavaDoc returnType = attributes.getValue("return");
112             boolean isAbstract = false;
113             if (attributes.getValue("abstract").compareTo("true") == 0)
114                 isAbstract = true;
115             boolean isNative = false;
116             if (attributes.getValue("native").compareTo("true") == 0)
117                 isNative = true;
118             boolean isSynchronized = false;
119             if (attributes.getValue("synchronized").compareTo("true") == 0)
120                 isSynchronized = true;
121             XMLToAPI.addMethod(methodName, returnType, isAbstract, isNative,
122                                isSynchronized, getModifiers(attributes));
123         } else if (localName.compareTo("field") == 0) {
124             currentElement = localName;
125             String JavaDoc fieldName = attributes.getValue("name");
126             String JavaDoc fieldType = attributes.getValue("type");
127             boolean isTransient = false;
128             if (attributes.getValue("transient").compareTo("true") == 0)
129                 isTransient = true;
130             boolean isVolatile = false;
131             if (attributes.getValue("volatile").compareTo("true") == 0)
132                 isVolatile = true;
133             String JavaDoc value = attributes.getValue("value");
134             XMLToAPI.addField(fieldName, fieldType, isTransient, isVolatile,
135                               value, getModifiers(attributes));
136         } else if (localName.compareTo("param") == 0) {
137             String JavaDoc paramName = attributes.getValue("name");
138             String JavaDoc paramType = attributes.getValue("type");
139             XMLToAPI.addParam(paramName, paramType);
140         } else if (localName.compareTo("exception") == 0) {
141             String JavaDoc paramName = attributes.getValue("name");
142             String JavaDoc paramType = attributes.getValue("type");
143             XMLToAPI.addException(paramName, paramType, currentElement);
144         } else if (localName.compareTo("doc") == 0) {
145             inDoc = true;
146             currentText = null;
147         } else {
148             if (inDoc) {
149                 // Start of an element, probably an HTML element
150
addStartTagToText(localName, attributes);
151             } else {
152                 System.out.println("Error: unknown element type: " + localName);
153                 System.exit(-1);
154             }
155         }
156     }
157     
158     /** Called when the end of an element is reached. */
159     public void endElement(java.lang.String JavaDoc uri, java.lang.String JavaDoc localName,
160                            java.lang.String JavaDoc qName) {
161     if (localName.equals(""))
162         localName = qName;
163         // Deal with the end of doc blocks
164
if (localName.compareTo("doc") == 0) {
165             inDoc = false;
166             // Add the assembled comment text to the appropriate current
167
// program element, as determined by currentElement.
168
addTextToComments();
169         } else if (inDoc) {
170             // An element was found inside the HTML text
171
addEndTagToText(localName);
172         } else if (currentElement.compareTo("constructor") == 0 &&
173                    localName.compareTo("constructor") == 0) {
174             currentElement = "class";
175         } else if (currentElement.compareTo("method") == 0 &&
176                    localName.compareTo("method") == 0) {
177             currentElement = "class";
178         } else if (currentElement.compareTo("field") == 0 &&
179                    localName.compareTo("field") == 0) {
180             currentElement = "class";
181         } else if (currentElement.compareTo("class") == 0 ||
182                    currentElement.compareTo("interface") == 0) {
183             // Feature request 510307 and bug 517383: duplicate comment ids.
184
// The end of a member element leaves the currentElement at the
185
// "class" level, but the next class may in fact be an interface
186
// and so the currentElement here will be "interface".
187
if (localName.compareTo("class") == 0 ||
188                 localName.compareTo("interface") == 0) {
189                 currentElement = "package";
190             }
191         }
192     }
193
194     /** Called to process text. */
195     public void characters(char[] ch, int start, int length) {
196          if (inDoc) {
197             String JavaDoc chunk = new String JavaDoc(ch, start, length);
198             if (currentText == null)
199                 currentText = chunk;
200             else
201                 currentText += chunk;
202          }
203     }
204
205     /**
206      * Trim the current text, check it is a sentence and add it to the
207      * current program element.
208      */

209     public void addTextToComments() {
210         // Eliminate any whitespace at each end of the text.
211
currentText = currentText.trim();
212         // Convert any @link tags to HTML links.
213
if (convertAtLinks) {
214             currentText = Comments.convertAtLinks(currentText, currentElement,
215                                                   api_.currPkg_, api_.currClass_);
216         }
217         // Check that it is a sentence
218
if (checkIsSentence && !currentText.endsWith(".") &&
219             currentText.compareTo(Comments.placeHolderText) != 0) {
220             System.out.println("Warning: text of comment does not end in a period: " + currentText);
221         }
222         // The construction of the commentID assumes that the
223
// documentation is the final element to be parsed. The format matches
224
// the format used in the report generator to look up comments in the
225
// the existingComments object.
226
String JavaDoc commentID = null;
227         // Add this comment to the current API element.
228
if (currentElement.compareTo("package") == 0) {
229             api_.currPkg_.doc_ = currentText;
230             commentID = api_.currPkg_.name_;
231         } else if (currentElement.compareTo("class") == 0 ||
232                    currentElement.compareTo("interface") == 0) {
233             api_.currClass_.doc_ = currentText;
234             commentID = api_.currPkg_.name_ + "." + api_.currClass_.name_;
235         } else if (currentElement.compareTo("constructor") == 0) {
236             api_.currCtor_.doc_ = currentText;
237             commentID = api_.currPkg_.name_ + "." + api_.currClass_.name_ +
238                 ".ctor_changed(";
239             if (api_.currCtor_.type_.compareTo("void") == 0)
240                 commentID = commentID + ")";
241             else
242                 commentID = commentID + api_.currCtor_.type_ + ")";
243         } else if (currentElement.compareTo("method") == 0) {
244             api_.currMethod_.doc_ = currentText;
245             commentID = api_.currPkg_.name_ + "." + api_.currClass_.name_ +
246                 "." + api_.currMethod_.name_ + "_changed(" +
247                 api_.currMethod_.getSignature() + ")";
248         } else if (currentElement.compareTo("field") == 0) {
249             api_.currField_.doc_ = currentText;
250             commentID = api_.currPkg_.name_ + "." + api_.currClass_.name_ +
251                 "." + api_.currField_.name_;
252         }
253         // Add to the list of possible comments for use when an
254
// element has changed (not removed or added).
255
if (createGlobalComments_ && commentID != null) {
256             String JavaDoc ct = currentText;
257             // Use any deprecation text as the possible comment, ignoring
258
// any other comment text.
259
if (currentDepText != null) {
260                 ct = currentDepText;
261                 currentDepText = null; // Never reuse it. Bug 469794
262
}
263             String JavaDoc ctOld = (String JavaDoc)(Comments.allPossibleComments.put(commentID, ct));
264             if (ctOld != null) {
265                 System.out.println("Error: duplicate comment id: " + commentID);
266                 System.exit(5);
267             }
268         }
269     }
270
271     /**
272      * Add the start tag to the current comment text.
273      */

274     public void addStartTagToText(String JavaDoc localName, Attributes JavaDoc attributes) {
275         // Need to insert the HTML tag into the current text
276
String JavaDoc currentHTMLTag = localName;
277         // Save the tag in a stack
278
tagStack.add(currentHTMLTag);
279         String JavaDoc tag = "<" + currentHTMLTag;
280         // Now add all the attributes into the current text
281
int len = attributes.getLength();
282         for (int i = 0; i < len; i++) {
283             String JavaDoc name = attributes.getLocalName(i);
284             String JavaDoc value = attributes.getValue(i);
285             tag += " " + name + "=\"" + value+ "\"";
286         }
287
288         // End the tag
289
if (Comments.isMinimizedTag(currentHTMLTag)) {
290             tag += "/>";
291         } else {
292             tag += ">";
293         }
294         // Now insert the HTML tag into the current text
295
if (currentText == null)
296             currentText = tag;
297         else
298             currentText += tag;
299     }
300
301     /**
302      * Add the end tag to the current comment text.
303      */

304     public void addEndTagToText(String JavaDoc localName) {
305         // Close the current HTML tag
306
String JavaDoc currentHTMLTag = (String JavaDoc)(tagStack.removeLast());
307         if (!Comments.isMinimizedTag(currentHTMLTag))
308             currentText += "</" + currentHTMLTag + ">";
309     }
310
311     /** Extra modifiers which are common to all program elements. */
312     public Modifiers getModifiers(Attributes JavaDoc attributes) {
313         Modifiers modifiers = new Modifiers();
314         modifiers.isStatic = false;
315         if (attributes.getValue("static").compareTo("true") == 0)
316             modifiers.isStatic = true;
317         modifiers.isFinal = false;
318         if (attributes.getValue("final").compareTo("true") == 0)
319             modifiers.isFinal = true;
320         modifiers.isDeprecated = false;
321         String JavaDoc cdt = attributes.getValue("deprecated");
322         if (cdt.compareTo("not deprecated") == 0) {
323             modifiers.isDeprecated = false;
324             currentDepText = null;
325         } else if (cdt.compareTo("deprecated, no comment") == 0) {
326             modifiers.isDeprecated = true;
327             currentDepText = null;
328         } else {
329             modifiers.isDeprecated = true;
330             currentDepText = API.showHTMLTags(cdt);
331         }
332         modifiers.visibility = attributes.getValue("visibility");
333         return modifiers;
334     }
335
336     public void warning(SAXParseException JavaDoc e) {
337         System.out.println("Warning (" + e.getLineNumber() + "): parsing XML API file:" + e);
338         e.printStackTrace();
339     }
340
341     public void error(SAXParseException JavaDoc e) {
342         System.out.println("Error (" + e.getLineNumber() + "): parsing XML API file:" + e);
343         e.printStackTrace();
344         System.exit(1);
345     }
346     
347     public void fatalError(SAXParseException JavaDoc e) {
348         System.out.println("Fatal Error (" + e.getLineNumber() + "): parsing XML API file:" + e);
349         e.printStackTrace();
350         System.exit(1);
351     }
352
353     /**
354      * If set, then attempt to convert @link tags to HTML links.
355      * A few of the HTML links may be broken links.
356      */

357     private static boolean convertAtLinks = true;
358
359     /** Set to enable increased logging verbosity for debugging. */
360     private static boolean trace = false;
361
362 }
363
Popular Tags