KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > mlw > vlh > web > tag > DefaultRowTag


1 /**
2  * Copyright (c) 2003 held jointly by the individual authors.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; with out even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * > http://www.gnu.org/copyleft/lesser.html
19  * > http://www.opensource.org/licenses/lgpl-license.php
20  */

21 package net.mlw.vlh.web.tag;
22
23 import java.util.ArrayList 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 net.mlw.vlh.ValueList;
31 import net.mlw.vlh.ValueListInfo;
32 import net.mlw.vlh.web.ValueListConfigBean;
33 import net.mlw.vlh.web.tag.support.ColumnInfo;
34 import net.mlw.vlh.web.tag.support.DisplayProvider;
35 import net.mlw.vlh.web.tag.support.Spacer;
36 import net.mlw.vlh.web.tag.support.ValueListNullSpacer;
37 import net.mlw.vlh.web.util.JspUtils;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /**
43  * This tag creates a table. It is ment to be used along with vlh:root tag.
44  * If the valuelist is empty, render only header.
45  * @todo Document this tag.
46  *
47  * @author Matthew L. Wilson, Andrej Zachar
48  * @version $Revision: 1.37 $ $Date: 2005/12/15 12:49:12 $
49  */

50 public class DefaultRowTag extends ConfigurableTag
51 {
52
53    private static final long serialVersionUID = 4050760477275928119L;
54
55    /** Commons logger. */
56    private static final Log LOGGER = LogFactory.getLog(DefaultRowTag.class);
57
58    /** Parent root tag.*/
59    private ValueListSpaceTag rootTag;
60
61    private DisplayProvider displayProvider;
62
63    private List JavaDoc columns = new ArrayList JavaDoc();
64
65    protected int currentRowNumber = 0;
66
67    protected Object JavaDoc beanInPageScope;
68
69    /** The name and type of the bean put in the pageContext. */
70    protected String JavaDoc bean;
71
72    private int focusRowNumber = -1;
73
74    /**
75     * True - Disable rendering of the header.
76     * False - Check if at least one column has a title, if yes, render header row,
77     * if not, skip it.
78     */

79    private boolean disableHeader = false;
80
81    /**
82     * How to render the header in case of nested value list (the default is <code>true</code>).
83     * <br><code>false</code> - the header of the nested value list is rendered as a part of the top value list
84     * <br><code>true</code> - the header is rendered for each nested valuelist
85     */

86    private boolean nestedHeader = true;
87
88    /**
89     * Initialization is called at the beginning of <code>doStart</code>.
90     * Subclasses have to call either <code>super.init()</code> or <code>super.doStart()</code>.
91     * @throws JspException
92     */

93    protected void init() throws JspException JavaDoc
94    {
95       this.columns.clear();
96    }
97
98    /**
99     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
100     */

101    public int doStartTag() throws JspException JavaDoc
102    {
103
104       init();
105
106       // If the valuelist is empty, render only header
107
ValueList valueList = getRootTag().getValueList();
108       if (valueList == null || valueList.getList() == null || valueList.getList().size() == 0)
109       {
110          getRootTag().setValueList(ValueListNullSpacer.getInstance());
111          LOGGER.warn("ValueList '" + getRootTag().getTableInfo().getName()
112                + "' is empty or null. Continue working with the singleton ValueListNullSpacer.");
113       }
114
115       if (getDisplayProvider().getMimeType() != null)
116       {
117          try
118          {
119             pageContext.getResponse().setContentType(getDisplayProvider().getMimeType());
120          }
121          catch (Exception JavaDoc e)
122          {
123             LOGGER.error("DefaultRowTag.doStartTag() exception...", e);
124             throw new JspException JavaDoc(e);
125          }
126       }
127
128       if (LOGGER.isDebugEnabled())
129       {
130          LOGGER.debug("Starting procesing rows of the table '" + getRootTag().getTableInfo().getId() + "' with the ValueList '"
131                + getRootTag().getTableInfo().getName() + "'.");
132       }
133
134       processIteration();
135
136       return EVAL_BODY_AGAIN;
137    }
138
139    /**
140     * @see javax.servlet.jsp.tagext.IterationTag#doAfterBody()
141     *
142     * @todo figure out why release is not working.
143     */

144    public int doAfterBody() throws JspException JavaDoc
145    {
146       // If this is the first row, then print the column headers!
147
if (currentRowNumber == 0 && getRootTag() != null)
148       {
149          if (isEnabledHeader())
150          {
151             DefaultColumnTag parentColumnTag = (DefaultColumnTag) findAncestorWithClass(this, DefaultColumnTag.class);
152             if (parentColumnTag == null || isNestedHeader())
153             {
154                StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
155                renderHeaderRow(sb, getColumns(), getRootTag().getTableInfo(), getRootTag().getValueList().getValueListInfo(), getRootTag()
156                      .getTableInfo().getParameters());
157                JspUtils.writePrevious(pageContext, sb.toString());
158                columns.clear();
159             }
160             else
161             {
162                // nested valuelist
163
parentColumnTag.setNestedColumnInfoList(columns);
164                columns = new ArrayList JavaDoc();
165             }
166          }
167          else
168          {
169             if (LOGGER.isDebugEnabled())
170             {
171                LOGGER.debug("Header of the table '" + getRootTag().getTableInfo().getId() + "' is skiped.");
172             }
173             columns.clear();
174          }
175       }
176
177       if (beanInPageScope == null || beanInPageScope instanceof Spacer)
178       {
179          // release();
180
return SKIP_BODY;
181       }
182
183       // Render the output from this iteration to the output stream
184
if (bodyContent != null)
185       {
186          String JavaDoc style = getRowStyleClass();
187          pageContext.setAttribute(bean + "Style", style);
188
189          appendClassCellAttribute(style);
190
191          JspUtils.writePrevious(pageContext, getDisplayProvider().getRowPreProcess(getCellAttributes()));
192          if (getDisplayProvider().doesIncludeBodyContent())
193          {
194             JspUtils.writePrevious(pageContext, bodyContent.getString());
195          }
196          else
197          {
198             String JavaDoc html = bodyContent.getString().replaceAll("\\n", "").replaceAll("\\r", "");
199             JspUtils.writePrevious(pageContext, html);
200          }
201
202          JspUtils.writePrevious(pageContext, getDisplayProvider().getRowPostProcess());
203          bodyContent.clearBody();
204       }
205
206       currentRowNumber++;
207       return processIteration();
208    }
209
210    /**
211     * Renders header row. Subclasses can overide or extend the method to provide different behaviour.
212     *
213     * @param sb
214     * @param tableInfo
215     * @param vlInfo
216     * @param parameters
217     * @throws JspException
218     */

219    protected void renderHeaderRow(StringBuffer JavaDoc sb, List JavaDoc columns, TableInfo tableInfo, ValueListInfo vlInfo, Map JavaDoc parameters)
220          throws JspException JavaDoc
221    {
222       sb.append(getDisplayProvider().getHeaderRowPreProcess());
223       for (Iterator JavaDoc iter = columns.iterator(); iter.hasNext();)
224       {
225          renderHeaderCell(sb, (ColumnInfo) iter.next(), tableInfo, vlInfo, parameters);
226       }
227       sb.append(getDisplayProvider().getHeaderRowPostProcess());
228    }
229
230    /**
231     * Renders header cell. Subclasses can overide or extend the method to provide different behaviour.
232     *
233     * @param sb
234     * @param columnInfo
235     * @param tableInfo
236     * @param vlInfo
237     * @param parameters
238     * @throws JspException
239     */

240    protected void renderHeaderCell(StringBuffer JavaDoc sb, ColumnInfo columnInfo, TableInfo tableInfo, ValueListInfo vlInfo, Map JavaDoc parameters)
241          throws JspException JavaDoc
242    {
243       sb.append(getDisplayProvider().getHeaderCellPreProcess(columnInfo, vlInfo));
244       if (columnInfo.getNestedList() != null)
245       {
246          renderNestedHeader(sb, columnInfo, tableInfo, vlInfo, parameters);
247       }
248       else
249       {
250          sb.append(getDisplayProvider().getHeaderLabel(columnInfo, tableInfo, vlInfo, parameters));
251       }
252       sb.append(getDisplayProvider().getHeaderCellPostProcess());
253    }
254
255    protected void renderNestedHeader(StringBuffer JavaDoc sb, ColumnInfo columnInfo, TableInfo tableInfo, ValueListInfo vlInfo, Map JavaDoc parameters)
256          throws JspException JavaDoc
257    {
258       sb.append(getDisplayProvider().getNestedHeaderPreProcess(columnInfo, null));
259       renderHeaderRow(sb, columnInfo.getNestedList(), tableInfo, vlInfo, parameters);
260       sb.append(getDisplayProvider().getNestedHeaderPostProcess());
261    }
262
263    /**
264     * This option could be overwritten by disableHeader (default set to false)
265     * @return true when at least one column's title is not null. false all
266     * titles are null.
267     */

268    protected boolean isEnabledHeader()
269    {
270       if (disableHeader)
271       {
272          return false;
273       }
274       return hasTitle(this.columns);
275    }
276
277    private boolean hasTitle(List JavaDoc columns)
278    {
279       for (Iterator JavaDoc iter = columns.iterator(); iter.hasNext();)
280       {
281          ColumnInfo columnInfo = (ColumnInfo) iter.next();
282          if (columnInfo.getNestedList() != null && hasTitle(columnInfo.getNestedList()) || columnInfo.getTitle() != null)
283          {
284             return true;
285          }
286       }
287       if (LOGGER.isDebugEnabled())
288       {
289          LOGGER.debug("No titles are specified in the table");
290       }
291       return false;
292    }
293
294    /**
295     * @see javax.servlet.jsp.tagext.Tag#doStartTag()
296     */

297    public int doEndTag() throws JspException JavaDoc
298    {
299       if (LOGGER.isDebugEnabled())
300       {
301          LOGGER.debug("End of processing rows of the table '" + getRootTag().getTableInfo().getId() + "' with the ValueList '"
302                + getRootTag().getTableInfo().getName() + "'.");
303       }
304
305       release();
306
307       return EVAL_PAGE;
308    }
309
310    /**
311     * Produces one row.
312     *
313     * @return
314     * @see javax.servlet.jsp.tagext.Tag#doEndTag()
315     * @throws JspException
316     * is an error occurs.
317     */

318    protected int processIteration() throws JspException JavaDoc
319    {
320       if (getRootTag() != null && getRootTag().getValueList() != null && getRootTag().getValueList().hasNext())
321       {
322          pageContext.setAttribute(bean + "RowNumber", new Integer JavaDoc(currentRowNumber));
323          beanInPageScope = getRootTag().getValueList().next();
324
325          if (LOGGER.isDebugEnabled())
326          {
327             LOGGER.debug("In the row no.'" + currentRowNumber + "' was setted the JavaBean '" + bean + "' in the pageContext.");
328          }
329
330          if (beanInPageScope == null || beanInPageScope instanceof Spacer)
331          {
332             pageContext.removeAttribute(bean);
333
334             if (LOGGER.isDebugEnabled())
335             {
336                LOGGER.debug("In the row no.'" + currentRowNumber + "' was not found any ValueList's List's (JavaBean) items to render.");
337             }
338          }
339          else
340          {
341             pageContext.setAttribute(bean, beanInPageScope);
342          }
343          return (EVAL_BODY_AGAIN);
344       }
345       else
346       {
347          // @todo check why you like to call release - it sets BodyTagSupport.parent to null!
348
// release();
349
return SKIP_BODY;
350       }
351    }
352
353    public final ValueListSpaceTag getRootTag() throws JspException JavaDoc
354    {
355       if (rootTag == null)
356       {
357          rootTag = (ValueListSpaceTag) JspUtils.getParent(this, ValueListSpaceTag.class);
358       }
359       return rootTag;
360    }
361
362    /**
363     * @return Returns the displayProvider.
364     * @throws JspException
365     */

366    public DisplayProvider getDisplayProvider() throws JspException JavaDoc
367    {
368       if (displayProvider == null)
369       {
370          displayProvider = getRootTag().getConfig().getDisplayProvider("html");
371          if (displayProvider == null)
372          {
373             LOGGER.error("Error getting default DisplayProvider (html).");
374             displayProvider = ValueListConfigBean.DEFAULT_DISPLAY_PROVIDER;
375          }
376       }
377
378       return displayProvider;
379    }
380
381    public void setDisplay(String JavaDoc display) throws JspException JavaDoc
382    {
383       this.displayProvider = getRootTag().getConfig().getDisplayProvider(display);
384    }
385
386    /**
387     * Gets the current row in the iteration.
388     *
389     * @return The current row in the iteration.
390     */

391    public int getCurrentRowNumber()
392    {
393       return currentRowNumber;
394    }
395
396    /**
397     * Adds a column to this table.
398     *
399     * @param column
400     * The Column to add.
401     */

402    public void addColumnInfo(ColumnInfo column)
403    {
404       columns.add(column);
405    }
406
407    /**
408     * Returns list of <code>ColumnInfo</code> objects.
409     *
410     * @return Returns the columns.
411     */

412    protected List JavaDoc getColumns()
413    {
414       return columns;
415    }
416
417    /**
418     * Sets the name of the bean put in the pageContext.
419     *
420     * @param bean
421     * The name of the bean put in the pageContext.
422     */

423    public void setBean(String JavaDoc bean)
424    {
425       this.bean = bean;
426    }
427
428    /**
429     * Gets the name of the bean put in the pageContext.
430     *
431     * @return The name of the bean put in the pageContext.
432     */

433    public String JavaDoc getBeanName()
434    {
435       return bean;
436    }
437
438    /**
439     * @param focusRowNumber
440     * (0 is considered to be first row) The focusRowNumber to set.
441     */

442    public void setFocusRowNumber(String JavaDoc focusRowNumber)
443    {
444       try
445       {
446          this.focusRowNumber = Integer.parseInt(focusRowNumber);
447       }
448       catch (NumberFormatException JavaDoc e)
449       {
450          this.focusRowNumber = -1;
451       }
452    }
453
454    /**
455     * @param disableHeader The disableHeader to set.
456     */

457    public void setDisableHeader(boolean disableHeader)
458    {
459       this.disableHeader = disableHeader;
460    }
461
462    /**
463     * @return Returns the nestedHeader.
464     * @see #setNestedHeader(boolean)
465     */

466    public boolean isNestedHeader()
467    {
468       return nestedHeader;
469    }
470
471    /**
472     * Set how to render the header in case of nested value list (the default is <code>true</code>).
473     * @param nestedHeader
474     * <code>false</code> - the header of the nested value list is rendered as a part of the top value list
475     * <code>true</code> - the header is rendered for each nested valuelist
476     */

477    public void setNestedHeader(boolean nestedHeader)
478    {
479       this.nestedHeader = nestedHeader;
480    }
481
482    /**
483     * @return style
484     * @throws JspException
485     */

486    public String JavaDoc getRowStyleClass() throws JspException JavaDoc
487    {
488       ValueListConfigBean config = getRootTag().getConfig();
489       if (currentRowNumber == getRootTag().getValueList().getValueListInfo().getFocusedRowNumberInTable())
490       {
491          return config.getFocusedRowStyle();
492
493       }
494       else
495       {
496          return config.getStylePrefix() + (currentRowNumber % config.getStyleCount());
497
498       }
499    }
500
501    private void reset()
502    {
503       this.rootTag = null;
504       this.bean = null;
505       this.beanInPageScope = null;
506       this.columns.clear();
507       this.currentRowNumber = 0;
508       this.disableHeader = false;
509       this.nestedHeader = true;
510       this.displayProvider = null;
511       this.currentRowNumber = 0;
512       this.focusRowNumber = -1;
513    }
514
515    /**
516     * Called on a Tag handler to release state.
517     * The page compiler guarantees that JSP page implementation
518     * objects will invoke this method on all tag handlers,
519     * but there may be multiple invocations on doStartTag and doEndTag in between.
520     *
521     * @see javax.servlet.jsp.tagext.Tag#release()
522     */

523    public void release()
524    {
525       super.release();
526       reset();
527    }
528 }
Popular Tags