KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > databinding > datagrid > api > rendering > DataGridTagModel


1 /*
2  * Copyright 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  * $Header:$
17  */

18 package org.apache.beehive.netui.databinding.datagrid.api.rendering;
19
20 import java.util.HashMap JavaDoc;
21 import javax.servlet.jsp.JspContext JavaDoc;
22 import javax.servlet.http.HttpServletRequest JavaDoc;
23
24 import org.apache.beehive.netui.databinding.datagrid.api.sort.SortDirection;
25 import org.apache.beehive.netui.databinding.datagrid.api.DataGridResourceProvider;
26 import org.apache.beehive.netui.databinding.datagrid.api.DataGridConfig;
27 import org.apache.beehive.netui.databinding.datagrid.api.DataGridURLBuilder;
28 import org.apache.beehive.netui.databinding.datagrid.api.DataGridState;
29 import org.apache.beehive.netui.databinding.datagrid.api.DataGridStateFactory;
30 import org.apache.beehive.netui.databinding.datagrid.runtime.rendering.table.TableRenderer;
31 import org.apache.beehive.netui.databinding.datagrid.runtime.util.PagedDataSet;
32 import org.apache.beehive.netui.databinding.datagrid.runtime.util.JspUtil;
33 import org.apache.beehive.netui.tags.rendering.AbstractRenderAppender;
34 import org.apache.beehive.netui.util.Bundle;
35
36 /**
37  * <p>
38  * The DataGridTagModel is a JavaBean that is exposed by the NetUI data grid tag into
39  * the {@link javax.servlet.jsp.PageContext} in a JSP. This bean exposes state and services
40  * which can be data bound by an expression language in a JSP.
41  * </p>
42  */

43 public class DataGridTagModel {
44
45     /**
46      * The render state used when the data grid performs its first pass through its tag body.
47      */

48     public static final int RENDER_STATE_START = 10;
49
50     /**
51      * The render state used when the data grid is rendering the caption tag.
52      */

53     public static final int RENDER_STATE_CAPTION = 20;
54
55     /**
56      * The render state used when the data grid is rendering the header tag.
57      */

58     public static final int RENDER_STATE_HEADER = 30;
59
60     /**
61      * The render state used when the data grid is rendering the data rows.
62      */

63     public static final int RENDER_STATE_GRID = 40;
64
65     /**
66      * The render state used when the data grid is rendering the footer.
67      */

68     public static final int RENDER_STATE_FOOTER = 50;
69
70     /**
71      * The render state used when the data grid has completed rendering.
72      */

73     public static final int RENDER_STATE_END = 60;
74
75     private static final int RENDER_STATE_UNINIT = -1;
76
77     private int _renderState = RENDER_STATE_UNINIT;
78     private boolean _disableDefaultPagerRendering = false;
79     private boolean _renderRowGroups = false;
80     private String JavaDoc _name = null;
81
82     private JspContext JavaDoc _jspContext = null;
83     private HttpServletRequest JavaDoc _request = null;
84     private StyleModel _styleModel = null;
85     private PagerRenderer _pagerRenderer = null;
86     private PagedDataSet _dataSet = null;
87     private TableRenderer _tableRenderer = null;
88     private DataGridResourceProvider _resourceProvider = null;
89     private DataGridState _dataGridState = null;
90     private DataGridURLBuilder _urlBuilder = null;
91     private DataGridConfig _dataGridConfig = null;
92
93     /**
94      * Constructor used to build a DataGridTagModel.
95      *
96      * @param name the name of the data grid
97      * @param dataGridConfig the {@link DataGridConfig} object for a data grid
98      * @param jspContext the {@link JspContext} for the JSP in which the data grid's rendering started
99      */

100     public DataGridTagModel(String JavaDoc name, DataGridConfig dataGridConfig, JspContext JavaDoc jspContext) {
101         super();
102
103         _jspContext = jspContext;
104         _request = JspUtil.getRequest(_jspContext);
105
106         _name = name;
107         _dataGridConfig = dataGridConfig;
108
109         DataGridStateFactory stateFactory = DataGridStateFactory.getInstance(_jspContext);
110         _dataGridState = stateFactory.getDataGridState(_name, _dataGridConfig);
111         _urlBuilder = stateFactory.getDataGridURLBuilder(_name, _dataGridConfig);
112     }
113
114     /**
115      * Accessor for the name of the data grid.
116      *
117      * @return the name of the data grid
118      */

119     public String JavaDoc getName() {
120         return _name;
121     }
122
123     /**
124      * Accessor for the {@link JspContext} for the JSP in which the grid started to render.
125      *
126      * @return the {@link JspContext}
127      */

128     public JspContext JavaDoc getJspContext() {
129         return _jspContext;
130     }
131
132     /**
133      * <p>
134      * Accessor for the current render state. This should be used by clients that need to
135      * affect their behavior based on the data grid's current render state. This value will
136      * be one of:
137      * <ul>
138      * <li>{@link #RENDER_STATE_START}</li>
139      * <li>{@link #RENDER_STATE_CAPTION}</li>
140      * <li>{@link #RENDER_STATE_HEADER}</li>
141      * <li>{@link #RENDER_STATE_GRID}</li>
142      * <li>{@link #RENDER_STATE_FOOTER}</li>
143      * <li>{@link #RENDER_STATE_END}</li>
144      * </ul>
145      * </p>
146      *
147      * @return the current render state
148      */

149     public int getRenderState() {
150         return _renderState;
151     }
152
153     /**
154      * <p>
155      * Method that alters the data grid's current render to the new <code>renderState</code>. If
156      * the provided render state value is unknown, an {@link IllegalStateException} is thrown. The
157      * data grid cycles through its state in this order:
158      * <ul>
159      * <li>{@link #RENDER_STATE_START}</li>
160      * <li>{@link #RENDER_STATE_CAPTION}</li>
161      * <li>{@link #RENDER_STATE_HEADER}</li>
162      * <li>{@link #RENDER_STATE_GRID}</li>
163      * <li>{@link #RENDER_STATE_FOOTER}</li>
164      * <li>{@link #RENDER_STATE_END}</li>
165      * </ul>
166      * </p>
167      *
168      * @param renderState the DataGridTagModel's new render state
169      * @throws IllegalStateException if an invalid state is provided
170      */

171     public void changeRenderState(int renderState) {
172         switch(_renderState) {
173             case RENDER_STATE_UNINIT:
174                 _renderState = RENDER_STATE_START;
175                 break;
176             case RENDER_STATE_START:
177                 _renderState = RENDER_STATE_CAPTION;
178                 break;
179             case RENDER_STATE_CAPTION:
180                 _renderState = RENDER_STATE_HEADER;
181                 break;
182             case RENDER_STATE_HEADER:
183                 _renderState = RENDER_STATE_GRID;
184                 break;
185             case RENDER_STATE_GRID:
186                 _renderState = RENDER_STATE_FOOTER;
187                 break;
188             case RENDER_STATE_FOOTER:
189                 _renderState = RENDER_STATE_END;
190                 break;
191             default:
192                 throw new IllegalStateException JavaDoc(Bundle.getErrorString("DataGridTagModel_InvalidStateTransition"));
193         }
194
195         return;
196     }
197
198     /**
199      * Accessor for the {@link PagedDataSet} that is used to render a data set in the grid.
200      *
201      * @return a {@link PagedDataSet} for the current data set
202      */

203     public PagedDataSet getDataSet() {
204         return _dataSet;
205     }
206
207     /**
208      * Setter for the {@link PagedDataSet} object. In order to canonicalize the type used by
209      * the data grid to manipulate the data set, the {@link PagedDataSet} is used to
210      * navigate the data set.
211      *
212      * @param dataSet the data set
213      */

214     public void setDataSet(PagedDataSet dataSet) {
215         /* todo: would be nice to address this side-effect outside of the setter */
216         _dataSet = dataSet;
217         _dataGridState.getPagerModel().setDataSetSize(_dataSet.getSize());
218     }
219
220     /**
221      * Accessor for the {@link PagerRenderer}. This is the {@link PagerRenderer} instance that
222      * will be used to render the UI used to display the pager.
223      *
224      * @return the {@link PagerRenderer} for the data grid
225      */

226     public PagerRenderer getPagerRenderer() {
227         if(_pagerRenderer == null)
228             setPagerRenderer(_dataGridConfig.getDefaultPagerRenderer());
229
230         return _pagerRenderer;
231     }
232
233     /**
234      * Set the {@link PagerRenderer} used to render the paging UI for the data grid.
235      *
236      * @param pagerRenderer the {@link PagerRenderer} to use
237      */

238     public void setPagerRenderer(PagerRenderer pagerRenderer) {
239         /* todo: would be nice to address this side-effect outside of the setter */
240         _pagerRenderer = pagerRenderer;
241         _pagerRenderer.setDataGridTagModel(this);
242     }
243
244     /**
245      * Get the {@link DataGridResourceProvider} used to provide string messages, paths, etc during
246      * data grid rendering.
247      *
248      * @return the {@link DataGridResourceProvider}
249      */

250     public DataGridResourceProvider getResourceProvider() {
251         return _resourceProvider;
252     }
253
254     /**
255      * Set the {@link DataGridResourceProvider} used to render the data grid.
256      * @param resourceProvider the new resource provider
257      */

258     public void setResourceProvider(DataGridResourceProvider resourceProvider) {
259         _resourceProvider = resourceProvider;
260     }
261
262     /**
263      * Check to see if the data grid will render its pager UI by default. The location for the default UI
264      * is controlled by the JSP tag doing the rendering.
265      * @return <code>true</code> if default rendering is enabled; <code>false</code> otherwise.
266      */

267     public boolean isDisableDefaultPagerRendering() {
268         return _disableDefaultPagerRendering;
269     }
270
271     /**
272      * Set a boolean to enable or disable rendering the pager UI by default. If <code>true</code>, the
273      * data grid rendering tags will produce the pager markup in some default location. If <code>false</code>
274      * the default pager rendering will be disabled. The default location is determined by the tags
275      * doing the rendering.
276      * @param disableDefaultPagerRendering boolean for enabling or disabling rendering the pager in the default location
277      */

278     public void setDisableDefaultPagerRendering(boolean disableDefaultPagerRendering) {
279         _disableDefaultPagerRendering = disableDefaultPagerRendering;
280     }
281
282     /**
283      * <p>
284      * Get the flag for whether to render the data grid using HTML row groups. Row groups include the HTML
285      * <code>thead</code>, <code>tbody</code>, and <code>tfoot</code> tags. If row group rendering is enabled,
286      * the HTML produced by the data grid will be contained inside of these tags and rendered in the correct
287      * order in the produced HTML. More detail on row groups can be found
288      * <a HREF="http://www.w3.org/TR/REC-html40/struct/tables.html#h-11.2.3">here</a>.
289      * </p>
290      * @return <code>true</code> if row groups will be rendered; <code>false</code> otherwise
291      */

292     public boolean isRenderRowGroups() {
293         return _renderRowGroups;
294     }
295
296     /**
297      * Set whether to render the data grid using HTML row groups. For more detail, see {@link #isRenderRowGroups()}.
298      *
299      * @param renderRowGroups <code>true</code> if rendering row groups; <code>false</code> otherwise
300      */

301     public void setRenderRowGroups(boolean renderRowGroups) {
302         _renderRowGroups = renderRowGroups;
303     }
304
305     /**
306      * Get the instance of {@link TableRenderer} that is used to render HTML table markup for a data grid.
307      * @return the {@link TableRenderer}
308      */

309     public TableRenderer getTableRenderer() {
310         return _tableRenderer;
311     }
312
313     /**
314      * Set the {@link TableRenderer} used to render HTML table markup for a data grid.
315      * @param tableRenderer the {@link TableRenderer} to use for rendering
316      */

317     public void setTableRenderer(TableRenderer tableRenderer) {
318         _tableRenderer = tableRenderer;
319     }
320
321     /**
322      * Get the {@link StyleModel} used to create style classes during data grid rendering.
323      * @return the {@link StyleModel}
324      */

325     public StyleModel getStyleModel() {
326         return _styleModel;
327     }
328
329     /**
330      * Set the {@link StyleModel} used to create style classes during data grid rendering.
331      * @param styleModel the {@link StyleModel}
332      */

333     public void setStyleModel(StyleModel styleModel) {
334         _styleModel = styleModel;
335     }
336
337     /**
338      * Get a message given a resource string name <code>key</code>.
339      * @param key the message key
340      * @return the value of the message
341      */

342     public String JavaDoc getMessage(String JavaDoc key) {
343         assert _resourceProvider != null : "Received a null resource provider";
344         return _resourceProvider.getMessage(key);
345     }
346
347     /**
348      * Format a message given a resource string name <code>key</code> and a set of
349      * formatting arguments <code>args</code>.
350      * @param key the message key
351      * @param args the arguments used when formatting the message
352      * @return the formatted message
353      */

354     public String JavaDoc formatMessage(String JavaDoc key, Object JavaDoc[] args) {
355         assert _resourceProvider != null : "Received a null resource provider";
356         return _resourceProvider.formatMessage(key, args);
357     }
358
359     /**
360      * <p>
361      * This method provides support for overriding the messages available in the {@link DataGridResourceProvider} on a
362      * per-message basis. The key and value parameters here will override (or add) a message available via
363      * the {@link DataGridResourceProvider} without requiring an entire Java properties file or custom
364      * {@link DataGridResourceProvider} implementation.
365      * </p>
366      * @param key the key of the message to override
367      * @param value the new value for the message key
368      */

369     public void addResourceOverride(String JavaDoc key, String JavaDoc value) {
370         OverridableDataGridResourceProvider overrideResourceProvider = null;
371         if(!(_resourceProvider instanceof OverridableDataGridResourceProvider)) {
372             overrideResourceProvider = new OverridableDataGridResourceProvider(_resourceProvider);
373             _resourceProvider = overrideResourceProvider;
374         }
375         else {
376             assert _resourceProvider instanceof OverridableDataGridResourceProvider;
377             overrideResourceProvider = (OverridableDataGridResourceProvider)_resourceProvider;
378         }
379
380         overrideResourceProvider.addResourceOverride(key, value);
381     }
382
383     /**
384      * <p>
385      * Get the resourrce path used when creating HTML image links during data grid rendering. The value of the
386      * default resource path is the {@link javax.servlet.http.HttpServletRequest#getContextPath()} combined
387      * with the value of the data grid message stringn obtained with the key {@link IDataGridMessageKeys#DATAGRID_RESOURCE_PATH}.
388      * </p>
389      * @return the string resource path
390      */

391     public String JavaDoc getResourcePath() {
392         /* todo: fix the message here to format with the context path */
393         return _request.getContextPath() + "/" + getMessage(IDataGridMessageKeys.DATAGRID_RESOURCE_PATH);
394     }
395
396     /**
397      * <p>
398      * Get the image paths used for the given {@link SortDirection}. The image paths are discovered
399      * by using the following mapping.
400      * <br/>
401      * <table>
402      * <tr><td>Sort direction</td><td>Message key</td></tr>
403      * <tr><td><code>{@link SortDirection#ASCENDING}</code></td><td><code>{@link IDataGridMessageKeys#SORT_ASC_IMAGE_PATH}</code></td></tr>
404      * <tr><td><code>{@link SortDirection#DESCENDING}</code></td><td><code>{@link IDataGridMessageKeys#SORT_DESC_IMAGE_PATH}</code></td></tr>
405      * <tr><td><code>{@link SortDirection#NONE}</code></td><td><code>{@link IDataGridMessageKeys#SORT_NONE_IMAGE_PATH}</code></td></tr>
406      * </table>
407      * The value for the message is obtained by looking up a value in the {@link DataGridResourceProvider} obtained
408      * via {@link #getResourceProvider()} using the message key in the table above.
409      * </p>
410      * @param sortDirection the {@link SortDirection} used to lookup an image path
411      * @return the string image used to represent a sort direction graphically
412      */

413     public String JavaDoc getSortImagePath(SortDirection sortDirection) {
414         /* todo: move to the DataGridConfig object */
415         if(sortDirection == SortDirection.ASCENDING)
416             return getMessage(IDataGridMessageKeys.SORT_ASC_IMAGE_PATH);
417         else if(sortDirection == SortDirection.DESCENDING)
418             return getMessage(IDataGridMessageKeys.SORT_DESC_IMAGE_PATH);
419         else {
420             assert sortDirection == SortDirection.NONE : "Encountered an invalid sort direction.";
421             return getDefaultSortImagePath();
422         }
423     }
424
425     /**
426      * Get the default image path used when constructing links to sort images. This value
427      * is taken from the resource String available via the {@link DataGridResourceProvider}
428      * obtained using {@link #getResourceProvider()} using the {@link IDataGridMessageKeys#SORT_NONE_IMAGE_PATH} key.
429      * @return the String path
430      */

431     public String JavaDoc getDefaultSortImagePath() {
432         return getMessage(IDataGridMessageKeys.SORT_NONE_IMAGE_PATH);
433     }
434
435     /**
436      * Method used to render the data grid's pager UI into the given {@link AbstractRenderAppender}.
437      *
438      * @param appender the {@link AbstractRenderAppender} into which the pager will be rendered
439      */

440     public void renderPager(AbstractRenderAppender appender) {
441         if(getPagerRenderer() != null)
442             appender.append(getPagerRenderer().render());
443     }
444
445     /**
446      * Accessor for obtaining the {@link DataGridState} object. This is a JavaBean
447      * property that can be accessed via an expression language in order to obtain
448      * access to the state information for the data grid stored in the returned object.
449      *
450      * @return the data grid's {@link DataGridState}
451      */

452     public DataGridState getState() {
453         return _dataGridState;
454     }
455
456     /**
457      * Accessor for obtaining the {@link DataGridURLBuilder} object. This is a JavaBean
458      * that can be accessed via an expression language in order to obtain access to the
459      * URL information for the data grid stored in the returned object.
460      *
461      * @return the data grid's {@link DataGridURLBuilder}
462      */

463     public DataGridURLBuilder getUrlBuilder() {
464         return _urlBuilder;
465     }
466
467     /**
468      * Accessor for obtaining the current index in the data set. This value is a zero
469      * based count current item being rendered. For the array {"foo", "bar", "baz"}, the
470      * indices for each item would be 0, 1, and 2. This value does correspond to the
471      * index into an Object array or a list, but in an arbitrary Collection, the index
472      * is simply the number of items that appeared in the Collection before the current one.
473      *
474      * @return the current index
475      */

476     public int getCurrentIndex() {
477         assert _dataSet != null;
478         return _dataSet.getCurrentIndex();
479     }
480
481     /**
482      * Accessor for obtaining the current item in the data set.
483      *
484      * @return the current item in the data set
485      */

486     public Object JavaDoc getCurrentItem() {
487         assert _dataSet != null;
488         return _dataSet.getCurrentItem();
489     }
490
491     /**
492      * Accessor for obtaining the data source expression that was used to data bind to the data set.
493      *
494      * @return the String for the data source
495      */

496     public String JavaDoc getDataSource() {
497         assert _dataSet != null;
498         return _dataSet.getDataSource();
499     }
500
501     /**
502      * Accessor for getting the next item in the data set.
503      *
504      * @return the next item in the data set. Note, depending on the data set, this item could
505      * be <code>null</code>.
506      */

507     public Object JavaDoc nextDataItem() {
508         assert _dataSet != null;
509         return _dataSet.next();
510     }
511
512     /**
513      * Accessor for determining if there is another item in the data set.
514      *
515      * @return <code>true</code> if there is a next item; <code>false</code> otherwise.
516      */

517     public boolean hasNextDataItem() {
518         assert _dataSet != null;
519         return _dataSet.hasNext();
520     }
521
522     /* -------------------------------------------------------------
523
524        Implementation specifics
525
526        ------------------------------------------------------------- */

527
528     /**
529      * <p>
530      * An internal class that represents a {@link DataGridResourceProvider} that supports
531      * property-by-property overrides. A JSP is able to specify message keys whose values
532      * to override; in situations where this functionality is used, this class provides
533      * the {@link DataGridResourceProvider} abstraction that implements this override
534      * functionality.
535      * </p>
536      */

537     private final class OverridableDataGridResourceProvider
538             extends DataGridResourceProvider {
539
540         private DataGridResourceProvider _delegate = null;
541         private HashMap JavaDoc/*<String, String>*/ _resourceOverrides = null;
542
543         private OverridableDataGridResourceProvider(DataGridResourceProvider resourceProvider) {
544             _delegate = resourceProvider;
545         }
546
547         private void addResourceOverride(String JavaDoc key, String JavaDoc value) {
548             if(_resourceOverrides == null)
549                 _resourceOverrides = new HashMap JavaDoc/*<String, String>*/();
550
551             /* todo: could consider asserting that this key is known by the data grid framework */
552             _resourceOverrides.put(key, value);
553         }
554
555         public String JavaDoc getMessage(String JavaDoc key) {
556             String JavaDoc msg = internalGetMessage(key);
557             if(msg != null)
558                 return msg;
559             else
560                 return _delegate.getMessage(key);
561         }
562
563         public String JavaDoc formatMessage(String JavaDoc key, Object JavaDoc[] args) {
564             String JavaDoc pattern = internalGetMessage(key);
565             if(pattern != null)
566                 return internalFormatMessage(pattern, args);
567             else
568                 return _delegate.formatMessage(key, args);
569         }
570
571         private final String JavaDoc internalGetMessage(String JavaDoc key) {
572             if(_resourceOverrides != null && _resourceOverrides.containsKey(key))
573                 return (String JavaDoc)_resourceOverrides.get(key);
574             else
575                 return null;
576         }
577     }
578 }
579
Popular Tags