View Javadoc

1   /*
2      $Id: XmlPrinter.java,v 1.4 2004/09/06 20:42:34 mch Exp $
3   
4     Date        Author      Changes
5      8 Oct 2002  M Hill      Created
6   
7      (c) Copyright...
8   */
9   package org.astrogrid.io.xml;
10  
11  import java.io.IOException;
12  import java.io.OutputStream;
13  import java.io.OutputStreamWriter;
14  import java.io.PrintWriter;
15  import java.io.Writer;
16  
17  /***
18   * A special XmlTagPrinter used to represent the underlying output stream.
19   * <p>
20   *
21   */
22  
23  public class XmlPrinter extends XmlTagPrinter
24  {
25     private PrintWriter out = null;
26     
27     private String indentSpaces = "   ";
28     private final static int INDENT_SIZE = 3;
29  
30     /*** marker to say whether root tag has already been opened.  Can only have
31      * one root tag.*/
32     private boolean startedRootTag = false;
33     
34     /***
35      * Constructor - pass in output stream to pipe to, and
36      * the initial header will be written if the flag is true.
37      */
38     public XmlPrinter(Writer aWriter, boolean writeProcInstHdr) throws IOException
39     {
40        super(null, null, null);
41        out = new PrintWriter(aWriter);
42        open(writeProcInstHdr);
43     }
44     
45     /***
46      * Constructor - pass in output stream to pipe to, and
47      * the initial header will be written
48      */
49     public XmlPrinter(OutputStream out, boolean writeProcInstHdr) throws IOException
50     {
51        this(new OutputStreamWriter(out), writeProcInstHdr);
52     }
53  
54  
55     protected void open(boolean writeProcInstHdr) throws IOException{
56        if (writeProcInstHdr) {
57           writeLine(0,"<?xml version=\"1.0\"?>");
58        }
59     }
60  
61     /***
62      * Should only be able to write comment tags at the root level (ie, at
63      * outputstream level) before any child tags are added
64      *
65     public void writeCommentTag(String tag) throws IOException
66     {
67        Log.affirm(state == STATE_PRETAG, "Cannot write comment "+tag+" as tag "+getChild()+" is set");
68        //       Log.assert( (tag.charAt(0) != '!') && (tag.charAt(0) != '?'), "Can only write comments (! or ?) before root tag, not '"+tag+"'");
69        writeLine("<"+tag+">");
70     }
71      /**/
72     
73     /***
74      * newTag overridden to ensure only one tag can be set
75      */
76     public XmlTagPrinter newTag(XmlTagPrinter aTag) throws IOException
77     {
78        assert !startedRootTag : "Cannot have more than one tag at root, trying to add "+aTag;
79        startedRootTag = true;
80        return super.newTag(aTag);
81     }
82     
83     /***
84      * writeString implementation - writes to the 'output stream' given in
85      * the constructor, using the AsciiOutputStream as a filter.
86      * NB - all writing is eventually channelled through this.
87      */
88     protected void writeString(String s) throws IOException
89     {
90        out.write(s);
91     }
92  
93     /***
94      * Implements the XmlOutput.writeIndentedLine method that writes a string
95      * plus a new line character, with a suitable number of spaces at the
96      * beginning corresponding to the given indent.
97      */
98     protected void writeLine(int indentIndex, String string) throws IOException
99     {
100       //convert indent index to index spaces
101       //there's a bit of a botch here to allow root nodes to be on the same level
102       //(ie 0 spaces) as the comment tags.
103       int indent = (indentIndex-1)*INDENT_SIZE;
104       if (indent<0)
105       {
106          indent = 0;
107       }
108       
109       //by reusing the same string when possible we save on garbage collection.
110       while (indentSpaces.length() < indent)
111       {
112          indentSpaces = indentSpaces + indentSpaces;
113       }
114         
115       writeString(indentSpaces.substring(0, indent) + string + "\n");
116    }
117 
118    /***
119     * Close tag - and output stream
120     */
121    public void close() throws IOException
122    {
123       super.close();
124       out.close();
125    }
126 
127    
128    /*** Test harness method - writes out a simple table
129     */
130    public static void main(String args[])
131    {
132       System.out.println("Hello World!");
133       
134       try
135       {
136          XmlPrinter xOut = new XmlPrinter(new OutputStreamWriter(System.out), true);
137          
138          XmlTagPrinter ftag = xOut.newTag("FRUIT");
139 
140          ftag.writeTag("DESCRIPTION","Sort of fruity things");
141          
142          XmlTagPrinter atag = ftag.newTag("APPLE");
143          atag.writeTag("SKIN","Rosy");
144          atag.writeTag("FLESH","White & Powdery");
145          atag.writeTag("STALK","Yes unless it's fallen off");
146          atag.close();
147          
148          XmlTagPrinter otag = ftag.newTag("ORANGE");
149          otag.writeTag("SKIN","Orange");
150          otag.writeTag("FLESH","Really Orange. Or Red.");
151          otag.writeTag("STALK","Would be orange but I've eaten it");
152 //         otag.close();
153          
154          xOut.close();
155          
156       } catch (IOException ioe)
157       {
158          System.out.println("IOE: "+ioe);
159       }
160       
161       System.out.println("Goodbye Cruel World!");
162       
163    }
164 }
165 
166