Source Code Cross Referenced for IndentingXMLEventWriter.java in  » XML » stax-utils » javanet » staxutils » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » stax utils » javanet.staxutils 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* $Id: IndentingXMLEventWriter.java,v 1.2 2004/06/24 22:06:11 kohsuke Exp $
002:         *
003:         * Copyright (c) 2004, Sun Microsystems, Inc.
004:         * All rights reserved.
005:         *
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions are
008:         * met:
009:         *
010:         *     * Redistributions of source code must retain the above copyright
011:         *      notice, this list of conditions and the following disclaimer.
012:         *
013:         *     * Redistributions in binary form must reproduce the above
014:         *      copyright notice, this list of conditions and the following
015:         *       disclaimer in the documentation and/or other materials provided
016:         *       with the distribution.
017:         *
018:         *     * Neither the name of Sun Microsystems, Inc. nor the names of its
019:         *       contributors may be used to endorse or promote products derived
020:         *       from this software without specific prior written permission.
021:         *
022:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
023:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
024:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
025:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
026:         * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
027:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
028:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
029:         * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
030:         * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
031:         * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
032:         * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
033:         */
034:        package javanet.staxutils;
035:
036:        import java.io.IOException;
037:        import java.io.Writer;
038:        import javax.xml.namespace.NamespaceContext;
039:        import javax.xml.namespace.QName;
040:        import javax.xml.stream.Location;
041:        import javax.xml.stream.XMLEventReader;
042:        import javax.xml.stream.XMLEventWriter;
043:        import javax.xml.stream.XMLStreamConstants;
044:        import javax.xml.stream.XMLStreamException;
045:        import javax.xml.stream.events.Characters;
046:        import javax.xml.stream.events.EndElement;
047:        import javax.xml.stream.events.StartElement;
048:        import javax.xml.stream.events.XMLEvent;
049:
050:        /**
051:         * Wraps another {@link XMLEventWriter} and does the indentation.
052:         * 
053:         * <p>
054:         * {@link XMLEventWriter} API doesn't provide any portable way of
055:         * doing pretty-printing. This {@link XMLEventWriter} filter provides
056:         * a portable indentation support by wrapping another {@link XMLEventWriter}
057:         * and adding proper {@link Characters} event for indentation.
058:         * 
059:         * <p>
060:         * Because whitespace handling in XML is tricky, this is not an
061:         * one-size-fit-all indentation engine. Instead, this class is
062:         * focused on handling so-called "data-oritented XML" like follows:
063:         * 
064:         * <pre><xmp>
065:         * <cards>
066:         *   <card id="kk.152">
067:         *     <firstName>Kohsuke</firstName>
068:         *     <lastName>Kawaguchi</lastName>
069:         *   </card>
070:         * </cards>
071:         * </xmp></pre>
072:         * 
073:         * <p>
074:         * We'll discuss more about the supported subset of XML later.
075:         * 
076:         * <p>
077:         * To use this engine, do as follows:
078:         * <pre>
079:         * {@link XMLEventWriter} w = xmlOutputFactory.createXMLEventWriter(...);
080:         * w = new {@link IndentingXMLEventWriter}(w);
081:         * 
082:         * // start writing
083:         * </pre>
084:         * 
085:         * <p>
086:         * Use {@link #setIndent(String)} and {@link #setNewLine(String)} to
087:         * control the indentation if you want.
088:         * 
089:         * 
090:         * <h2>What Subset Does This Support?</h2>
091:         * <p>
092:         * This engine works when the content model of each element is either
093:         * element-only or #PCDATA (but not mixed content model.) IOW, it
094:         * assumes that the children of any element is either (a) only elements
095:         * and no #PCDATA or (b) #PCDATA only and no elements.
096:         * 
097:         * <p>
098:         * The engine also tries to handle comments, PIs, and a DOCTYPE decl,
099:         * but in general it works only when those things appear in the
100:         * element-only content model.
101:         * 
102:         * 
103:         * <h2>For Maintainers</h2>
104:         * <p>
105:         * Please don't try to make this class into an almighty indentation class.
106:         * I've seen it attempted in Xerces and it's not gonna be pretty.
107:         * 
108:         * <p>
109:         * If you come up with an idea of another pretty-printer
110:         * that supports another subset, please go ahead and write your own class.
111:         * 
112:         * 
113:         * 
114:         * @author
115:         *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
116:         */
117:        public class IndentingXMLEventWriter implements  XMLEventWriter {
118:            private final XMLEventWriter core;
119:
120:            /**
121:             * String used for indentation.
122:             */
123:            private String indent = "  ";
124:
125:            /**
126:             * String for EOL.
127:             */
128:            private String newLine;
129:
130:            /**
131:             * Current nest level.
132:             */
133:            private int depth = 0;
134:
135:            /**
136:             * True if the current element has text.
137:             */
138:            private boolean hasText;
139:
140:            /**
141:             * {@link XMLEvent} constant that returns the {@link #newLine}.
142:             */
143:            private final Characters newLineEvent = new CharactersImpl() {
144:                public String getData() {
145:                    return newLine;
146:                }
147:            };
148:
149:            /**
150:             * {@link XMLEvent} constant that returns the {@link #indent}.
151:             */
152:            private final Characters indentEvent = new CharactersImpl() {
153:                public String getData() {
154:                    return indent;
155:                }
156:            };
157:
158:            /**
159:             * Partial implementation of {@link Characters} event.
160:             */
161:            private static abstract class CharactersImpl implements  Characters {
162:
163:                public boolean isWhiteSpace() {
164:                    return true;
165:                }
166:
167:                public boolean isCData() {
168:                    return false;
169:                }
170:
171:                public boolean isIgnorableWhiteSpace() {
172:                    // this is hard call. On one hand, we want the indentation to
173:                    // get through whatever pipeline, so we are tempted to return false.
174:                    // also DTD isn't necessarily present.
175:                    //
176:                    // But on the other hand, this IS an ignorable whitespace
177:                    // in its intended meaning.
178:                    return true;
179:                }
180:
181:                public int getEventType() {
182:                    // it's not clear if we are supposed to return SPACES
183:                    return XMLStreamConstants.CHARACTERS;
184:                }
185:
186:                public Location getLocation() {
187:                    // spec isn't clear if we can return null, but it doesn't say we can't.
188:                    return null;
189:                }
190:
191:                public boolean isStartElement() {
192:                    return false;
193:                }
194:
195:                public boolean isAttribute() {
196:                    return false;
197:                }
198:
199:                public boolean isNamespace() {
200:                    return false;
201:                }
202:
203:                public boolean isEndElement() {
204:                    return false;
205:                }
206:
207:                public boolean isEntityReference() {
208:                    return false;
209:                }
210:
211:                public boolean isProcessingInstruction() {
212:                    return false;
213:                }
214:
215:                public boolean isCharacters() {
216:                    return true;
217:                }
218:
219:                public boolean isStartDocument() {
220:                    return false;
221:                }
222:
223:                public boolean isEndDocument() {
224:                    return false;
225:                }
226:
227:                public StartElement asStartElement() {
228:                    return null;
229:                }
230:
231:                public EndElement asEndElement() {
232:                    return null;
233:                }
234:
235:                public Characters asCharacters() {
236:                    return this ;
237:                }
238:
239:                public QName getSchemaType() {
240:                    return null;
241:                }
242:
243:                public void writeAsEncodedUnicode(Writer writer)
244:                        throws XMLStreamException {
245:                    try {
246:                        // technically we need to do escaping, for we allow
247:                        // any characters to be used for indent and newLine.
248:                        // but in practice, who'll use something other than 0x20,0x0D,0x0A,0x08?
249:                        writer.write(getData());
250:                    } catch (IOException e) {
251:                        throw new XMLStreamException(e);
252:                    }
253:                }
254:
255:            };
256:
257:            public IndentingXMLEventWriter(XMLEventWriter core) {
258:                if (core == null)
259:                    throw new IllegalArgumentException();
260:                this .core = core;
261:
262:                // get the default line separator
263:                try {
264:                    newLine = System.getProperty("line.separator");
265:                } catch (SecurityException e) {
266:                    // use '\n' if we can't figure it out
267:                    newLine = "\n";
268:                }
269:            }
270:
271:            /**
272:             * Returns the string used for indentation.
273:             */
274:            public String getIndent() {
275:                return indent;
276:            }
277:
278:            /**
279:             * Sets the string used for indentation.
280:             * 
281:             * <p>
282:             * By default, this is set to two space chars.
283:             * 
284:             * @param indent
285:             *      A string like "  ", "\\t". Must not be null.
286:             */
287:            public void setIndent(String indent) {
288:                if (indent == null)
289:                    throw new IllegalArgumentException();
290:                this .indent = indent;
291:            }
292:
293:            /**
294:             * Returns the string used for newline.
295:             */
296:            public String getNewLine() {
297:                return newLine;
298:            }
299:
300:            /**
301:             * Sets the string used for newline.
302:             * 
303:             * <p>
304:             * By default, this is set to the platform default new line.
305:             * 
306:             * @param newLine
307:             *      A string like "\\n" or "\\r\\n". Must not be null.
308:             */
309:            public void setNewLine(String newLine) {
310:                if (newLine == null)
311:                    throw new IllegalArgumentException();
312:                this .newLine = newLine;
313:            }
314:
315:            public void add(XMLEvent event) throws XMLStreamException {
316:                switch (event.getEventType()) {
317:                case XMLStreamConstants.CHARACTERS:
318:                case XMLStreamConstants.CDATA:
319:                case XMLStreamConstants.SPACE:
320:                    if (event.asCharacters().isWhiteSpace())
321:                        // skip any indentation given by the client
322:                        // we are running the risk of ignoring the non-ignorable
323:                        // significant whitespaces, but that's a risk explained
324:                        // in the class javadoc.
325:                        return;
326:
327:                    hasText = true;
328:                    core.add(event);
329:                    return;
330:
331:                case XMLStreamConstants.START_ELEMENT:
332:                    newLine();
333:                    core.add(event);
334:                    hasText = false;
335:                    depth++;
336:                    return;
337:
338:                case XMLStreamConstants.END_ELEMENT:
339:                    depth--;
340:                    if (!hasText) {
341:                        newLine();
342:                    }
343:                    core.add(event);
344:                    hasText = false;
345:                    return;
346:
347:                case XMLStreamConstants.PROCESSING_INSTRUCTION:
348:                case XMLStreamConstants.COMMENT:
349:                case XMLStreamConstants.DTD:
350:                    // those things can be mixed with text,
351:                    // and at this point we don't know if text follows this
352:                    // like <foo><?pi?>text</foo>
353:                    //
354:                    // but we make a bold assumption that the those primitives
355:                    // only appear as a part of the element-only content model.
356:                    // so we always indent them as:
357:                    // <foo>
358:                    //   <?pi?>
359:                    //   ...
360:                    // </foo>
361:                    if (!hasText) {
362:                        // if we know that we already had a text, I see no
363:                        // reason to indent
364:                        newLine();
365:                    }
366:                    core.add(event);
367:                    return;
368:
369:                case XMLStreamConstants.END_DOCUMENT:
370:                    core.add(event);
371:                    // some implementation does the buffering by default,
372:                    // and it prevents the output from appearing.
373:                    // this has been a confusion for many people.
374:                    // calling flush wouldn't hurt decent impls, and it
375:                    // prevent such unnecessary confusion.
376:                    flush();
377:                    break;
378:
379:                default:
380:                    core.add(event);
381:                    return;
382:                }
383:
384:            }
385:
386:            /**
387:             * Prints out a new line and indent.
388:             */
389:            private void newLine() throws XMLStreamException {
390:                core.add(newLineEvent);
391:                for (int i = 0; i < depth; i++)
392:                    core.add(indentEvent);
393:            }
394:
395:            public void add(XMLEventReader reader) throws XMLStreamException {
396:                // we can't just delegate to the core
397:                // because we need to do indentation.
398:                if (reader == null)
399:                    throw new IllegalArgumentException();
400:                while (reader.hasNext()) {
401:                    add(reader.nextEvent());
402:                }
403:            }
404:
405:            public void close() throws XMLStreamException {
406:                core.close();
407:            }
408:
409:            public void flush() throws XMLStreamException {
410:                core.flush();
411:            }
412:
413:            public NamespaceContext getNamespaceContext() {
414:                return core.getNamespaceContext();
415:            }
416:
417:            public String getPrefix(String uri) throws XMLStreamException {
418:                return core.getPrefix(uri);
419:            }
420:
421:            public void setDefaultNamespace(String uri)
422:                    throws XMLStreamException {
423:                core.setDefaultNamespace(uri);
424:            }
425:
426:            public void setNamespaceContext(NamespaceContext context)
427:                    throws XMLStreamException {
428:                core.setNamespaceContext(context);
429:            }
430:
431:            public void setPrefix(String prefix, String uri)
432:                    throws XMLStreamException {
433:                core.setPrefix(prefix, uri);
434:            }
435:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.