Update jflex to 1.8.2
[scilab.git] / scilab / modules / helptools / src / java / org / scilab / modules / helptools / DocbookTagConverter.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - Calixte DENIZET
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 package org.scilab.modules.helptools;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Stack;
27
28 import javax.xml.parsers.ParserConfigurationException;
29 import javax.xml.parsers.SAXParser;
30 import javax.xml.parsers.SAXParserFactory;
31
32 import org.scilab.modules.commons.ScilabConstants;
33 import org.scilab.modules.helptools.external.ExternalXMLHandler;
34 import org.scilab.modules.helptools.image.Image;
35 import org.scilab.modules.helptools.image.ImageConverter;
36 import org.scilab.modules.helptools.image.LaTeXImageConverter;
37 import org.scilab.modules.helptools.image.MathMLImageConverter;
38 import org.scilab.modules.helptools.image.SVGImageConverter;
39 import org.scilab.modules.helptools.image.ScilabImageConverter;
40 import org.scilab.modules.helptools.image.XcosImageConverter;
41 import org.xml.sax.Attributes;
42 import org.xml.sax.InputSource;
43 import org.xml.sax.Locator;
44 import org.xml.sax.SAXException;
45 import org.xml.sax.helpers.DefaultHandler;
46
47 /**
48  * Class the convert a DocBook xml file
49  * @author Calixte DENIZET
50  */
51 public abstract class DocbookTagConverter extends DefaultHandler implements Converter {
52
53     private static final String DOCBOOKURI = "http://docbook.org/ns/docbook";
54     private static final Class<?>[] argsType = new Class[] {Map.class, String.class};
55     protected static final String SCI = ScilabConstants.SCI.getPath();
56
57     private Map<String, Method> mapMeth = new HashMap<String, Method>();
58     private Map<String, ExternalXMLHandler> externalHandlers = new HashMap<String, ExternalXMLHandler>();
59     private List<DocbookTagConverter> converters;
60     private final ImageConverter imgConvert;
61     private final File in;
62     private DocbookElement baseElement = new DocbookElement(null, null, null);
63     private Stack<DocbookElement> stack = new Stack<DocbookElement>();
64     private String errors = "";
65
66     /**
67      * True when an error is met during the parsing
68      */
69     protected boolean hasError;
70
71     /**
72      * The file which is parsed
73      */
74     protected String currentFileName;
75
76     /**
77      * The file which is parsed
78      */
79     protected String currentBaseName;
80
81     /**
82      * Useful to locate the errors
83      */
84     protected Locator locator;
85
86     /**
87      * Constructor
88      * @param in the input file path
89      */
90     public DocbookTagConverter(String in, final ImageConverter imgConvert) throws IOException {
91         if (in != null && !in.isEmpty()) {
92             this.in = new File(in);
93         } else {
94             this.in = null;
95         }
96
97         this.imgConvert = imgConvert;
98         imgConvert.registerExternalImageConverter(new LaTeXImageConverter(this));
99         imgConvert.registerExternalImageConverter(new MathMLImageConverter(this));
100         imgConvert.registerExternalImageConverter(new SVGImageConverter(this));
101         imgConvert.registerExternalImageConverter(new ScilabImageConverter(this));
102         imgConvert.registerExternalImageConverter(new XcosImageConverter(this));
103     }
104
105     /**
106      * Constructor
107      * @param in the inputstream
108      * @param inName the name of the input file
109      */
110     public DocbookTagConverter(String inName, DocbookElement elem, final ImageConverter imgConvert) throws IOException {
111         this(inName, imgConvert);
112         baseElement = elem;
113     }
114
115     public ImageConverter getImageConverter() {
116         return imgConvert;
117     }
118
119     public String getBaseImagePath() {
120         return "";
121     }
122
123     /**
124      * Hook used by {@link ImageConverter}s to emit format specific code from any docbook image element
125      * @param code the code to translate
126      * @param fileName the filename
127      * @param attrs the attribute of the image
128      * @return a {@link Converter} specific code which embed the image and the source code
129      */
130     public abstract String generateImageCode(String code, String fileName, Map<String, String> attrs);
131
132     /**
133      * Hook used by {@link ImageConverter}s to emit format specific code from any docbook image element
134      * @param img image information
135      * @param fileName the filename
136      * @param attrs the attribute of the image
137      * @return a {@link Converter} specific code which embed the image and the source code
138      */
139     public abstract String generateImageCode(Image img, String fileName, Map<String, String> attrs);
140
141     /**
142      * Hook used by {@link ImageConverter}s to emit format specific code from any docbook image element
143      * @param fileName the filename
144      * @param attrs the attribute of the image
145      * @return a {@link Converter} specific code which embed the image and the source code
146      */
147     public abstract String generateImageCode(String fileName, Map<String, String> attrs);
148
149     /**
150      * Handle the tag
151      * @param tag the tag to handle
152      * @param attributes the attributes as a Map
153      * @param contents the contents between the matching tags
154      * @return the HTML code
155      * @throws UnhandledDocbookTagException if an handled tga is encountered
156      */
157     public String handleDocbookTag(String tag, Map<String, String> attributes, String contents) throws SAXException {
158         if (tag != null && tag.length() > 0) {
159             Method method = mapMeth.get(tag);
160             if (method == null) {
161                 String name = "handle" + Character.toString(Character.toUpperCase(tag.charAt(0))) + tag.substring(1);
162                 try {
163                     method = this.getClass().getMethod(name, argsType);
164                     mapMeth.put(tag, method);
165                 } catch (NoSuchMethodException e) {
166                     throw new UnhandledDocbookTagException(tag);
167                 }
168             }
169             try {
170                 return (String) method.invoke(this, new Object[] {attributes, contents});
171             } catch (IllegalAccessException e) {
172                 throw new UnhandledDocbookTagException(tag);
173             } catch (InvocationTargetException e) {
174                 throw new SAXException("Problem with tag " + tag + "\n" + e.getCause());
175             }
176         } else {
177             throw new UnhandledDocbookTagException(tag);
178         }
179     }
180
181     public String getCurrentFileName() {
182         return currentFileName;
183     }
184
185     public String getCurrentBaseName() {
186         return currentBaseName;
187     }
188
189     /**
190      * Register an Docbook tag converter. The aim is to parse the xml one time.
191      * @param c the converter to register
192      */
193     public void registerConverter(DocbookTagConverter c) {
194         if (converters == null) {
195             converters = new ArrayList<DocbookTagConverter>();
196         }
197
198         converters.add(c);
199         c.setDocumentLocator(locator);
200     }
201
202     /**
203      * @param c the converter to remove
204      */
205     public void removeConverter(DocbookTagConverter c) {
206         if (converters != null) {
207             converters.remove(c);
208         }
209     }
210
211     /**
212      * @return all the registered converters
213      */
214     public DocbookTagConverter[] getConverters() {
215         if (converters == null) {
216             return null;
217         }
218
219         return converters.toArray(new DocbookTagConverter[0]);
220     }
221
222     /**
223      * Register an XMLHandler for external XML
224      * @param h the external XML handler
225      */
226     protected void registerExternalXMLHandler(ExternalXMLHandler h) {
227         if (externalHandlers.get(h.getURI()) == null) {
228             externalHandlers.put(h.getURI(), h);
229             h.setConverter(this);
230         }
231     }
232
233     /**
234      * Register all needed External XML Handler.
235      */
236     @Override
237     public void registerAllExternalXMLHandlers() {
238     }
239
240     /**
241      * Unregister all External XML Handler
242      */
243     public void unregisterAllExternalXMLHandler() {
244         for (ExternalXMLHandler h : externalHandlers.values()) {
245             h.setConverter(null);
246         }
247         externalHandlers.clear();
248     }
249
250     /**
251      * @param tagName the tag name
252      * @return true if the contents of the tag must be escaped
253      */
254     public boolean isEscapable(String tagName, String uri) {
255         return true;
256     }
257
258     /**
259      * @param tagName the tag name
260      * @return true if the contents of the tag must be trimed
261      */
262     public boolean isTrimable(String tagName) {
263         return true;
264     }
265
266     /**
267      * @return the parent tag name
268      */
269     public String getParentTagName() {
270         return stack.peek().getName();
271     }
272
273     /**
274      * @return the parent tag contents
275      */
276     public String getParentContent() {
277         return stack.peek().getStringBuilder().toString();
278     }
279
280     /**
281      * Start the conversion
282      * @throws SAXException if a problem is encountered during the parsing
283      * @throws IOException if an IO problem is encountered
284      */
285     public void convert() throws SAXException, IOException {
286         SAXParserFactory factory = SAXParserFactory.newInstance();
287         factory.setValidating(false);
288         factory.setNamespaceAware(true);
289         factory.setXIncludeAware(true);
290
291         try {
292             factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
293             SAXParser parser = factory.newSAXParser();
294             // Must be uncommented to be able to read comments
295             //parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
296             parser.parse(in, this);
297         } catch (ParserConfigurationException e) {
298             exceptionOccurred(e);
299         } catch (SAXException e) {
300             System.err.println(e);
301         } catch (IOException e) {
302             System.err.println(e);
303         }
304
305         if (hasError) {
306             throw new SAXException(errors);
307         }
308     }
309
310     /**
311      * Install not converted files (templates, images) to the converted directory
312      */
313     public void install() {
314     }
315
316     /**
317      * {@inheritDoc}
318      */
319     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
320         if (publicId != null) {
321             publicId = publicId.replaceAll(" ", "%20");
322         }
323         if (systemId != null) {
324             systemId = systemId.replaceAll(" ", "%20");
325         }
326
327         currentFileName = systemId;
328         currentBaseName = new File(systemId).getName();
329
330         for (ExternalXMLHandler h : externalHandlers.values()) {
331             h.resetCompt();
332         }
333
334         if (converters != null) {
335             for (DocbookTagConverter conv : converters) {
336                 conv.resolveEntity(publicId, systemId);
337             }
338         }
339
340         return super.resolveEntity(publicId, systemId);
341     }
342
343     /**
344      * {@inheritDoc}
345      */
346     public void startDocument() throws SAXException {
347         stack.push(baseElement.getNewInstance(null, null, null));
348         if (converters != null) {
349             for (DocbookTagConverter conv : converters) {
350                 conv.startDocument();
351             }
352         }
353     }
354
355     /**
356      * {@inheritDoc}
357      */
358     public void endDocument() throws SAXException {
359         stack.clear();
360
361         if (converters != null) {
362             for (DocbookTagConverter conv : converters) {
363                 conv.endDocument();
364             }
365         }
366     }
367
368     /**
369      * {@inheritDoc}
370      */
371     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
372         if (uri.equals(DOCBOOKURI)) {
373             int len = attributes.getLength();
374             Map<String, String> map = new HashMap<String, String>(len);
375             for (int i = 0; i < len; i++) {
376                 map.put(attributes.getLocalName(i), attributes.getValue(i));
377             }
378             stack.push(baseElement.getNewInstance(localName, uri, map));
379         } else {
380             ExternalXMLHandler h = externalHandlers.get(uri);
381             if (h == null) {
382                 exceptionOccurred(new SAXException("uri " + uri + " not handled"));
383                 return;
384             }
385             StringBuilder buf = h.startExternalXML(localName, attributes, locator);
386             if (buf != null) {
387                 DocbookElement elem = baseElement.getNewInstance(localName, uri, null);
388                 elem.setStringBuilder(buf);
389                 stack.push(elem);
390             }
391         }
392
393         if (converters != null) {
394             for (DocbookTagConverter conv : converters) {
395                 conv.startElement(uri, localName, qName, attributes);
396             }
397         }
398     }
399
400     /**
401      * {@inheritDoc}
402      */
403     public void endElement(String uri, String localName, String qName) throws SAXException {
404         if (uri.equals(DOCBOOKURI)) {
405             DocbookElement elem = stack.pop();
406             if (!elem.getName().equals(localName)) {
407                 exceptionOccurred(new SAXException("tag " + elem.getName() + " is closed with tag " + localName));
408                 return;
409             }
410             try {
411                 DocbookElement elemp = stack.peek();
412                 elemp.setParent(elem);
413                 StringBuilder buf = elem.getStringBuilder();
414                 if (isTrimable(elem.getName())) {
415                     buf = trim(buf);
416                 }
417                 String str = handleDocbookTag(elem.getName(), elem.getAttributes(), buf.toString());
418                 if (str != null) {
419                     elemp.getStringBuilder().append(str);
420                 }
421             } catch (SAXException e) {
422                 exceptionOccurred(e);
423                 return;
424             }
425         } else {
426             ExternalXMLHandler h = externalHandlers.get(uri);
427             if (h == null) {
428                 exceptionOccurred(new SAXException("uri " + uri + " not handled"));
429                 return;
430             }
431             String str = h.endExternalXML(localName);
432             if (str != null) {
433                 stack.pop();
434                 stack.peek().getStringBuilder().append(str);
435             }
436         }
437
438         if (converters != null) {
439             for (DocbookTagConverter conv : converters) {
440                 conv.endElement(uri, localName, qName);
441             }
442         }
443     }
444
445     /*public void comment(char[] ch, int start, int length) throws SAXException {
446
447       }*/
448
449     /**
450      * {@inheritDoc}
451      */
452     public void characters(char[] ch, int start, int length) throws SAXException {
453         int end = start + length;
454
455         if (isEscapable(stack.peek().getName(), stack.peek().getURI())) {
456             StringBuilder buf = stack.peek().getStringBuilder();
457             int save = start;
458             for (int i = start; i < end; i++) {
459                 switch (ch[i]) {
460                     case '\'' :
461                         buf.append(ch, save, i - save);
462                         buf.append("&#0039;");
463                         save = i + 1;
464                         break;
465                     case '\"' :
466                         buf.append(ch, save, i - save);
467                         buf.append("&#0034;");
468                         save = i + 1;
469                         break;
470                     case '<' :
471                         buf.append(ch, save, i - save);
472                         buf.append("&lt;");
473                         save = i + 1;
474                         break;
475                     case '>' :
476                         buf.append(ch, save, i - save);
477                         buf.append("&gt;");
478                         save = i + 1;
479                         break;
480                     case '&' :
481                         buf.append(ch, save, i - save);
482                         buf.append("&amp;");
483                         save = i + 1;
484                         break;
485                     default :
486                         break;
487                 }
488             }
489
490             if (save < end) {
491                 buf.append(ch, save, end - save);
492             }
493         } else {
494             stack.peek().getStringBuilder().append(ch, start, length);
495         }
496
497         if (converters != null) {
498             for (DocbookTagConverter conv : converters) {
499                 conv.characters(ch, start, length);
500             }
501         }
502     }
503
504     /**
505      * {@inheritDoc}
506      */
507     public void setDocumentLocator(Locator locator) {
508         this.locator = locator;
509     }
510
511     /**
512      * @return the document locator
513      */
514     public Locator getDocumentLocator() {
515         return locator;
516     }
517
518     /**
519      * @return the used stack
520      */
521     protected Stack<DocbookElement> getStack() {
522         return stack;
523     }
524
525     /**
526      * Handle an exception depending on the presence of a locator
527      * @param e the exception to handle
528      * @throws SAXException if problem
529      */
530     protected void fatalExceptionOccurred(Exception e) throws SAXException {
531         throw new SAXException(errors + "\nFATAL error:\n" + e.getMessage());
532     }
533
534     /**
535      * Handle an exception depending on the presence of a locator
536      * @param e the exception to handle
537      * @throws SAXException if problem
538      */
539     protected void exceptionOccurred(Exception e) {
540         if (!hasError) {
541             hasError = true;
542         }
543         errors += makeErrorMessage(e);
544     }
545
546     private String makeErrorMessage(Exception e) {
547         String sId = "";
548         if (currentFileName != null) {
549             sId = "SystemID:" + currentFileName;
550         }
551
552         String file;
553         try {
554             file = in.getCanonicalPath();
555         } catch (IOException e1) {
556             e1.printStackTrace();
557             file = null;
558         }
559         if (locator != null) {
560             return "\nCannot parse " + file + ":\n" + e.getMessage() + "\n" + sId + " at line " + locator.getLineNumber();
561         } else {
562             return "\nCannot parse " + file + ":\n" + e.getMessage() + "\n" + sId;
563         }
564     }
565
566     /**
567      * @param the StringBuilder to trim
568      * @return a trimed StringBuilder
569      */
570     private static StringBuilder trim(StringBuilder buf) {
571         int i = 0;
572         int end = buf.length();
573         char c;
574         for (; i < end; i++) {
575             c = buf.charAt(i);
576             if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
577                 break;
578             }
579         }
580         buf.delete(0, i);
581         end = end - i;
582         for (i = end - 1; i >= 0; i--) {
583             c = buf.charAt(i);
584             if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
585                 break;
586             }
587         }
588         buf.setLength(i + 1);
589
590         return buf;
591     }
592
593     /*
594      * All Handled tag method definition, these methods are the implementation of "Docbook 5.0 - subset Scilab"
595      */
596
597     public abstract String handleAnswer(final Map<String, String> attributes, final String contents) throws SAXException;
598     public abstract String handleBibliomixed(final Map<String, String> attributes, final String contents) throws SAXException;
599     public abstract String handleBibliomset(final Map<String, String> attributes, final String contents) throws SAXException;
600     public abstract String handleBook(final Map<String, String> attributes, final String contents) throws SAXException;
601     public abstract String handleCaption(final Map<String, String> attributes, final String contents) throws SAXException;
602     public abstract String handleCaution(final Map<String, String> attributes, final String contents) throws SAXException;
603     public abstract String handleChapter(final Map<String, String> attributes, final String contents) throws SAXException;
604     public abstract String handleCode(final Map<String, String> attributes, final String contents) throws SAXException;
605     public abstract String handleCommand(final Map<String, String> attributes, final String contents) throws SAXException;
606     public abstract String handleConstant(final Map<String, String> attributes, final String contents) throws SAXException;
607     public abstract String handleEmphasis(final Map<String, String> attributes, final String contents) throws SAXException;
608     public abstract String handleFirstname(final Map<String, String> attributes, final String contents) throws SAXException;
609     public abstract String handleFunction(final Map<String, String> attributes, final String contents) throws SAXException;
610     public abstract String handleImagedata(final Map<String, String> attributes, final String contents) throws SAXException;
611     public abstract String handleImageobject(final Map<String, String> attributes, final String contents) throws SAXException;
612     public abstract String handleImportant(final Map<String, String> attributes, final String contents) throws SAXException;
613     public abstract String handleInfo(final Map<String, String> attributes, final String contents) throws SAXException;
614     public abstract String handleInformalequation(final Map<String, String> attributes, final String contents) throws SAXException;
615     public abstract String handleInformaltable(final Map<String, String> attributes, final String contents) throws SAXException;
616     public abstract String handleInlinemediaobject(final Map<String, String> attributes, final String contents) throws SAXException;
617     public abstract String handleItemizedlist(final Map<String, String> attributes, final String contents) throws SAXException;
618     public abstract String handleLatex(final Map<String, String> attributes, final String contents) throws SAXException;
619     public abstract String handleLink(final Map<String, String> attributes, final String contents) throws SAXException;
620     public abstract String handleListitem(final Map<String, String> attributes, final String contents) throws SAXException;
621     public abstract String handleLiteral(final Map<String, String> attributes, final String contents) throws SAXException;
622     public abstract String handleLiterallayout(final Map<String, String> attributes, final String contents) throws SAXException;
623     public abstract String handleMediaobject(final Map<String, String> attributes, final String contents) throws SAXException;
624     public abstract String handleMember(final Map<String, String> attributes, final String contents) throws SAXException;
625     public abstract String handleNote(final Map<String, String> attributes, final String contents) throws SAXException;
626     public abstract String handleOption(final Map<String, String> attributes, final String contents) throws SAXException;
627     public abstract String handleOrderedlist(final Map<String, String> attributes, final String contents) throws SAXException;
628     public abstract String handlePara(final Map<String, String> attributes, final String contents) throws SAXException;
629     public abstract String handlePart(final Map<String, String> attributes, final String contents) throws SAXException;
630     public abstract String handleProgramlisting(final Map<String, String> attributes, final String contents) throws SAXException;
631     public abstract String handlePubdate(final Map<String, String> attributes, final String contents) throws SAXException;
632     public abstract String handleQandaentry(final Map<String, String> attributes, final String contents) throws SAXException;
633     public abstract String handleQandaset(final Map<String, String> attributes, final String contents) throws SAXException;
634     public abstract String handleQuestion(final Map<String, String> attributes, final String contents) throws SAXException;
635     public abstract String handleRefentry(final Map<String, String> attributes, final String contents) throws SAXException;
636     public abstract String handleRefnamediv(final Map<String, String> attributes, final String contents) throws SAXException;
637     public abstract String handleRefname(final Map<String, String> attributes, final String contents) throws SAXException;
638     public abstract String handleRefpurpose(final Map<String, String> attributes, final String contents) throws SAXException;
639     public abstract String handleRefsection(final Map<String, String> attributes, final String contents) throws SAXException;
640     public abstract String handleRefsect1(final Map<String, String> attributes, final String contents) throws SAXException;
641     public abstract String handleRefsect2(final Map<String, String> attributes, final String contents) throws SAXException;
642     public abstract String handleRefsect3(final Map<String, String> attributes, final String contents) throws SAXException;
643     public abstract String handleRefsynopsisdiv(final Map<String, String> attributes, final String contents) throws SAXException;
644     public abstract String handleReplaceable(final Map<String, String> attributes, final String contents) throws SAXException;
645     public abstract String handleRevdescription(final Map<String, String> attributes, final String contents) throws SAXException;
646     public abstract String handleRevhistory(final Map<String, String> attributes, final String contents) throws SAXException;
647     public abstract String handleRevision(final Map<String, String> attributes, final String contents) throws SAXException;
648     public abstract String handleRevnumber(final Map<String, String> attributes, final String contents) throws SAXException;
649     public abstract String handleRevremark(final Map<String, String> attributes, final String contents) throws SAXException;
650     public abstract String handleScreen(final Map<String, String> attributes, final String contents) throws SAXException;
651     public abstract String handleScreenshot(final Map<String, String> attributes, final String contents) throws SAXException;
652     public abstract String handleSection(final Map<String, String> attributes, final String contents) throws SAXException;
653     public abstract String handleSimplelist(final Map<String, String> attributes, final String contents) throws SAXException;
654     public abstract String handleSubscript(final Map<String, String> attributes, final String contents) throws SAXException;
655     public abstract String handleSuperscript(final Map<String, String> attributes, final String contents) throws SAXException;
656     public abstract String handleSurname(final Map<String, String> attributes, final String contents) throws SAXException;
657     public abstract String handleSynopsis(final Map<String, String> attributes, final String contents) throws SAXException;
658     public abstract String handleTable(final Map<String, String> attributes, final String contents) throws SAXException;
659     public abstract String handleTbody(final Map<String, String> attributes, final String contents) throws SAXException;
660     public abstract String handleTd(final Map<String, String> attributes, final String contents) throws SAXException;
661     public abstract String handleTerm(final Map<String, String> attributes, final String contents) throws SAXException;
662     public abstract String handleTh(final Map<String, String> attributes, final String contents) throws SAXException;
663     public abstract String handleTip(final Map<String, String> attributes, final String contents) throws SAXException;
664     public abstract String handleTitle(final Map<String, String> attributes, final String contents) throws SAXException;
665     public abstract String handleTr(final Map<String, String> attributes, final String contents) throws SAXException;
666     public abstract String handleUlink(final Map<String, String> attributes, final String contents) throws SAXException;
667     public abstract String handleVariablelist(final Map<String, String> attributes, final String contents) throws SAXException;
668     public abstract String handleVarlistentry(final Map<String, String> attributes, final String contents) throws SAXException;
669     public abstract String handleVarname(final Map<String, String> attributes, final String contents) throws SAXException;
670     public abstract String handleWarning(final Map<String, String> attributes, final String contents) throws SAXException;
671     public abstract String handleXref(final Map<String, String> attributes, final String contents) throws SAXException;
672     public abstract String handleAnchor(final Map<String, String> attributes, final String contents) throws SAXException;
673 }