Save This Page
Home » displaytag-1.1.1-src » org » displaytag » decorator » [javadoc | source]
    1   /**
    2    * Licensed under the Artistic License; you may not use this file
    3    * except in compliance with the License.
    4    * You may obtain a copy of the License at
    5    *
    6    *      http://displaytag.sourceforge.net/license.html
    7    *
    8    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
    9    * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   10    * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   11    */
   12   package org.displaytag.decorator;
   13   
   14   import java.text.MessageFormat;
   15   import java.util.HashMap;
   16   import java.util.Iterator;
   17   import java.util.List;
   18   import java.util.Map;
   19   
   20   import javax.servlet.jsp.PageContext;
   21   
   22   import org.apache.commons.lang.ObjectUtils;
   23   import org.apache.commons.lang.StringUtils;
   24   import org.apache.commons.logging.Log;
   25   import org.apache.commons.logging.LogFactory;
   26   import org.displaytag.exception.DecoratorException;
   27   import org.displaytag.model.HeaderCell;
   28   import org.displaytag.model.TableModel;
   29   
   30   
   31   /**
   32    * A table decorator which adds rows with totals (for column with the "total" attribute set) and subtotals (grouping by
   33    * the column with a group="1" attribute).
   34    * @author Fabrizio Giustina
   35    * @version $Id$
   36    */
   37   public class TotalTableDecorator extends TableDecorator
   38   {
   39   
   40       /**
   41        * Logger.
   42        */
   43       private static Log log = LogFactory.getLog(TotalTableDecorator.class);
   44   
   45       /**
   46        * total amount.
   47        */
   48       private Map grandTotals = new HashMap();
   49   
   50       /**
   51        * total amount for current group.
   52        */
   53       private Map subTotals = new HashMap();
   54   
   55       /**
   56        * Previous values needed for grouping.
   57        */
   58       private Map previousValues = new HashMap();
   59   
   60       /**
   61        * Name of the property used for grouping.
   62        */
   63       private String groupPropertyName;
   64   
   65       /**
   66        * Label used for subtotals. Default: "{0} total".
   67        */
   68       private String subtotalLabel = "{0} subtotal";
   69   
   70       /**
   71        * Label used for totals. Default: "Total".
   72        */
   73       private String totalLabel = "Total";
   74   
   75       /**
   76        * Setter for <code>subtotalLabel</code>.
   77        * @param subtotalLabel The subtotalLabel to set.
   78        */
   79       public void setSubtotalLabel(String subtotalLabel)
   80       {
   81           this.subtotalLabel = subtotalLabel;
   82       }
   83   
   84       /**
   85        * Setter for <code>totalLabel</code>.
   86        * @param totalLabel The totalLabel to set.
   87        */
   88       public void setTotalLabel(String totalLabel)
   89       {
   90           this.totalLabel = totalLabel;
   91       }
   92   
   93       /**
   94        * @see org.displaytag.decorator.Decorator#init(PageContext, Object, TableModel)
   95        */
   96       public void init(PageContext context, Object decorated, TableModel tableModel)
   97       {
   98           super.init(context, decorated, tableModel);
   99   
  100           // reset
  101           groupPropertyName = null;
  102           grandTotals.clear();
  103           subTotals.clear();
  104           previousValues.clear();
  105   
  106           for (Iterator it = tableModel.getHeaderCellList().iterator(); it.hasNext();)
  107           {
  108               HeaderCell cell = (HeaderCell) it.next();
  109               if (cell.getGroup() == 1)
  110               {
  111                   groupPropertyName = cell.getBeanPropertyName();
  112               }
  113           }
  114       }
  115   
  116       public String startRow()
  117       {
  118           String subtotalRow = null;
  119   
  120           if (groupPropertyName != null)
  121           {
  122               Object groupedPropertyValue = evaluate(groupPropertyName);
  123               Object previousGroupedPropertyValue = previousValues.get(groupPropertyName);
  124               // subtotals
  125               if (previousGroupedPropertyValue != null
  126                   && !ObjectUtils.equals(previousGroupedPropertyValue, groupedPropertyValue))
  127               {
  128                   subtotalRow = createTotalRow(false);
  129               }
  130               previousValues.put(groupPropertyName, groupedPropertyValue);
  131           }
  132   
  133           for (Iterator it = tableModel.getHeaderCellList().iterator(); it.hasNext();)
  134           {
  135               HeaderCell cell = (HeaderCell) it.next();
  136               if (cell.isTotaled())
  137               {
  138                   String totalPropertyName = cell.getBeanPropertyName();
  139                   Number amount = (Number) evaluate(totalPropertyName);
  140   
  141                   Number previousSubTotal = (Number) subTotals.get(totalPropertyName);
  142                   Number previousGrandTotals = (Number) grandTotals.get(totalPropertyName);
  143   
  144                   subTotals.put(totalPropertyName, new Double((previousSubTotal != null
  145                       ? previousSubTotal.doubleValue()
  146                       : 0)
  147                       + (amount != null ? amount.doubleValue() : 0)));
  148   
  149                   grandTotals.put(totalPropertyName, new Double((previousGrandTotals != null ? previousGrandTotals
  150                       .doubleValue() : 0)
  151                       + (amount != null ? amount.doubleValue() : 0)));
  152               }
  153           }
  154   
  155           return subtotalRow;
  156       }
  157   
  158       /**
  159        * After every row completes we evaluate to see if we should be drawing a new total line and summing the results
  160        * from the previous group.
  161        * @return String
  162        */
  163       public final String finishRow()
  164       {
  165           StringBuffer buffer = new StringBuffer(1000);
  166   
  167           // Grand totals...
  168           if (getViewIndex() == ((List) getDecoratedObject()).size() - 1)
  169           {
  170               if (groupPropertyName != null)
  171               {
  172                   buffer.append(createTotalRow(false));
  173               }
  174               buffer.append(createTotalRow(true));
  175           }
  176           return buffer.toString();
  177   
  178       }
  179   
  180       protected String createTotalRow(boolean grandTotal)
  181       {
  182           StringBuffer buffer = new StringBuffer(1000);
  183           buffer.append("\n<tr class=\"total\">"); //$NON-NLS-1$
  184   
  185           List headerCells = tableModel.getHeaderCellList();
  186   
  187           for (Iterator it = headerCells.iterator(); it.hasNext();)
  188           {
  189               HeaderCell cell = (HeaderCell) it.next();
  190               String cssClass = ObjectUtils.toString(cell.getHtmlAttributes().get("class"));
  191   
  192               buffer.append("<td"); //$NON-NLS-1$
  193               if (StringUtils.isNotEmpty(cssClass))
  194               {
  195                   buffer.append(" class=\""); //$NON-NLS-1$
  196                   buffer.append(cssClass);
  197                   buffer.append("\""); //$NON-NLS-1$
  198               }
  199               buffer.append(">"); //$NON-NLS-1$
  200   
  201               if (cell.isTotaled())
  202               {
  203                   String totalPropertyName = cell.getBeanPropertyName();
  204                   Object total = grandTotal ? grandTotals.get(totalPropertyName) : subTotals.get(totalPropertyName);
  205   
  206                   DisplaytagColumnDecorator[] decorators = cell.getColumnDecorators();
  207                   for (int j = 0; j < decorators.length; j++)
  208                   {
  209                       try
  210                       {
  211                           total = decorators[j].decorate(total, this.getPageContext(), tableModel.getMedia());
  212                       }
  213                       catch (DecoratorException e)
  214                       {
  215                           log.warn(e.getMessage(), e);
  216                           // ignore, use undecorated value for totals
  217                       }
  218                   }
  219                   buffer.append(total);
  220               }
  221               else if (groupPropertyName != null && groupPropertyName.equals(cell.getBeanPropertyName()))
  222               {
  223                   buffer.append(grandTotal ? totalLabel : MessageFormat.format(subtotalLabel, new Object[]{previousValues
  224                       .get(groupPropertyName)}));
  225               }
  226   
  227               buffer.append("</td>"); //$NON-NLS-1$
  228   
  229           }
  230   
  231           buffer.append("</tr>"); //$NON-NLS-1$
  232   
  233           // reset subtotal
  234           this.subTotals.clear();
  235   
  236           return buffer.toString();
  237       }
  238   
  239   }

Save This Page
Home » displaytag-1.1.1-src » org » displaytag » decorator » [javadoc | source]