KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > taglibs > xtags > xpath > ForEachTag


1 /*
2  * Copyright 1999,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.taglibs.xtags.xpath;
18
19 import java.io.IOException JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.Comparator JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import javax.servlet.jsp.JspException JavaDoc;
29
30 import org.dom4j.DocumentFactory;
31 import org.dom4j.Node;
32 import org.dom4j.XPath;
33
34 import org.apache.taglibs.xtags.util.JspVariableContext;
35
36
37 /** A tag which performs an iteration over the results of an XPath expression on an XML document
38   *
39   * @author James Strachan
40   */

41 public class ForEachTag extends AbstractBodyTag implements ContextNodeTag {
42
43     /** Holds the XPath selection instance. */
44     private XPath xpath;
45     
46     /** Holds value of property id. */
47     private String JavaDoc id;
48     
49     /** Holds value of property type. */
50     private String JavaDoc type;
51     
52     /** Holds the current iterator */
53     private Iterator JavaDoc iterator;
54     
55     /** Holds value of property contextNode. */
56     private Object JavaDoc contextNode;
57     
58     /** Holds the sorting XPath expression */
59     private XPath sortXPath;
60     /** Holds value of property distinct. */
61     private boolean distinct;
62     
63     /** The input nodes */
64     private Object JavaDoc context;
65     
66     /** Cache of original context which is restored after the loop finishes */
67     private Object JavaDoc originalContext;
68     
69     /** Holds value of property ascending. */
70     private boolean ascending = true;
71     
72     public ForEachTag() {
73     }
74
75     /** Causes the iteration to be stopped like the Java 'break' statement.
76       */

77     public void breakLoop() throws JspException JavaDoc {
78         finishLoop();
79     }
80     
81     // ContextNodeTag interface
82
//-------------------------------------------------------------------------
83
public Object JavaDoc getContext() {
84         return contextNode;
85     }
86     
87     // BodyTag interface
88
//-------------------------------------------------------------------------
89
public int doStartTag() throws JspException JavaDoc {
90         originalContext = TagHelper.getInputNodes( pageContext );
91         iterator = null;
92         if ( xpath != null ) {
93             List JavaDoc list = selectNodes();
94             iterator = list.iterator();
95             if ( hasNext() ) {
96                 return EVAL_BODY_TAG;
97             }
98         }
99         reset();
100         return SKIP_BODY;
101     }
102
103     public int doAfterBody() throws JspException JavaDoc {
104         if ( iterator != null ) {
105             if ( hasNext() ) {
106                 return EVAL_BODY_TAG;
107             }
108             else {
109                 finishLoop();
110             }
111         }
112         // reset the original context just in case a <jsp:include>
113
// was used in the body or whatnot
114
TagHelper.setInputNodes( pageContext, originalContext );
115         reset();
116         return SKIP_BODY;
117     }
118     
119
120     public void release() {
121         reset();
122         xpath = null;
123         sortXPath = null;
124         distinct = false;
125         ascending = true;
126     }
127
128     
129     // Properties
130
//-------------------------------------------------------------------------
131
public void setContext(Object JavaDoc context) {
132         this.context = context;
133     }
134     
135     /** Sets the select XPath expression
136       */

137     public void setSelect(String JavaDoc select) {
138         this.xpath = createXPath( select );
139     }
140
141     /** Sets the XPath selection expression
142       */

143     public void setSelectXPath(XPath xpath) {
144         this.xpath = xpath;
145     }
146     
147     /** Setter for property sort.
148      * @param sort New value of property sort.
149      */

150     public void setSort(String JavaDoc sort) {
151         if ( sort == null ) {
152             this.sortXPath = null;
153         }
154         else {
155             this.sortXPath = createXPath( sort );
156         }
157     }
158
159     public void setSortXPath(XPath sortXPath) {
160         this.sortXPath = sortXPath;
161     }
162     
163     /** Getter for property distinct.
164      * @return Value of property distinct.
165      */

166     public boolean isDistinct() {
167         return distinct;
168     }
169     /** Setter for property distinct.
170      * @param distinct New value of property distinct.
171      */

172     public void setDistinct(boolean distinct) {
173         this.distinct = distinct;
174     }
175     
176     /** Getter for property id.
177      * @return Value of property id.
178      */

179     public String JavaDoc getId() {
180         return id;
181     }
182     
183     /** Setter for property id.
184      * @param id New value of property id.
185      */

186     public void setId(String JavaDoc id) {
187         this.id = id;
188     }
189     
190     /** Getter for property type.
191      * @return Value of property type.
192      */

193     public String JavaDoc getType() {
194         return type;
195     }
196     
197     /** Setter for property type.
198      * @param type New value of property type.
199      */

200     public void setType(String JavaDoc type) {
201         this.type = type;
202     }
203     
204     
205     /** Getter for property ascending.
206      * @return Value of property ascending.
207      */

208     public boolean isAscending() {
209         return ascending;
210     }
211     
212     /** Setter for property ascending.
213      * @param ascending New value of property ascending.
214      */

215     public void setAscending(boolean ascending) {
216         this.ascending = ascending;
217     }
218     
219     // Implementation methods
220
//-------------------------------------------------------------------------
221
protected List JavaDoc selectNodes() {
222         if ( xpath != null ) {
223             Object JavaDoc input = getInputNodes();
224             if ( sortXPath != null ) {
225                 List JavaDoc answer = xpath.selectNodes( input, sortXPath, distinct );
226                 if ( ! ascending ) {
227                     Collections.reverse( answer );
228                 }
229                 return answer;
230             }
231             else {
232                 return xpath.selectNodes( input );
233             }
234         }
235         return Collections.EMPTY_LIST;
236     }
237     
238     /** @return the input node on which to make a selction
239       */

240     public Object JavaDoc getInputNodes() {
241         if ( context == null ) {
242             return TagHelper.getInputNodes( pageContext, this, true );
243         }
244         return context;
245     }
246     
247     
248     /** Finishes the loop and outputs the current body */
249     protected void finishLoop() throws JspException JavaDoc {
250         iterator = null;
251         contextNode = null;
252         try {
253             bodyContent.writeOut(bodyContent.getEnclosingWriter());
254         }
255         catch (IOException JavaDoc e) {
256             handleException(e);
257         }
258         bodyContent.clearBody();
259     }
260     
261     /** Performs an iteration and defines a variable of the current object */
262     protected boolean hasNext() {
263         if ( iterator.hasNext() ) {
264             contextNode = iterator.next();
265             TagHelper.defineVariable( pageContext, getId(), contextNode );
266             if ( contextNode != null ) {
267                 return true;
268             }
269         }
270         return false;
271     }
272     
273     /** A factory method to create new XPath instances */
274     protected XPath createXPath(String JavaDoc xpathExpression) {
275         XPath xpath = getDocumentFactory().createXPath( xpathExpression );
276         xpath.setVariableContext( JspVariableContext.getInstance( pageContext ) );
277         return xpath;
278     }
279
280     /** @return the factory used to create XPath instances */
281     protected DocumentFactory getDocumentFactory() {
282         return DocumentFactory.getInstance();
283     }
284     
285     private void reset() {
286         iterator = null;
287         contextNode = null;
288     }
289     
290 }
291
Popular Tags