View Javadoc

1   /*
2    * Copyright (C) 2004 TiongHiang Lee
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not,  write to the Free Software
16   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17   *
18   * Email: thlee@thinklient.org
19   */
20  
21  package org.onemind.commons.java.xml.digest;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.*;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  import javax.xml.parsers.*;
29  import org.xml.sax.Attributes;
30  import org.xml.sax.SAXException;
31  import org.xml.sax.helpers.DefaultHandler;
32  /***
33   * The SaxDigesterHandler use digesters to digest the elements in the xml. The digesters can be added using the addDigester(). By
34   * default the sequential digester list is used.
35   * @author TiongHiang Lee (thlee@thinklient.org)
36   * @version $Id: SaxDigesterHandler.java,v 1.3 2005/01/30 06:31:37 thlee Exp $ $Name:  $
37   */
38  public class SaxDigesterHandler extends DefaultHandler
39  {
40  
41      /*** the logger * */
42      private static final Logger _logger = Logger.getLogger(SaxDigesterHandler.class.getName());
43  
44      /*** the map contains subdigesters **/
45      private Map _digesters = new HashMap();
46  
47      /*** keep track of the path for current element **/
48      private List _elementPath = new ArrayList();
49  
50      /***
51       * Constructor
52       */
53      public SaxDigesterHandler()
54      {
55      }
56  
57      /***
58       * Adding a digester to the root path
59       * @param dig the digester
60       */
61      public void addDigester(ElementDigester dig)
62      {
63          addDigester(null, dig);
64      }
65  
66      /***
67       * Add a digester for the path
68       * @param path the path
69       * @param dig the digester
70       */
71      public void addDigester(String path, ElementDigester dig)
72      {
73          if (path == null)
74          {
75              _digesters.put(dig.getElementName(), dig);
76          } else
77          {
78              _digesters.put(path + "/" + dig.getElementName(), dig);
79          }
80      }
81  
82      /***
83       * Add a subdigester to current element path
84       * @param dig the digester
85       */
86      public void addSubDigester(ElementDigester dig)
87      {
88          String path = getCurrentPath();
89          addDigester(path, dig);
90      }
91  
92      /***
93       * Add a sub digester at a path of current path + prefixPath
94       * @param prefixPath the prefix path
95       * @param dig the digester
96       */
97      public void addSubDigester(String prefixPath, ElementDigester dig)
98      {
99          String path = getCurrentPath();
100         if (path == null)
101         {
102             addDigester(prefixPath, dig);
103         } else if (prefixPath == null)
104         {
105             addDigester(path, dig);
106         } else
107         {
108             addDigester(path + "/" + prefixPath, dig);
109         }
110     }
111 
112     /***
113      * Append the name to the element path and return the new path string
114      * @param name the name of new element
115      * @return the new path string
116      */
117     private String appendElementPath(String name)
118     {
119         int i = _elementPath.size();
120         if (i > 0)
121         {
122             String str = (String) _elementPath.get(i - 1);
123             String newStr = str + "/" + name;
124             _elementPath.add(newStr);
125             return newStr;
126         } else
127         {
128             _elementPath.add(name);
129             return name;
130         }
131     }
132 
133     /***
134      * {@inheritDoc}
135      */
136     public void characters(char[] ch, int start, int length) throws SAXException
137     {
138         ElementDigester dig = getDigester(getCurrentPath());
139         if (dig != null)
140         {
141             dig.characters(this, ch, start, length);
142         }
143     }
144 
145     /***
146      * {@inheritDoc}
147      */
148     public void endDocument() throws SAXException
149     {
150         //do nothing
151     }
152 
153     /***
154      * {@inheritDoc}
155      */
156     public void endElement(String uri, String localName, String qName) throws SAXException
157     {
158         String str = removeElementPath(qName);
159         ElementDigester dig = (ElementDigester) getDigester(str);
160         if (dig != null)
161         {
162             dig.endDigest(this);
163         }
164     }
165 
166     /***
167      * Get the current element path
168      * @return the path, or null if at start of document
169      */
170     public String getCurrentPath()
171     {
172         int i = _elementPath.size();
173         if (i > 0)
174         {
175             return (String) _elementPath.get(i - 1);
176         } else
177         {
178             return null;
179         }
180     }
181 
182     /***
183      * Get the digester for particular path
184      * @param path the path
185      * @return the digester, or null if there's none found
186      */
187     private ElementDigester getDigester(String path)
188     {
189         return (ElementDigester) _digesters.get(path);
190     }
191 
192     /***
193      * Remove the element path
194      * @param qname the element name is being removed
195      * @return the path string before the path is removed
196      */
197     private String removeElementPath(String qname)
198     {
199         int i = _elementPath.size();
200         if (i > 0)
201         {
202             String str = (String) _elementPath.remove(i - 1);
203             return str;
204         } else
205         {
206             throw new IllegalStateException("Cannot remove element path " + qname);
207         }
208     }
209 
210     /***
211      * {@inheritDoc}
212      */
213     public void startDocument() throws SAXException
214     {
215         //do nothing
216     }
217 
218     /***
219      * Call start of particular element digester, if there's any
220      * @param attr the attribute
221      * @param path the path
222      * @throws SAXException
223      */
224     private void startDigest(String path, Attributes attr) throws SAXException
225     {
226         if (_logger.isLoggable(Level.FINEST))
227         {
228             _logger.finest("Digesting " + path);
229         }
230         ElementDigester dig = (ElementDigester) getDigester(path);
231         if (dig != null)
232         {
233             if (_logger.isLoggable(Level.FINEST))
234             {
235                 _logger.finest("with " + dig);
236             }
237             dig.startDigest(this, attr);
238         }
239     }
240 
241     /***
242      * {@inheritDoc}
243      */
244     public void startElement(String namespaceURI, String lName, // local name
245             String qName, // qualified name
246             Attributes attrs) throws SAXException
247     {
248         String newPath = appendElementPath(qName);
249         startDigest(newPath, attrs);
250     }
251 
252     /***
253      * Parse an input
254      * @param stream the stream
255      * @throws ParserConfigurationException
256      * @throws SAXException
257      * @throws IOException
258      */
259     public synchronized void parse(InputStream stream) throws ParserConfigurationException, SAXException, IOException
260     {
261         SAXParserFactory fac = SAXParserFactory.newInstance();
262         SAXParser parser = fac.newSAXParser();
263         parser.parse(stream, this);
264     }
265 }