001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.xbean.spring.generator;
018    
019    import java.io.PrintWriter;
020    import java.io.Writer;
021    import java.util.LinkedList;
022    
023    /**
024     * @author Dain Sundstrom
025     * @version $Id$
026     * @since 1.0
027     */
028    public class XmlWriter {
029        private PrintWriter writer;
030    
031        private LinkedList elementStack = new LinkedList();
032    
033        private boolean tagInProgress;
034    
035        private int depth;
036    
037        private String lineIndenter;
038    
039        private String encoding;
040    
041        private String docType;
042    
043        private boolean readyForNewLine;
044    
045        private boolean tagIsEmpty;
046    
047        public XmlWriter(PrintWriter writer, String lineIndenter) {
048            this(writer, lineIndenter, null, null);
049        }
050    
051        public XmlWriter(Writer writer, String lineIndenter) {
052            this(new PrintWriter(writer), lineIndenter);
053        }
054    
055        public XmlWriter(PrintWriter writer) {
056            this(writer, null, null);
057        }
058    
059        public XmlWriter(Writer writer) {
060            this(new PrintWriter(writer));
061        }
062    
063        public XmlWriter(PrintWriter writer, String lineIndenter, String encoding, String doctype) {
064            this.writer = writer;
065    
066            this.lineIndenter = lineIndenter;
067    
068            this.encoding = encoding;
069    
070            this.docType = doctype;
071    
072            if (docType != null || encoding != null) {
073                writeDocumentHeaders();
074            }
075        }
076    
077        public XmlWriter(Writer writer, String lineIndenter, String encoding, String doctype) {
078            this(new PrintWriter(writer), lineIndenter, encoding, doctype);
079        }
080    
081        public XmlWriter(PrintWriter writer, String encoding, String doctype) {
082            this(writer, "  ", encoding, doctype);
083        }
084    
085        public XmlWriter(Writer writer, String encoding, String doctype) {
086            this(new PrintWriter(writer), encoding, doctype);
087        }
088    
089        public void startElement(String name) {
090            tagIsEmpty = false;
091    
092            finishTag();
093    
094            write("<");
095    
096            write(name);
097    
098            elementStack.addLast(name);
099    
100            tagInProgress = true;
101    
102            depth++;
103    
104            readyForNewLine = true;
105    
106            tagIsEmpty = true;
107        }
108    
109        public void writeText(String text) {
110            writeText(text, true);
111        }
112    
113        public void writeMarkup(String text) {
114            writeText(text, false);
115        }
116    
117        private void writeText(String text, boolean escapeHtml) {
118            readyForNewLine = false;
119    
120            tagIsEmpty = false;
121    
122            finishTag();
123    
124            if (escapeHtml) {
125                text = text.replaceAll("&", "&amp;");
126    
127                text = text.replaceAll("<", "&lt;");
128    
129                text = text.replaceAll(">", "&gt;");
130            }
131    
132            write(text);
133        }
134    
135        public void addAttribute(String key, String value) {
136            write(" ");
137    
138            write(key);
139    
140            write("=\"");
141    
142            write(value);
143    
144            write("\"");
145        }
146    
147        public void endElement() {
148            depth--;
149    
150            if (tagIsEmpty) {
151                write("/");
152    
153                readyForNewLine = false;
154    
155                finishTag();
156    
157                elementStack.removeLast();
158            } else {
159                finishTag();
160    
161                write("</" + elementStack.removeLast() + ">");
162            }
163    
164            readyForNewLine = true;
165        }
166    
167        private void write(String str) {
168            writer.write(str);
169        }
170    
171        private void finishTag() {
172            if (tagInProgress) {
173                write(">");
174            }
175    
176            tagInProgress = false;
177    
178            if (readyForNewLine) {
179                endOfLine();
180            }
181            readyForNewLine = false;
182    
183            tagIsEmpty = false;
184        }
185    
186        protected void endOfLine() {
187            write("\n");
188    
189            for (int i = 0; i < depth; i++) {
190                write(lineIndenter);
191            }
192        }
193    
194        private void writeDocumentHeaders() {
195            write("<?xml version=\"1.0\"");
196    
197            if (encoding != null) {
198                write(" encoding=\"" + encoding + "\"");
199            }
200    
201            write("?>");
202    
203            endOfLine();
204    
205            if (docType != null) {
206                write("<!DOCTYPE ");
207    
208                write(docType);
209    
210                write(">");
211    
212                endOfLine();
213            }
214        }
215    }