KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dbforms > taglib > DbFilterTag


1 /*
2  * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/taglib/DbFilterTag.java,v 1.27 2004/08/18 12:26:06 hkollmann Exp $
3  * $Revision: 1.27 $
4  * $Date: 2004/08/18 12:26:06 $
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.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.dbforms.config.FieldValue;
30
31 import org.dbforms.util.MessageResources;
32 import org.dbforms.util.ParseUtil;
33 import org.dbforms.util.Util;
34
35 import java.io.IOException JavaDoc;
36
37 import java.util.ArrayList JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.Locale JavaDoc;
40
41 import javax.servlet.http.HttpServletRequest JavaDoc;
42 import javax.servlet.jsp.JspException JavaDoc;
43 import javax.servlet.jsp.JspWriter JavaDoc;
44
45
46
47 /**
48  * custom tag that build up a set of sql filters. Create a set of sql filter
49  * conditions, letting user select which one will be applied. A filter tag
50  * contains one or more filterCondition tag. Each filterCondition represent a
51  * sql condition and is identified by its label. In the body of the
52  * filterCondition tag there is the piece of SQL code that we want to insert
53  * in the where clause, the character ? act like a placeholder, so a ? in the
54  * sql code will be substituted with the some user input. To tell the system
55  * what type of user input we want, the last tag is used, the filterValue tag.
56  * Each ? found in body will be subsituted by its corresponding filterValue
57  * tag. With the "type" attribute of this tag you can select the input more.
58  * Selecting "text", a filterValue will render an html input tag, with
59  * "select" you'll have an html select, and so on. An example is like this:
60  * <pre>
61  * &lt;db:filter>
62  * &lt;db:filterCondition label="author name like">
63  * NAME LIKE '%?%'
64  * &lt;db:filterValue type="timestamp" useJsCalendar="true" />
65  * &lt;/db:filterCondition>
66  * &lt;db:filterCondition label="ID > V1 AND ID &lt; V2">
67  * AUTHOR_ID >= ? AND AUTHOR_ID &lt;= ?
68  * &lt;db:filterValue label="V1" type="numeric"/>
69  * &lt;db:filterValue label="V2" type="numeric"/>
70  * &lt;/db:filterCondition>
71  * &lt;db:filterCondition label="author = ">
72  * NAME = '?'
73  * &lt;db:filterValue type="select">
74  * &lt;db:queryData name="q1" query="select distinct name as n1, name as n2 from author where AUTHOR_ID &lt; 100 order by name"/>
75  * &lt;/db:filterValue>
76  * &lt;/db:filterCondition>
77  * &lt;db:filterCondition label="now is after date">
78  * CURRENT_DATE > ?
79  * &lt;db:filterValue type="date" useJsCalendar="true" />
80  * &lt;/db:filterCondition>
81  * &lt;db:filterCondition label="filter without user input">
82  * AUTHOR_ID > 10
83  * &lt;/db:filterCondition>
84  * &lt;/db:filter>
85  * </pre>
86  * This structure will be rendered as a html select element to select the
87  * condition the you want to apply. On the onchange event there is a submit,
88  * so the page reload with the input elements of the condition that you have
89  * selected. After all input elements, there are two buttons, one to apply
90  * the condition, one to unset the current applied condition.
91  *
92  * <p>
93  * Internals:
94  *
95  * <dl>
96  * <dt>
97  * filter_[tableId]
98  * </dt>
99  * <dd>
100  * prefix that all the parameters created by this tag have.
101  * </dd>
102  * <dt>
103  * filter_[tableId]_sel
104  * </dt>
105  * <dd>
106  * index of the currently selected condition
107  * </dd>
108  * <dt>
109  * filter_[tableId]_cond_[condId]
110  * </dt>
111  * <dd>
112  * text of the currently selected condition
113  * </dd>
114  * <dt>
115  * filter_[tableId]_cond_[condId]_value_[valueId]
116  * </dt>
117  * <dd>
118  * current value of the input tag corresponding to the filterValue tag
119  * identified by [valueId]
120  * </dd>
121  * <dt>
122  * filter_[tableId]_cond_[condId]_valuetype_[valueId]
123  * </dt>
124  * <dd>
125  * type of the value identified by [valueId]
126  * </dd>
127  * </dl>
128  * </p>
129  *
130  * <p>
131  * Reading data from request, and update corrispondently the sqlFilter
132  * attribute of DbFormTag is done in the static method generateSqlFilter,
133  * which produce in output a valid filter string. This method is called in
134  * DbFormTag's method doStartTag, setting with it the sqlFilter attribute
135  * value. The only other changes needed in DbFormTag's doStartTag is the
136  * nullifing of the firstPosition and lastPosition variables that normally
137  * contain the current position in the case of applying of a filter (.i.e.
138  * when user press the set button, and so the filter_&lt;tableId&gt;_set
139  * parameter is found in request). This is needed because here we must force
140  * the goto event to move to the first avalilable row.
141  * </p>
142  *
143  * <p></p>
144  *
145  * @author Sergio Moretti
146  * @version $Revision: 1.27 $
147  */

148 public class DbFilterTag extends DbBaseHandlerTag
149    implements javax.servlet.jsp.tagext.TryCatchFinally JavaDoc {
150    /** DOCUMENT ME! */
151    protected static final String JavaDoc FLT_COND = "_cond_";
152
153    /** DOCUMENT ME! */
154    protected static final String JavaDoc FLT_PREFIX = "filter_";
155
156    /** DOCUMENT ME! */
157    protected static final String JavaDoc FLT_SEL = "_sel";
158
159    /** DOCUMENT ME! */
160    protected static final String JavaDoc FLT_SET = "_set";
161
162    /** DOCUMENT ME! */
163    protected static final String JavaDoc FLT_VALUE = "_value_";
164
165    /** DOCUMENT ME! */
166    protected static final String JavaDoc FLT_VALUETYPE = "_valuetype_";
167
168    /** DOCUMENT ME! */
169    protected static final String JavaDoc FLT_SEARCHALGO = "_searchalgo_";
170    private static Log logCat = LogFactory.getLog(DbFilterTag.class
171                                                             .getName());
172
173    /** list of conditions defined for this filter element */
174    private ArrayList JavaDoc conds;
175
176    /** used to override the label of the main select's first option element */
177    private String JavaDoc disabledCaption;
178
179    /** prefix for this filter of the request's parameters */
180    private String JavaDoc filterName;
181
182    /** caption of the SET button */
183    private String JavaDoc setCaption;
184
185    /** size attribute for select element */
186    private String JavaDoc size;
187
188    /** caption of the UNSET button */
189    private String JavaDoc unsetCaption;
190
191    /**
192     * return the currently setted filter condition, reading it from request.
193     *
194     * @param request
195     * @param tableId
196     *
197     * @return filter string
198     */

199    public static String JavaDoc getSqlFilter(HttpServletRequest JavaDoc request,
200                                      int tableId) {
201       int conditionId = getCurrentCondition(request, tableId);
202
203       if (conditionId > -1) {
204          // if there's an active condition, build up it from request
205
return DbFilterConditionTag.getSqlFilter(request, tableId, conditionId);
206       }
207
208       return null;
209    }
210
211
212    /**
213     * return the parametes of the currently setted filter condition, reading
214     * it from request.
215     *
216     * @param request
217     * @param tableId
218     *
219     * @return filter string
220     */

221    public static FieldValue[] getSqlFilterParams(HttpServletRequest JavaDoc request,
222                                                  int tableId) {
223       int conditionId = getCurrentCondition(request, tableId);
224
225       if (conditionId > -1) {
226          // if there's an active condition, build up it from request
227
return DbFilterConditionTag.getSqlFilterParams(request, tableId,
228                                                         conditionId);
229       }
230
231       return null;
232    }
233
234
235    /**
236     * DOCUMENT ME!
237     *
238     * @param string
239     */

240    public void setDisabledCaption(String JavaDoc string) {
241       disabledCaption = string;
242    }
243
244
245    /**
246     * DOCUMENT ME!
247     *
248     * @param string
249     */

250    public void setSetCaption(String JavaDoc string) {
251       setCaption = string;
252    }
253
254
255    /**
256     * DOCUMENT ME!
257     *
258     * @param string
259     */

260    public void setSize(String JavaDoc string) {
261       size = string;
262    }
263
264
265    /**
266     * DOCUMENT ME!
267     *
268     * @param string
269     */

270    public void setUnsetCaption(String JavaDoc string) {
271       unsetCaption = string;
272    }
273
274
275    /**
276     * @see javax.servlet.jsp.tagext.TryCatchFinally#doCatch(java.lang.Throwable)
277     */

278    public void doCatch(Throwable JavaDoc t) throws Throwable JavaDoc {
279       throw t;
280    }
281
282
283    /**
284     * here we read information from nested tags and we render output to the
285     * page.
286     *
287     * @see javax.servlet.jsp.tagext.IterationTag#doEndTag()
288     */

289    public int doEndTag() throws JspException JavaDoc {
290       // retrieve the currently active condition from request
291
int currentCondId = getCurrentCondition((HttpServletRequest JavaDoc) pageContext
292                                               .getRequest(), getTableId());
293       DbFilterConditionTag currentCond = null;
294
295       if (currentCondId > -1) {
296          currentCond = new DbFilterConditionTag();
297
298          // read the object's state stored in array and apply it in newly created object
299
currentCond.setState(pageContext, this,
300                               (DbFilterConditionTag.State) conds.get(currentCondId));
301       }
302
303       StringBuffer JavaDoc buf = render(currentCond);
304
305       try {
306          // clear body content.
307
// It's meaningless for filter tag and should not be rendered!
308
if (bodyContent != null) {
309             bodyContent.clearBody();
310          }
311
312          JspWriter JavaDoc out = pageContext.getOut();
313          out.write(buf.toString());
314       } catch (IOException JavaDoc e) {
315          throw new JspException JavaDoc(e.getMessage());
316       }
317
318       return SKIP_BODY;
319    }
320
321
322    /**
323     * reset tag state
324     *
325     * @see javax.servlet.jsp.tagext.TryCatchFinally#doFinally()
326     */

327    public void doFinally() {
328       conds = null;
329       disabledCaption = null;
330       filterName = null;
331       setCaption = null;
332       size = null;
333       unsetCaption = null;
334       super.doFinally();
335    }
336
337
338    /**
339     * initialize environment
340     *
341     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
342     */

343    public int doStartTag() throws JspException JavaDoc {
344       init();
345
346       return EVAL_BODY_INCLUDE;
347    }
348
349
350    /**
351     * filter prefix
352     *
353     * @param tableId
354     *
355     * @return
356     */

357    protected static String JavaDoc getFilterName(int tableId) {
358       return FLT_PREFIX + tableId;
359    }
360
361
362    /**
363     * filter's parameters prefix in request
364     *
365     * @return
366     */

367    protected String JavaDoc getFilterName() {
368       return filterName;
369    }
370
371
372    /**
373     * return tableId of the parent dbform tag
374     *
375     * @return
376     */

377    protected int getTableId() {
378       return getParentForm()
379                 .getTable()
380                 .getId();
381    }
382
383
384    /**
385     * add a condition object to the list. Called by nested DbFilterConditionTag
386     *
387     * @param condition to add
388     *
389     * @return index of the newly added condition
390     */

391    protected int addCondition(DbFilterConditionTag condition) {
392       conds.add(condition.getState());
393
394       return conds.size() - 1;
395    }
396
397
398    /**
399     * retrieve the currently active condition from request
400     *
401     * @param request
402     * @param tableId
403     *
404     * @return the condition id
405     */

406    private static int getCurrentCondition(HttpServletRequest JavaDoc request,
407                                           int tableId) {
408       int curCondId = -1;
409
410       // retrieve the current condition from parameters
411
String JavaDoc param = ParseUtil.getParameter(request,
412                                             getFilterName(tableId) + FLT_SEL);
413
414       if (!Util.isNull(param)) {
415          // try to transform parameter string in integer
416
try {
417             curCondId = Integer.parseInt(param);
418          } catch (NumberFormatException JavaDoc e) {
419             logCat.error("getCurrentCondition", e);
420          }
421       }
422
423       logCat.debug("setting current filter: " + curCondId);
424
425       return curCondId;
426    }
427
428
429    /**
430     * initialize class fields.
431     */

432    private void init() {
433       conds = new ArrayList JavaDoc();
434       filterName = getFilterName(getTableId());
435
436       if (size == null) {
437          size = "1";
438       }
439
440       if (disabledCaption == null) {
441          disabledCaption = "";
442       }
443
444       if (setCaption == null) {
445          setCaption = "set";
446       }
447
448       if (unsetCaption == null) {
449          unsetCaption = "unset";
450       }
451    }
452
453
454    /**
455     * render output
456     *
457     * @param currentCond
458     *
459     * @return
460     *
461     * @throws JspException
462     */

463    private StringBuffer JavaDoc render(DbFilterConditionTag currentCond)
464                         throws JspException JavaDoc {
465       StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
466
467       // render main select
468
buf.append("\n<select name=\"" + filterName + FLT_SEL + "\" class=\""
469                  + getStyleClass() + "\" size=\"" + size
470                  + "\" onchange=\"document.dbform.submit()\" >\n");
471
472       int cnt = 0;
473       buf.append("\t<option value=\"-1\" >" + disabledCaption + "</option>\n");
474
475       // render an option for each nested condition
476
DbFilterConditionTag cond = new DbFilterConditionTag();
477       Locale JavaDoc locale = MessageResources.getLocale((HttpServletRequest JavaDoc) pageContext
478                                                                .getRequest());
479
480       for (Iterator JavaDoc i = conds.iterator(); i.hasNext();) {
481          // read DbFilterConditionTag object's state stored in array and apply to cond object
482
cond.setState(this.pageContext, this,
483                        (DbFilterConditionTag.State) i.next());
484
485          // select the currently active condition
486
String JavaDoc selected = ((currentCond != null) && currentCond.equals(cond))
487                            ? "selected"
488                            : "";
489
490          // NAK Added support for localization of option label
491
// If the caption is not null and the resources="true" attribute
492
String JavaDoc label = cond.getLabel();
493
494          if ((label != null) && getParentForm()
495                                          .hasCaptionResourceSet()) {
496             try {
497                String JavaDoc message = MessageResources.getMessage(label, locale);
498
499                if (message != null) {
500                   label = message;
501                }
502             } catch (Exception JavaDoc e) {
503                logCat.debug("setCaption(" + label + ") Exception : "
504                             + e.getMessage());
505             }
506          }
507
508          // render option
509
buf.append("\t<option value=\"" + cnt + "\" " + selected + ">" + label
510                     + "</option>\n");
511          cnt++;
512       }
513
514       buf.append("</select>\n");
515
516       if (currentCond != null) {
517          // render the current condition
518
buf.append(currentCond.render());
519
520          if (!Util.isNull(setCaption)) {
521             DbBaseHandlerFactory btn = new DbBaseHandlerFactory(this.pageContext,
522                                                                 this,
523                                                                 DbNavReloadButtonTag.class);
524             ((DbNavReloadButtonTag) btn.getTag()).setCaption(setCaption);
525             ((DbNavReloadButtonTag) btn.getTag()).setForceReload("true");
526             buf.append(btn.render());
527          }
528
529          if (!Util.isNull(unsetCaption)) {
530             DbBaseHandlerFactory btn = new DbBaseHandlerFactory(this.pageContext,
531                                                                 this,
532                                                                 DbNavReloadButtonTag.class);
533             ((DbNavReloadButtonTag) btn.getTag()).setCaption(unsetCaption);
534             ((DbNavReloadButtonTag) btn.getTag()).setOnClick("document.dbform."
535                                                              + filterName
536                                                              + FLT_SEL
537                                                              + ".selectedIndex = -1;");
538             ((DbNavReloadButtonTag) btn.getTag()).setForceReload("true");
539             buf.append(btn.render());
540          }
541       }
542
543       return buf;
544    }
545 }
546
Popular Tags