View Javadoc

1   /*
2    * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/taglib/DbFilterConditionTag.java,v 1.25 2006/01/13 13:38:50 hkollmann Exp $
3    * $Revision: 1.25 $
4    * $Date: 2006/01/13 13:38:50 $
5    *
6    * DbForms - a Rapid Application Development Framework
7    * Copyright (C) 2001 Joachim Peer <joepeer@excite.com>
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2.1 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   */
23  
24  package org.dbforms.taglib;
25  
26  import org.dbforms.config.FieldValue;
27  
28  import org.dbforms.util.ParseUtil;
29  
30  import java.util.ArrayList;
31  import java.util.Iterator;
32  
33  import javax.servlet.http.HttpServletRequest;
34  import javax.servlet.jsp.JspException;
35  import javax.servlet.jsp.PageContext;
36  import javax.servlet.jsp.tagext.TryCatchFinally;
37  
38  
39  
40  /***
41   * Holds an sql condition that has to be nested inside a DbFilterTag. A
42   * condition is specified as sql code in the body of the tag. The character ?
43   * is a placeholder for user's input substitution. Every char ? found in sql
44   * code is replaced with value evalutated from corresponding filterValue tag
45   * nested. So there must be as ? as filterValue tags.
46   *
47   * @author Sergio Moretti
48   * @version $Revision: 1.25 $
49   */
50  public class DbFilterConditionTag extends AbstractScriptHandlerTag
51     implements TryCatchFinally {
52  
53     /*** object containing tag's state */
54     private transient State state;
55  
56     /***
57                                                                                          *
58                                                                                          */
59     public DbFilterConditionTag() {
60        super();
61        state = new State();
62     }
63  
64     /***
65      * DOCUMENT ME!
66      *
67      * @param string
68      */
69     public void setLabel(String string) {
70        state.label = string;
71     }
72  
73  
74     /***
75      * DOCUMENT ME!
76      *
77      * @return
78      */
79     public String getLabel() {
80        return state.label;
81     }
82  
83  
84     /***
85      * read filterCondition from body
86      *
87      * @see javax.servlet.jsp.tagext.IterationTag#doAfterBody()
88      */
89     public int doAfterBody() throws JspException {
90        if (this.bodyContent != null) {
91           state.filterCondition = bodyContent.getString()
92                                              .trim();
93        }
94  
95        return SKIP_BODY;
96     }
97  
98  
99     /***
100     * reset tag state
101     *
102     * @see javax.servlet.jsp.tagext.TryCatchFinally#doFinally()
103     */
104    public void doFinally() {
105       state = new State();
106    }
107 
108 
109    /***
110     * initialize environment and process body only if this condition is the
111     * currently selected.
112     *
113     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
114     */
115    public int doStartTag() throws JspException {
116       init();
117 
118       String sel = ParseUtil.getParameter((HttpServletRequest) pageContext
119                                           .getRequest(),
120                                           ((DbFilterTag) getParent())
121                                           .getFilterName()
122                                           + DbFilterTag.FLT_SEL);
123 
124       // process body only if this condition is active
125       if (sel != null) {
126          int selId = Integer.parseInt(sel);
127 
128          if (selId == state.conditionId) {
129             return EVAL_BODY_BUFFERED;
130          }
131       }
132 
133       return SKIP_BODY;
134    }
135 
136 
137    /***
138     * comparison using conditionId field
139     *
140     * @see java.lang.Object#equals(java.lang.Object)
141     */
142    public boolean equals(Object obj) {
143       return (obj instanceof DbFilterConditionTag)
144              && (state.conditionId == ((DbFilterConditionTag) obj).state.conditionId);
145    }
146 
147 
148    /***
149     * DOCUMENT ME!
150     *
151     * @return DOCUMENT ME!
152     */
153    public int hashCode() {
154       return state.conditionId;
155    }
156 
157 
158    /***
159     * condition prefix for request parameter
160     *
161     * @param tableId
162     * @param conditionId
163     *
164     * @return
165     */
166    protected static String getConditionName(int tableId,
167                                             int conditionId) {
168       return DbFilterTag.getFilterName(tableId) + DbFilterTag.FLT_COND
169              + conditionId;
170    }
171 
172 
173    /***
174     * generate condition from request. Called from nested DbFilterTag object
175     *
176     * @param request
177     * @param tableId
178     * @param conditionId
179     *
180     * @return string containing sql condition code
181     */
182    protected static String getSqlFilter(HttpServletRequest request,
183                                         int                tableId,
184                                         int                conditionId) {
185       return ParseUtil.getParameter(request,
186                                     DbFilterTag.getFilterName(tableId)
187                                     + DbFilterTag.FLT_COND + conditionId);
188    }
189 
190 
191    /***
192     * generate condition from request. Called from nested DbFilterTag object
193     *
194     * @param request
195     * @param tableId
196     * @param conditionId
197     *
198     * @return string containing sql condition code
199     */
200    protected static FieldValue[] getSqlFilterParams(HttpServletRequest request,
201                                                     int                tableId,
202                                                     int                conditionId) {
203       return DbFilterValueTag.readValuesFromRequest(request, tableId,
204                                                     conditionId);
205    }
206 
207 
208 
209    /***
210     * condition prefix for request parameters
211     *
212     * @return
213     */
214    protected String getConditionName() {
215       return getConditionName(((DbFilterTag) getParent()).getTableId(),
216                               state.conditionId);
217    }
218 
219 
220    /***
221     * DOCUMENT ME!
222     *
223     * @param pg DOCUMENT ME!
224     * @param parent DOCUMENT ME!
225     * @param state
226     */
227    protected void setState(PageContext pg,
228                            DbFilterTag parent,
229                            State       state) {
230       setParent(parent);
231       setPageContext(pg);
232       this.state = state;
233    }
234 
235 
236    /***
237     * DOCUMENT ME!
238     *
239     * @return
240     */
241    protected State getState() {
242       return state;
243    }
244 
245 
246    /***
247     * add a value to the value's list. called from nested DbFilterValueTag
248     * objs.
249     *
250     * @param value
251     *
252     * @return index of the newly added object
253     */
254    protected int addValue(DbFilterValueTag value) {
255       state.values.add(value.getState());
256 
257       return state.values.size() - 1;
258    }
259 
260 
261    /***
262     * render output, called from parent DbFilterCondition obj.
263     *
264     * @return string containing html code for this obj
265     */
266    protected StringBuffer render() throws JspException {
267       StringBuffer buf = new StringBuffer();
268       buf.append("<input type=\"hidden\" name=\""
269                  + ((DbFilterTag) getParent()).getFilterName()
270                  + DbFilterTag.FLT_COND + state.conditionId + "\" value=\""
271                  + state.filterCondition + "\" />\n");
272 
273       DbFilterValueTag value = new DbFilterValueTag();
274 
275       for (Iterator i = state.values.iterator(); i.hasNext();) {
276          value.setState(this.pageContext, this,
277                         (DbFilterValueTag.State) i.next());
278          buf.append(value.render());
279       }
280 
281       return buf;
282    }
283 
284 
285    /***
286     * initialize class's attributes
287     */
288    private void init() {
289       // state object is createad in constructor (for the first use) and in doEndTag next times
290       state.values = new ArrayList();
291 
292       //state.parentFilter = (DbFilterTag) getParent();
293       state.conditionId     = ((DbFilterTag) getParent()).addCondition(this);
294       state.filterCondition = null;
295 
296       if (state.label == null) {
297          state.label = Integer.toString(state.conditionId);
298       }
299    }
300 
301    /***
302     * tag's state holder. Used a separate class to hold tag's state to
303     * workaround to Tag pooling, in which an tag object is reused, but we have
304     * the need to store informations about all  child tags in the parent, so
305     * we store the state, and apply it to a dummy tag when needed.
306     *
307     * @author Sergio Moretti
308     */
309    protected static class State {
310       /*** list of value object's state contained in this condition */
311       protected ArrayList values = null;
312 
313       /*** raw filter condition */
314       protected String filterCondition = null;
315 
316       /*** condition's label, appear as an option in html select element */
317       protected String label = null;
318 
319       /*** identifier of condition */
320       protected int conditionId = -1;
321    }
322 }