KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > improve > struts > taglib > layout > collection > CollectionTag


1 package fr.improve.struts.taglib.layout.collection;
2
3 import java.lang.reflect.InvocationTargetException JavaDoc;
4 import java.lang.reflect.Method JavaDoc;
5 import java.text.DecimalFormat JavaDoc;
6 import java.text.NumberFormat JavaDoc;
7 import java.util.ArrayList JavaDoc;
8 import java.util.HashMap JavaDoc;
9 import java.util.Iterator JavaDoc;
10 import java.util.List JavaDoc;
11 import java.util.Map JavaDoc;
12
13 import javax.servlet.http.HttpServletResponse JavaDoc;
14 import javax.servlet.jsp.JspException JavaDoc;
15
16 import org.apache.struts.taglib.html.Constants;
17 import org.apache.struts.util.RequestUtils;
18
19 import fr.improve.struts.taglib.layout.collection.header.MultiLevelHeader;
20 import fr.improve.struts.taglib.layout.el.Expression;
21 import fr.improve.struts.taglib.layout.event.StaticCodeIncludeLayoutEvent;
22 import fr.improve.struts.taglib.layout.event.StaticCodeIncludeListener;
23 import fr.improve.struts.taglib.layout.sort.SortUtil;
24 import fr.improve.struts.taglib.layout.util.IFooterRenderer;
25 import fr.improve.struts.taglib.layout.util.IMathCollectionRenderer;
26 import fr.improve.struts.taglib.layout.util.IMultiLevelHeaderRenderer;
27 import fr.improve.struts.taglib.layout.util.LayoutUtils;
28
29
30
31 /**
32  * This class is responsible for displaying the collection.<br />
33  * Actually, the rendering is done by another class implementing the CollectionInterface.
34  * This class just computes differents parameters (headers and items).
35  * @author: Jean-Noel Ribette
36  **/

37 public class CollectionTag extends BaseCollectionTag implements StaticCodeIncludeListener {
38     /**
39      * Math class
40      */

41     static Class JavaDoc mathClass;
42     
43     static {
44         try {
45             mathClass = RequestUtils.applicationClass("org.apache.commons.math.stat.StatUtils");
46         } catch (ClassNotFoundException JavaDoc e) {
47             // Math class is not available.
48
}
49     }
50     
51     /**
52      * String of the static code to generate.
53      */

54     private String JavaDoc staticCode = "";
55     
56     /**
57      * Map of the numbers for operation
58      */

59     protected Map JavaDoc numbers = new HashMap JavaDoc();
60     
61     /* (non-Javadoc)
62      * @see fr.improve.struts.taglib.layout.BodyLayoutTagSupport#reset()
63      */

64     protected void reset() {
65         numbers.clear();
66         super.reset();
67     }
68     /**
69      * Store in a List the value of the cells for selected column in a map
70      * @author Damien Viel
71      * @version 1.0
72      * @throws JspException
73      *
74      */

75     protected void storeMathData(double in_value) throws JspException JavaDoc {
76         if (!isFirst()) {
77             int lc_ligne = getIndex();
78             int lc_col = getColumn();
79             Object JavaDoc bean = getBean();
80             String JavaDoc property = ((ItemContext)headers.get(lc_col)).getProperty();
81             String JavaDoc mathOp = ((ItemContext)headers.get(lc_col)).getMathOperation();
82             if (mathOp!=null) {
83                String JavaDoc key = String.valueOf(lc_col);
84                if (!numbers.containsKey(key)){
85                     double[] lc_list = new double[size]; // ???
86
numbers.put(key,lc_list);
87                }
88                 double[] lc_list = (double[]) numbers.get(key);
89                lc_list[index-1] = in_value;
90             }
91         }
92     }
93     /**
94      *
95      * @author Damien Viel
96      * @param in_operation
97      * @param in_data
98      * @return
99      * @throws JspException
100      */

101     protected String JavaDoc doMathOperation(String JavaDoc in_operation, double[] in_data, String JavaDoc in_mathPattern) throws JspException JavaDoc {
102         if (in_data!=null && in_operation!=null && in_operation.length()>0){
103             double total = computeMathResult(in_operation, in_data);
104             if (in_mathPattern!=null){
105                 NumberFormat JavaDoc lc_format = new DecimalFormat JavaDoc(in_mathPattern);
106                 return lc_format.format(total);
107             }
108             return String.valueOf(total);
109         }
110         return null;
111     }
112     /**
113      *
114      * @author JNRibette
115      * @param in_operation
116      * @param in_data
117      * @return
118      * @throws JspException
119      */

120     protected double computeMathResult(String JavaDoc in_operation, double[] in_data) throws JspException JavaDoc {
121         if (mathClass==null) {
122             throw new IllegalStateException JavaDoc("Math operation is not available, please put commons-math.jar in the classpath");
123         }
124         Method JavaDoc m;
125         try {
126             m = mathClass.getMethod(in_operation, new Class JavaDoc[]{double[].class});
127         } catch (NoSuchMethodException JavaDoc e) {
128             throw new IllegalArgumentException JavaDoc("Math operation " + in_operation + " is not supported");
129         }
130         Double JavaDoc result = null;
131         try {
132             result = (Double JavaDoc) m.invoke(null,new Object JavaDoc[]{in_data});
133         } catch (InvocationTargetException JavaDoc e) {
134             // TODO log
135
throw new JspException JavaDoc("Math operation " + in_operation + " failed : " + e.getMessage());
136         } catch (IllegalAccessException JavaDoc e) {
137             // TODO log
138
throw new JspException JavaDoc("Math operation " + in_operation + " failed : " + e.getMessage());
139         }
140         return result.doubleValue();
141         //return new BigDecimal(result.doubleValue()).setScale(3,BigDecimal.ROUND_HALF_UP).doubleValue();
142
}
143
144
145     
146 /**
147  * add an item.
148  */

149 protected void addItem(StringBuffer JavaDoc in_buffer, String JavaDoc in_item, String JavaDoc in_url, String JavaDoc in_target, String JavaDoc in_onclick) throws JspException JavaDoc {
150     // Display the table cell.
151
if (in_url==null) {
152         renderItem(in_buffer, in_item);
153     } else {
154         StringBuffer JavaDoc lc_buffer = new StringBuffer JavaDoc();
155         String JavaDoc lc_item = in_item;
156         if (sortType==SORT_JAVASCRIPT) {
157             if (lc_item.startsWith("<!--")) {
158                 // if we are sorting the collection on the client, make sure the resulting item still begin with the comment
159
// which may be used to sort the items.
160
int lc_index = lc_item.indexOf("-->");
161                 lc_buffer.append(lc_item.substring(0, lc_index +3));
162                 lc_item = lc_item.substring(lc_index+3);
163             } else {
164                 // same concern, in case there is no preliminar comment.
165
lc_buffer.append("<!-- ");
166                 lc_buffer.append(in_item);
167                 lc_buffer.append("-->");
168             }
169         }
170         
171         lc_buffer.append("<a HREF=\"");
172         lc_buffer.append(((HttpServletResponse JavaDoc)pageContext.getResponse()).encodeURL(in_url));
173         if (in_onclick!=null) {
174             lc_buffer.append("\" onClick=\"");
175             lc_buffer.append(Expression.evaluate(in_onclick, pageContext));
176         }
177         if (in_target!=null) {
178             lc_buffer.append("\" target=\"");
179             lc_buffer.append(in_target);
180         }
181         String JavaDoc lc_styleClass = styleClass;
182         if (tempStyleClass != null) lc_styleClass = tempStyleClass;
183         if (lc_styleClass != null) {
184             lc_buffer.append("\" class=\"");
185             lc_buffer.append(lc_styleClass);
186         }
187         lc_buffer.append("\">");
188         lc_buffer.append(lc_item);
189         lc_buffer.append("</a>");
190         renderItem(in_buffer, lc_buffer.toString());
191     }
192 }
193
194
195 protected void renderBlankCollection(StringBuffer JavaDoc in_buffer) throws JspException JavaDoc {
196     panel.doPrintEmptyCollection(in_buffer, LayoutUtils.getLabel(pageContext, getBundle(), emptyKey, null, false));
197 }
198     // render the end of the table
199
protected void renderEnd(StringBuffer JavaDoc buffer) throws JspException JavaDoc {
200         renderMathData(buffer);
201         renderFooter(buffer);
202         panel.doEndPanel(buffer);
203         renderStaticCode(buffer);
204     }
205     
206     /**
207      * Render the result for the specified math operation
208      * @param in_buffer
209      * @throws JspException
210      */

211     protected void renderMathData(StringBuffer JavaDoc in_buffer) throws JspException JavaDoc {
212         if (!(panel instanceof IMathCollectionRenderer)) {
213             return;
214         }
215         IMathCollectionRenderer lc_renderer = (IMathCollectionRenderer) panel;
216     
217         // did we start generated footer ?
218
boolean started = false;
219         // number of null consecutive footer.
220
int consecutiveNull = 0;
221         String JavaDoc uniqueParam = mathOperationId;
222         int lc_nbOfSpan = 0;
223         for (int i=0; i < headers.size(); i++) {
224             ItemContext lc_header = (ItemContext) headers.get(i);
225             String JavaDoc lc_operation = lc_header.getMathOperation();
226             String JavaDoc lc_mathStyleClass = tempStyleClass!=null ? tempStyleClass : styleClass;
227             String JavaDoc lc_mathPattern = lc_header.getMathPattern();
228             double[] data = (double[])numbers.get(String.valueOf(i));
229             String JavaDoc lc_data = doMathOperation(lc_operation,data,lc_mathPattern);
230             // Unique identifier for the result cell
231
String JavaDoc resultId = CollectionInputTag.MATH_ID_PREFIX + "t" + uniqueParam + "r" + i;
232             
233             // If there is no math operation to do
234
if (lc_operation==null) {
235                 consecutiveNull++;
236             } else {
237                 if (!started){
238                     // Start rendering result !
239
lc_renderer.startMathData(in_buffer);
240                     started = true;
241                 }
242                                 
243                 // Generate an empty td with colspan = number of consecutive null.
244
if (consecutiveNull>0) {
245                     lc_renderer.renderMathData(in_buffer, "&nbsp;", consecutiveNull, null,lc_mathStyleClass);
246                     lc_nbOfSpan = lc_nbOfSpan + consecutiveNull;
247                 }
248                 
249                 // Generate the result cell.
250
lc_renderer.renderMathData(in_buffer, lc_data, 1, resultId,lc_mathStyleClass);
251                 consecutiveNull = 0;
252                 lc_nbOfSpan = lc_nbOfSpan + 1;
253             }
254         }
255         if (started) {
256             if (headers.size()-lc_nbOfSpan>0){
257                 lc_renderer.renderMathData(in_buffer, "&nbsp;", headers.size()-lc_nbOfSpan, null,styleClass);
258             }
259             // There were result, close.
260
lc_renderer.endMathData(in_buffer);
261         }
262         
263     }
264     
265     /**
266      * Render the footer of the collection.
267      */

268     protected void renderFooter(StringBuffer JavaDoc in_buffer) throws JspException JavaDoc {
269         // Get IFooterRenderer
270
if (!(panel instanceof IFooterRenderer)) {
271             return;
272         }
273         IFooterRenderer lc_renderer = (IFooterRenderer) panel;
274         
275         // did we start generated footer ?
276
boolean started = false;
277         
278         // number of null consecutive footer.
279
int consecutiveNull = 0;
280         
281         for (int i=0; i < headers.size(); i++) {
282             ItemContext lc_header = (ItemContext) headers.get(i);
283             String JavaDoc lc_footer = lc_header.getFooter();
284             if (lc_footer==null) {
285                 consecutiveNull++;
286             } else {
287                 if (!started){
288                     // Start rendering footer !
289
lc_renderer.startFooter(in_buffer);
290                     started = true;
291                 }
292                 
293                 // Generate an empty td with colspan = number of consecutive null.
294
if (consecutiveNull>0) {
295                     lc_renderer.printFooterElement(in_buffer, "&nbsp;", consecutiveNull);
296                 }
297                 
298                 // Generate the footer.
299
Object JavaDoc[] lc_args = new Object JavaDoc[5];
300                 lc_args[0] = Expression.evaluate(lc_header.getFooterArg0(), pageContext);
301                 lc_args[1] = Expression.evaluate(lc_header.getFooterArg1(), pageContext);
302                 String JavaDoc lc_label = LayoutUtils.getLabel(pageContext, getBundle(), lc_footer, lc_args, false);
303                 lc_renderer.printFooterElement(in_buffer, lc_label, 1);
304                 consecutiveNull = 0;
305                 
306             }
307         }
308         
309         if (started) {
310             // There were footer, close.
311
lc_renderer.endFooter(in_buffer);
312         }
313     }
314     
315     
316 /**
317  * Print a column title to the buffer.
318  * (mono level header)
319  */

320 protected void renderHeader(StringBuffer JavaDoc buffer, ItemContext in_header) throws JspException JavaDoc {
321     
322     // Compute the title.
323
String JavaDoc lc_key = in_header.getTitle();
324     String JavaDoc lc_arg0 = Expression.evaluate(in_header.getArg0(), pageContext);
325     String JavaDoc lc_arg1 = Expression.evaluate(in_header.getArg1(), pageContext);
326     Object JavaDoc[] lc_args = new Object JavaDoc[2];
327     lc_args[0] = lc_arg0;
328     lc_args[1] = lc_arg1;
329     String JavaDoc lc_title = LayoutUtils.getLabel(pageContext, getBundle(), lc_key, lc_args, false);
330     
331     // Compute the sort url.
332
String JavaDoc lc_sortUrl = computeSortUrl(in_header.getSortProperty());
333         
334     // Print the title.
335
panel.doPrintHeader(buffer, lc_title, in_header.getWidth(), lc_sortUrl);
336 }
337
338     protected String JavaDoc computeSortUrl(String JavaDoc in_sortProperty) {
339         String JavaDoc lc_sortUrl = null;
340         if (in_sortProperty!=null) {
341             StringBuffer JavaDoc lc_tempBuffer = new StringBuffer JavaDoc();
342             switch (sortType) {
343                 case SORT_LAYOUT:
344                     String JavaDoc lc_unEncodedUrl = SortUtil.getURLForCollection(in_sortProperty, (javax.servlet.http.HttpServletRequest JavaDoc) pageContext.getRequest());
345                     lc_tempBuffer.append(((HttpServletResponse JavaDoc)pageContext.getResponse()).encodeURL(lc_unEncodedUrl));
346                     break;
347                 case SORT_CUSTOM:
348                     // use user custom sort action.
349
if (! sortAction.toLowerCase().startsWith("javascript:")) {
350                         // No js code : go to the server to sort.
351
lc_tempBuffer.append(sortAction);
352                         if (sortAction.indexOf("?")!=-1) lc_tempBuffer.append("&"); else lc_tempBuffer.append("?");
353                         lc_tempBuffer.append(sortParam);
354                         lc_tempBuffer.append("=");
355                         lc_tempBuffer.append(in_sortProperty);
356                     } else {
357                         // Js code : need to put the right parameters at their place.
358
String JavaDoc javascriptSortParamName = "sortParam";
359                         if (sortParam != null && sortParam.trim().length() > 0) {
360                             javascriptSortParamName = sortParam;
361                         }
362                         pageContext.setAttribute(javascriptSortParamName, in_sortProperty);
363                         lc_tempBuffer.append(Expression.evaluate(sortAction, pageContext));
364                         pageContext.removeAttribute(javascriptSortParamName);
365                     }
366                     break;
367                 case SORT_JAVASCRIPT:
368                     // sorting on the client browser with javascript.
369
lc_tempBuffer.append("javascript:arraySort(");
370                     lc_tempBuffer.append(sortParam);
371                     lc_tempBuffer.append(",");
372                     lc_tempBuffer.append(column);
373                     lc_tempBuffer.append(",");
374                     lc_tempBuffer.append(size);
375                     lc_tempBuffer.append(",");
376                     lc_tempBuffer.append(nbOfColumns);
377                     lc_tempBuffer.append(")");
378                     break;
379             }
380             lc_sortUrl = lc_tempBuffer.toString();
381         }
382         return lc_sortUrl;
383     }
384     
385     private MultiLevelHeader currentHeader;
386
387     /**
388      * Print a column title to the buffer.
389      * (multi level header)
390      */

391     protected void renderMultiLevelHeaders(StringBuffer JavaDoc in_buffer, List JavaDoc in_multiLevelHeaders, int in_level) throws JspException JavaDoc {
392         if (in_multiLevelHeaders!=null) {
393             List JavaDoc lc_nestedLevels = null;
394             Iterator JavaDoc lc_it = in_multiLevelHeaders.iterator();
395             IMultiLevelHeaderRenderer lc_panel = (IMultiLevelHeaderRenderer) panel;
396             column = 0;
397             
398             // Did we start a header row ?
399
boolean lc_started = false;
400             
401             while (lc_it.hasNext()) {
402                 MultiLevelHeader lc_header = (MultiLevelHeader) lc_it.next();
403                 List JavaDoc lc_headerChildren = lc_header.getChildHeaders();
404                 int lc_rowSpan = lc_headerChildren!=null ? 1 : in_level+1 - lc_header.getLevel();
405                 
406                 Object JavaDoc[] lc_args = new Object JavaDoc[2];
407                 lc_args[0] = Expression.evaluate(lc_header.getArg0(), pageContext);
408                 lc_args[1] = Expression.evaluate(lc_header.getArg1(), pageContext);
409                 String JavaDoc lc_title = LayoutUtils.getLabel(pageContext, getBundle(), lc_header.getTitle(), lc_args, false);
410                 String JavaDoc lc_sortUrl = computeSortUrl(lc_header.getSortProperty());
411                 String JavaDoc lc_styleClass = lc_header.getStyleClass()==null ? getStyleClass() : lc_header.getStyleClass();
412                 String JavaDoc lc_tooltip = LayoutUtils.getLabel(pageContext, getBundle(), lc_header.getTooltip(), null, false);
413                 currentHeader = lc_header;
414                 
415                 if (lc_title!=null) {
416                     // Title is not null, render it.
417

418                     if (!lc_started) {
419                         // First time we render a title, start a title row.
420
lc_panel.startMultiLevelHeaderRow(in_buffer);
421                         lc_started = true;
422                     }
423                     
424                     // Render the title.
425
lc_panel.renderMultiLevelHeader(in_buffer, lc_title, lc_sortUrl, lc_styleClass, lc_header.getColSpan(), lc_rowSpan, lc_header.getWidth());
426                 }
427                 currentHeader = null;
428                 if (lc_headerChildren!=null) {
429                     if (lc_nestedLevels==null) {
430                         lc_nestedLevels = new ArrayList JavaDoc();
431                     }
432                     lc_nestedLevels.addAll(lc_headerChildren);
433                 }
434                 column++;
435             }
436             if(lc_started) {
437                 lc_panel.endMultiLevelHeaderRow(in_buffer);
438             }
439             renderMultiLevelHeaders(in_buffer, lc_nestedLevels, in_level-1);
440         }
441     }
442     
443     public MultiLevelHeader getCurrentHeader() {
444         return currentHeader;
445     }
446
447 protected void renderItem(StringBuffer JavaDoc buffer, String JavaDoc in_item) throws JspException JavaDoc {
448     
449     String JavaDoc lc_item = in_item;
450
451     // if the line of the table are selectable and this is the first column, add a checkbox or a radio button.
452
if (needSelect && !selectHidden) {
453         StringBuffer JavaDoc lc_tempBuffer = new StringBuffer JavaDoc();
454         if (sortType==SORT_JAVASCRIPT && lc_item.startsWith("<!--")) {
455             // if we are sorting the collection on the client, make sure the resulting item still begin with the comment
456
// which may be used to sort the items.
457
int lc_index = lc_item.indexOf("-->");
458             lc_tempBuffer.append(lc_item.substring(0, lc_index +3));
459             lc_item = lc_item.substring(lc_index+3);
460         }
461         renderSelection(lc_tempBuffer);
462         needSelect = false;
463         lc_tempBuffer.append(lc_item);
464         lc_item = lc_tempBuffer.toString();
465     }
466
467     
468     String JavaDoc[] lc_styleClasses = new String JavaDoc[1 + tempStyles.size()];
469     lc_styleClasses[0] = tempStyleClass!=null ? tempStyleClass : styleClass;
470     for (int i=0; i < tempStyles.size(); i++) {
471         lc_styleClasses[i+1] = (String JavaDoc) tempStyles.get(i);
472     }
473     
474     panel.doPrintItem(buffer, lc_item, lc_styleClasses, sortType==SORT_JAVASCRIPT ? "t" + sortParam + "l" + index + "c" + column : null);
475 }
476
477     protected void renderSelection(StringBuffer JavaDoc lc_tempBuffer) throws JspException JavaDoc {
478         lc_tempBuffer.append("<input type=\"");
479         if ("checkbox".equalsIgnoreCase(selectType)) {
480             lc_tempBuffer.append("checkbox");
481         } else {
482             lc_tempBuffer.append("radio");
483         }
484         lc_tempBuffer.append("\" name=\"");
485         if (selectName!=null) {
486             lc_tempBuffer.append(selectName);
487         } else {
488             lc_tempBuffer.append(selectProperty);
489         }
490         if ("checkbox".equalsIgnoreCase(selectType)) {
491             if (selectId!=null) {
492                 lc_tempBuffer.append("(");
493                 lc_tempBuffer.append(LayoutUtils.getProperty(bean, selectId));
494                 lc_tempBuffer.append(")");
495             } else {
496                 lc_tempBuffer.append("[");
497                 lc_tempBuffer.append(index-1);
498                 lc_tempBuffer.append("]");
499                 if (selectIndex!=null) {
500                     lc_tempBuffer.append(".");
501                     lc_tempBuffer.append(selectIndex);
502                 }
503             }
504         }
505         
506         if (onClick!=null) {
507             lc_tempBuffer.append("\" onclick=\"");
508             lc_tempBuffer.append(onClick);
509         }
510         
511         lc_tempBuffer.append("\" value=\"");
512         Object JavaDoc lc_value = LayoutUtils.getProperty(bean, selectProperty);
513         lc_tempBuffer.append(lc_value);
514         lc_tempBuffer.append("\"");
515         
516         // check if the value is selected.
517
if (isCurrentBeanSelected()) {
518             lc_tempBuffer.append(" checked");
519         }
520     
521         lc_tempBuffer.append(">");
522 }
523
524     protected void renderStart(StringBuffer JavaDoc out_buffer) throws JspException JavaDoc {
525         // Display the title.
526
// we do not use the possibility of the PanelTag to do that.
527
Object JavaDoc[] lc_args = new Object JavaDoc[5];
528         Object JavaDoc lc_arg0 = null;
529         if (arg0Name!=null) {
530             lc_arg0 = LayoutUtils.getBeanFromPageContext(pageContext, arg0Name, null);
531         }
532         lc_args[0] = lc_arg0;
533         panel.doPrintTitle(out_buffer, LayoutUtils.getLabel(pageContext, getBundle(), title, lc_args, false));
534                 
535         panel.doStartPanel(out_buffer, align,width);
536     }
537     
538      
539     /**
540      * Returns true if the bean at the current index is selected. Results only valid
541      * when called once iteration is under way.
542      * @return boolean
543      * @throws JspException
544      * @author LeeFreyberg
545      */

546     public boolean isCurrentBeanSelected() throws JspException JavaDoc{
547         if (selectName!=null) {
548             Object JavaDoc lc_selectedValue = null;
549             if ("checkbox".equalsIgnoreCase(selectType)) {
550                 if (selectId==null) {
551                     lc_selectedValue = LayoutUtils.getBeanFromPageContext(pageContext, Constants.BEAN_KEY, selectName + "[" + (index-1) +"]");
552                 } else {
553                     lc_selectedValue = LayoutUtils.getBeanFromPageContext(pageContext, Constants.BEAN_KEY, selectName + "(" + LayoutUtils.getProperty(bean, selectId) +")");
554                 }
555             } else {
556                 lc_selectedValue = LayoutUtils.getBeanFromPageContext(pageContext, Constants.BEAN_KEY, selectName);
557             }
558             if (lc_selectedValue!=null && lc_selectedValue.equals(LayoutUtils.getProperty(bean, selectProperty))) {
559                 return true;
560             }
561         }
562         return false;
563     }
564     public Object JavaDoc processStaticCodeIncludeEvent(StaticCodeIncludeLayoutEvent in_event) throws JspException JavaDoc {
565         String JavaDoc lc_codeToPrint = (String JavaDoc) in_event.sendToParent(this);
566         staticCode += lc_codeToPrint;
567         return "";
568     }
569     protected void renderStaticCode(StringBuffer JavaDoc out_buffer) {
570         if (staticCode.length()>0) {
571             out_buffer.append(staticCode);
572             staticCode = "";
573         }
574     }
575 }
576
Popular Tags