001package com.hfg.xml.parser;
002
003import java.io.*;
004import java.util.ArrayList;
005import java.util.Collection;
006
007import org.xml.sax.Attributes;
008import org.xml.sax.SAXException;
009
010import com.hfg.util.StringUtil;
011import com.hfg.xml.XMLAttribute;
012import com.hfg.xml.XMLUtil;
013
014//------------------------------------------------------------------------------
015/**
016 * XML SAX ContentHandler that reproduces the XML. Useful in conjunction with
017 * pseudo-SAX parsers that operate on non-XML files (the NcbiASN1BinarySAXParser
018 * for example.)
019 *
020 * @author J. Alex Taylor, hairyfatguy.com
021 */
022//------------------------------------------------------------------------------
023// com.hfg XML/HTML Coding Library
024//
025// This library is free software; you can redistribute it and/or
026// modify it under the terms of the GNU Lesser General Public
027// License as published by the Free Software Foundation; either
028// version 2.1 of the License, or (at your option) any later version.
029//
030// This library is distributed in the hope that it will be useful,
031// but WITHOUT ANY WARRANTY; without even the implied warranty of
032// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
033// Lesser General Public License for more details.
034//
035// You should have received a copy of the GNU Lesser General Public
036// License along with this library; if not, write to the Free Software
037// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
038//
039// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
040// jataylor@hairyfatguy.com
041//------------------------------------------------------------------------------
042
043public class XMLRepeatContentHandler extends AbstractContentHandler
044{
045   private BufferedWriter mWriter;
046   private String         mIndent = "   ";
047   private int            mIndentCount;
048   private METHOD         mLastMethod;
049
050   private String         mCurrentStartTag;
051   private Collection<XMLAttribute>  mCurrentAttributes;
052
053
054   private static enum METHOD { startElement, endElement, characters }
055
056   //-----------------------------------------------------------------------
057   public XMLRepeatContentHandler(OutputStream stream)
058   {
059      mWriter = new BufferedWriter(new OutputStreamWriter(stream));
060   }
061
062
063   //-----------------------------------------------------------------------
064   public XMLRepeatContentHandler setIndentSize(int inValue)
065   {
066      mIndent = StringUtil.polyChar(' ', inValue);
067      return this;
068   }
069
070   //-----------------------------------------------------------------------
071   @Override
072   public void startDocument()
073         throws SAXException
074   {
075      try
076      {
077         mWriter.write("<?xml version='1.0' ?>");
078         mWriter.newLine();
079      }
080      catch (IOException e)
081      {
082         throw new SAXException(e);
083      }
084   }
085
086   //-----------------------------------------------------------------------
087   @Override
088   public void endDocument()
089         throws SAXException
090   {
091      try
092      {
093         mWriter.close();
094      }
095      catch (IOException e)
096      {
097         throw new SAXException(e);
098      }
099   }
100
101   //-----------------------------------------------------------------------
102   @Override
103   public void startElement(String inURI, String inLocalName, String inName, Attributes inAttributes)
104   {
105      try
106      {
107         if (mLastMethod == METHOD.startElement)
108         {
109            mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes));
110
111            mWriter.newLine();
112            mIndentCount++;
113         }
114
115         mWriter.write(StringUtil.polyString(mIndent, mIndentCount));
116
117         mCurrentStartTag   = inName;
118
119         mCurrentAttributes = null;
120         if (inAttributes.getLength() > 0)
121         {
122            mCurrentAttributes = new ArrayList<XMLAttribute>(inAttributes.getLength());
123            for (int i = 0; i < inAttributes.getLength(); i++)
124            {
125               mCurrentAttributes.add(new XMLAttribute(inAttributes.getQName(i), inAttributes.getValue(i)));
126            }
127         }
128
129//         mWriter.write(XMLUtil.composeStartTag(inName, inAttributes));
130      }
131      catch (IOException e)
132      {
133         throw new RuntimeException(e);
134      }
135
136      mLastMethod = METHOD.startElement;
137   }
138
139   //-----------------------------------------------------------------------
140   @Override
141   public void endElement(String inURI, String inLocalName, String inName)
142   {
143      try
144      {
145         if (mLastMethod == METHOD.endElement)
146         {
147            mWriter.write(StringUtil.polyString(mIndent, (mIndentCount--) - 1));
148         }
149
150         if (mLastMethod == METHOD.startElement)
151         {
152            mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes, XMLUtil.EMPTY_TAG));
153         }
154         else
155         {
156            mWriter.write(XMLUtil.composeEndTag(inName));
157         }
158
159         mWriter.newLine();
160      }
161      catch (IOException e)
162      {
163         throw new RuntimeException(e);
164      }
165
166      mLastMethod = METHOD.endElement;
167   }
168
169   //-----------------------------------------------------------------------
170   @Override
171   public void characters(char[] inChars, int offset, int length)
172   {
173      try
174      {
175         mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes, XMLUtil.NOT_EMPTY_TAG));
176         mWriter.write(XMLUtil.escapeContentIfNecessary(new String(inChars, offset, length)));
177      }
178      catch (IOException e)
179      {
180         throw new RuntimeException(e);
181      }
182
183      mLastMethod = METHOD.characters;
184   }
185
186}