View Javadoc

1   /*
2   
3       stax  Stack API for XML.
4       Copyright (c) 2001-2006 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 2.1 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.gnu.org/copyleft/lesser.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package net.sf.stax;
25  
26  import java.util.List;
27  import java.util.Stack;
28  import java.util.ArrayList;
29  
30  import org.xml.sax.Attributes;
31  import org.xml.sax.SAXException;
32  
33  /***
34   * For-child dispatch.  Use this class to handle multiple child
35   * elements of the same type.  The list of values, returned by the
36   * <code>endTree(StAXContext)</code> method, is available to a
37   * parent handler via its <code>endElement(String, String, String,
38   * String, Object, StAXContext)</code> method.
39   *
40   * <p>For example, for the following (sub-)tree:
41   * <pre>
42   * &gt;foo&lt;
43   *   &gt;int&lt;0&gt;/int&lt;
44   *   &gt;int&lt;1&gt;/int&lt;
45   *   &gt;int&lt;2&gt;/int&lt;
46   *   &gt;int&lt;3&gt;/int&lt;
47   *   &gt;int&lt;4&gt;/int&lt;
48   * &gt;/foo&lt;
49   * </pre>
50   * </p>
51   * <p>Use
52   * <pre>
53   * class FooHandler
54   *     extends StAXContentHandlerBase
55   * {
56   *     private List integerValues;
57   *     private DispatchForChild dispatch = new DispatchForChild(new IntElementHandler());
58   *
59   *     public void startElement(..., StAXDelegationContext dctx)
60   *     {
61   *         dctx.delegate(dispatch);
62   *     }
63   *
64   *     public void endElement(..., Object result, ...)
65   *     {
66   *         this.integerValues = (List) result;
67   *     }
68   * }
69   * </pre>
70   * </p>
71   *
72   * @author  Thomas Down
73   * @author  Matthew Pocock
74   * @author  Michael Heuer
75   * @version $Revision: 1.3 $ $Date: 2006/01/02 20:37:34 $
76   */
77  public final class DispatchForChild
78      extends StAXContentHandlerBase
79  {
80      /*** Wrapped handler. */
81      private final StAXContentHandler handler;
82  
83      /*** Stack of frames. */
84      private final Stack frames;
85  
86  
87      /***
88       * Create a new for-child dispatch wrapping the specified handler.
89       *
90       * @param handler wrapped handler
91       */
92      public DispatchForChild(final StAXContentHandler handler)
93      {
94          this.handler = handler;
95          frames = new Stack();
96      }
97  
98  
99      /*** @see StAXContentHandlerBase */
100     public void startTree(final StAXContext ctx)
101     {
102         frames.push(new Frame());
103     }
104 
105     /*** @see StAXContentHandlerBase */
106     public void startElement(final String nsURI,
107                              final String localName,
108                              final String qName,
109                              final Attributes attrs,
110                              final StAXDelegationContext dctx)
111         throws SAXException
112     {
113         Frame f = (Frame) frames.peek();
114 
115         if (f.getDepth() == 1)
116         {
117             dctx.delegate(handler);
118         }
119         else
120         {
121             if (f.getDepth() > 1)
122             {
123                 throw new SAXException("Too deep");
124             }
125         }
126         f.setDepth(f.getDepth() + 1);
127     }
128 
129     /*** @see StAXContentHandlerBase */
130     public void endElement(final String nsURI,
131                            final String localName,
132                            final String qName,
133                            final Object result,
134                            final StAXContext ctx)
135     {
136         Frame f = (Frame) frames.peek();
137 
138         f.setDepth(f.getDepth() - 1);
139         if (f.getDepth() == 1)
140         {
141             f.getResults().add(result);
142         }
143     }
144 
145     /*** @see StAXContentHandlerBase */
146     public Object endTree(final StAXContext ctx)
147     {
148         Frame f = (Frame) frames.pop();
149         return f.getResults();
150     }
151 
152 
153     /***
154      * Memento frame class.
155      */
156     private static final class Frame
157     {
158         /*** List of results. */
159         private List results;
160 
161         /*** Depth. */
162         private int depth;
163 
164 
165         /***
166          * Create a new empty frame.
167          */
168         public Frame()
169         {
170             results = new ArrayList();
171             depth = 0;
172         }
173 
174 
175         /***
176          * Return a modifiable list of results for this frame.
177          *
178          * @return a modifiable list of results for this frame
179          */
180         public List getResults()
181         {
182             return results;
183         }
184 
185         /***
186          * Return the depth for this frame.
187          *
188          * @return the depth for this frame
189          */
190         public int getDepth()
191         {
192             return depth;
193         }
194 
195         /***
196          * Set the depth for this frame to <code>depth</code>.
197          *
198          * @param depth depth
199          */
200         public void setDepth(final int depth)
201         {
202             this.depth = depth;
203         }
204     }
205 }