001    /*
002     * Copyright (c) 2007 Henri Sivonen
003     *
004     * Permission is hereby granted, free of charge, to any person obtaining a 
005     * copy of this software and associated documentation files (the "Software"), 
006     * to deal in the Software without restriction, including without limitation 
007     * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
008     * and/or sell copies of the Software, and to permit persons to whom the 
009     * Software is furnished to do so, subject to the following conditions:
010     *
011     * The above copyright notice and this permission notice shall be included in 
012     * all copies or substantial portions of the Software.
013     *
014     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
015     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
016     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
017     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
018     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
019     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
020     * DEALINGS IN THE SOFTWARE.
021     */
022    
023    package nu.validator.htmlparser.test;
024    
025    import java.io.IOException;
026    import java.io.Writer;
027    import java.util.Map;
028    import java.util.TreeMap;
029    
030    import org.xml.sax.Attributes;
031    import org.xml.sax.ContentHandler;
032    import org.xml.sax.Locator;
033    import org.xml.sax.SAXException;
034    import org.xml.sax.ext.LexicalHandler;
035    
036    public class TreeDumpContentHandler implements ContentHandler, LexicalHandler {
037    
038        private final Writer writer;
039    
040        private int level = 0;
041    
042        private boolean inCharacters = false;
043    
044        private boolean close;
045    
046        /**
047         * @param writer
048         */
049        public TreeDumpContentHandler(final Writer writer, boolean close) {
050            this.writer = writer;
051            this.close = close;
052        }
053    
054        public TreeDumpContentHandler(final Writer writer) {
055            this(writer, true);
056        }
057    
058        private void printLead() throws IOException {
059            if (inCharacters) {
060                writer.write("\"\n");
061                inCharacters = false;
062            }
063            writer.write("| ");
064            for (int i = 0; i < level; i++) {
065                writer.write("  ");
066            }
067        }
068    
069        public void characters(char[] ch, int start, int length)
070                throws SAXException {
071            try {
072                if (!inCharacters) {
073                    printLead();
074                    writer.write('"');
075                    inCharacters = true;
076                }
077                writer.write(ch, start, length);
078            } catch (IOException e) {
079                throw new SAXException(e);
080            }
081        }
082    
083        public void endElement(String uri, String localName, String qName)
084                throws SAXException {
085            try {
086                if (inCharacters) {
087                    writer.write("\"\n");
088                    inCharacters = false;
089                }
090                level--;
091            } catch (IOException e) {
092                throw new SAXException(e);
093            }
094        }
095    
096        public void startElement(String uri, String localName, String qName,
097                Attributes atts) throws SAXException {
098            try {
099                printLead();
100                writer.write('<');
101                writer.write(qName);
102                writer.write(">\n");
103                level++;
104    
105                TreeMap<String, String> map = new TreeMap<String, String>();
106                for (int i = 0; i < atts.getLength(); i++) {
107                    map.put(atts.getQName(i), atts.getValue(i));
108                }
109                for (Map.Entry<String, String> entry : map.entrySet()) {
110                    printLead();
111                    writer.write(entry.getKey());
112                    writer.write("=\"");
113                    writer.write(entry.getValue());
114                    writer.write("\"\n");
115                }
116            } catch (IOException e) {
117                throw new SAXException(e);
118            }
119        }
120    
121        public void comment(char[] ch, int offset, int len) throws SAXException {
122            try {
123                printLead();
124                writer.write("<!-- ");
125                writer.write(ch, offset, len);
126                writer.write(" -->\n");
127            } catch (IOException e) {
128                throw new SAXException(e);
129            }
130        }
131    
132        public void startDTD(String name, String publicIdentifier,
133                String systemIdentifier) throws SAXException {
134            try {
135                printLead();
136                writer.write("<!DOCTYPE ");
137                writer.write(name);
138                writer.write(">\n");
139            } catch (IOException e) {
140                throw new SAXException(e);
141            }
142        }
143    
144        public void endDocument() throws SAXException {
145            try {
146                if (inCharacters) {
147                    writer.write("\"\n");
148                    inCharacters = false;
149                }
150                if (close) {
151                    writer.flush();
152                    writer.close();
153                }
154            } catch (IOException e) {
155                throw new SAXException(e);
156            }
157        }
158    
159        public void startPrefixMapping(String prefix, String uri)
160                throws SAXException {
161        }
162    
163        public void startEntity(String arg0) throws SAXException {
164        }
165    
166        public void endCDATA() throws SAXException {
167        }
168    
169        public void endDTD() throws SAXException {
170        }
171    
172        public void endEntity(String arg0) throws SAXException {
173        }
174    
175        public void startCDATA() throws SAXException {
176        }
177    
178        public void endPrefixMapping(String prefix) throws SAXException {
179        }
180    
181        public void ignorableWhitespace(char[] ch, int start, int length)
182                throws SAXException {
183        }
184    
185        public void processingInstruction(String target, String data)
186                throws SAXException {
187        }
188    
189        public void setDocumentLocator(Locator locator) {
190        }
191    
192        public void skippedEntity(String name) throws SAXException {
193        }
194    
195        public void startDocument() throws SAXException {
196        }
197    
198    }