001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.utils.xml;
022
023import java.io.IOException;
024import java.io.PrintWriter;
025
026/**
027 * Simple implementation of XMLWriter, optimized for speed.  The output is
028 * not necessarily human-readable, but is fine for automated parsing.
029 *
030 * @author Thomas Down
031 */
032
033public class FastXMLWriter /* implements XMLWriter */ {
034    private PrintWriter writer;
035    private boolean isOpeningTag = false;
036
037    public FastXMLWriter(PrintWriter writer) {
038        this.writer = writer;
039    }
040
041    public void openTag(String qName)
042        throws IOException
043    {
044        if (isOpeningTag) {
045            writer.print('>');
046        }
047        writer.print('<');
048        writer.print(qName);
049        isOpeningTag = true;
050    }
051
052    public void attribute(String qName, String value)
053        throws IOException
054    {
055        if (! isOpeningTag) {
056            throw new IOException("attributes must follow an openTag");
057        }
058
059        writer.print(' ');
060        writer.print(qName);
061        writer.print("=\"");
062        printAttributeValue(value);
063        writer.print('"');
064    }
065
066    public void closeTag(String qName) 
067        throws IOException
068    {
069        if (isOpeningTag) {
070            writer.println(" />");
071        } else {
072            writer.print("</");
073            writer.print(qName);
074            writer.print('>');
075        }
076
077        isOpeningTag = false;
078    }
079
080    public void println(String data)
081        throws IOException
082    {
083        if (isOpeningTag) {
084            writer.println('>');
085            isOpeningTag = false;
086        }
087        printChars(data);
088        writer.println();
089    }
090
091    public void print(String data)
092        throws IOException
093    {
094        if (isOpeningTag) {
095            writer.print('>');
096            isOpeningTag = false;
097        }
098        printChars(data);
099    }
100
101
102    public void printRaw(String data)
103        throws IOException
104    {
105        writer.println(data);
106    }
107    
108    protected void printChars(String data) 
109        throws IOException
110    {
111        if (data == null) {
112            printChars("null");
113            return;
114        }
115
116        for (int pos = 0; pos < data.length(); ++pos) {
117            char c = data.charAt(pos);
118            if (c == '<' || c == '>' || c == '&') {
119                numericalEntity(c);
120            } else {
121                writer.write(c);
122            }
123        }
124    }
125
126    protected void printAttributeValue(String data) 
127        throws IOException
128    {
129        if (data == null) {
130            printAttributeValue("null");
131            return;
132        }
133
134        for (int pos = 0; pos < data.length(); ++pos) {
135            char c = data.charAt(pos);
136            if (c == '<' || c == '>' || c == '&' || c == '"') {
137                numericalEntity(c);
138            } else {
139                writer.write(c);
140            }
141        }
142    }
143
144    protected void numericalEntity(char c)
145        throws IOException
146    {
147        writer.print("&#");
148        writer.print((int) c);
149        writer.print(';');
150    }
151}