You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2009/03/19 15:00:54 UTC

svn commit: r756003 - in /incubator/click/trunk/click: documentation/docs/ examples/src/org/apache/click/examples/page/table/ examples/webapp/WEB-INF/ examples/webapp/table/ framework/src/org/apache/click/control/

Author: sabob
Date: Thu Mar 19 14:00:54 2009
New Revision: 756003

URL: http://svn.apache.org/viewvc?rev=756003&view=rev
Log:
Promoted Table getFirstRow and getLastRow to public. New demo added showcasing how to page through a large dataset

Added:
    incubator/click/trunk/click/examples/src/org/apache/click/examples/page/table/LargeDatasetDemo.java
    incubator/click/trunk/click/examples/webapp/table/large-dataset-demo.htm
Modified:
    incubator/click/trunk/click/documentation/docs/roadmap-changes.html
    incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml
    incubator/click/trunk/click/framework/src/org/apache/click/control/Table.java

Modified: incubator/click/trunk/click/documentation/docs/roadmap-changes.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/documentation/docs/roadmap-changes.html?rev=756003&r1=756002&r2=756003&view=diff
==============================================================================
--- incubator/click/trunk/click/documentation/docs/roadmap-changes.html (original)
+++ incubator/click/trunk/click/documentation/docs/roadmap-changes.html Thu Mar 19 14:00:54 2009
@@ -85,6 +85,11 @@
     </div>
     <ul style="padding: 0em; margin-left:0em;margin-bottom: 2em">
       <li>
+        <a target="_blank" class="external" href="http://www.avoka.com/click-examples/table/large-dataset-demo.htm">
+        Large Dataset Demo</a> demonstrates a Table with a large number of rows
+        and how to lazily page through the rows using a custom Table model.
+      </li>
+      <li>
         <a target="_blank" class="external" href="http://www.avoka.com/click-examples/panel/reusable-panel-demo.htm">
           Reusable Panel Demo</a> is an example of a reusable Panel
           which provides a Form for capturing Client details.
@@ -96,6 +101,14 @@
     </div>
     <ul style="padding: 0em; margin-left:0em;margin-bottom: 2em">
       <li class="change">
+          Improved Table to support very large datasets by promoting the methods
+          <a href="click-api/org/apache/click/control/Table.html#getFirstRow()">getFirstRow()</a>
+          and <a href="click-api/org/apache/click/control/Table.html#getLastRow()">getLastRow()</a>
+          as public. These methods provide the necessary information to only
+          retrieve the displayed rows
+          [<a target='_blank' href="https://issues.apache.org/click/browse/CLK-504">504</a>].
+      </li>
+      <li class="change">
           Added ability to specify a custom TreeNode icon through the new method
           TreeNode.<a href="extras-api/org/apache/click/extras/tree/TreeNode.html#setIcon(java.lang.String)">setIcon(String)</a>.
           This issue was raised and fixed by Tim Hooper

Added: incubator/click/trunk/click/examples/src/org/apache/click/examples/page/table/LargeDatasetDemo.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/src/org/apache/click/examples/page/table/LargeDatasetDemo.java?rev=756003&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/src/org/apache/click/examples/page/table/LargeDatasetDemo.java (added)
+++ incubator/click/trunk/click/examples/src/org/apache/click/examples/page/table/LargeDatasetDemo.java Thu Mar 19 14:00:54 2009
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.click.examples.page.table;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.click.control.Column;
+import org.apache.click.control.Table;
+import org.apache.click.examples.page.BorderPage;
+
+/**
+ * Provides a demonstration of a Table with a huge number of rows and how to
+ * lazily page through the rows using a custom List implementation.
+ *
+ * @author Bob Schellink
+ */
+public class LargeDatasetDemo extends BorderPage {
+
+    public Table table;
+
+    public LargeDatasetDemo() {
+        table = new Table();
+
+        // Setup customers table
+        table.setClass(Table.CLASS_ITS);
+
+        Column column = new Column("name");
+        column.setWidth("140px;");
+        table.addColumn(column);
+
+        column = new Column("email");
+        column.setAutolink(true);
+        column.setWidth("230px;");
+        table.addColumn(column);
+
+        column = new Column("age");
+        column.setTextAlign("center");
+        column.setWidth("40px;");
+        table.addColumn(column);
+
+        column = new Column("holdings");
+        column.setFormat("${0,number,#,##0.00}");
+        column.setTextAlign("right");
+        column.setWidth("100px;");
+        table.addColumn(column);
+
+        table.setPageSize(5);
+    }
+
+    /**
+     * @see org.apache.click.Page#onRender()
+     */
+    public void onRender() {
+        // Create TableModel for the specified table and total number of customers
+        TableModel model = new TableModel(table, getCustomerCount());
+
+        // Set the TableModel as the Table row list. Table is now able to
+        // calculate the last row value.
+        // NOTE: If table rowList is not set, table cannot calculate the last row
+        // and invoking #getLastRow will return 0.
+        table.setRowList(model);
+
+        // Retrieve customers given the firstRow, lastRow and pageSize
+        List customers = getCustomers(table.getFirstRow(), table.getLastRow(), table.getPageSize());
+
+        // Add the customers to the table model
+        model.addAll(customers);
+    }
+
+    // ---------------------------------------------------------- Inner Classes
+
+    /**
+     * Provides a custom List implementation which returns a pre-defined size,
+     * even if the underlying amount of entries is less.
+     *
+     * The List also returns correct row for a specified index by offsetting
+     * the index against the Table's firstRow value.
+     */
+    class TableModel extends ArrayList {
+
+        /** The model's Table instance. */
+        private Table table;
+
+        /** The total number of rows of the model. */
+        private int numOfRows;
+
+        /**
+         * Create a new TableModel instance for the given Table and total number
+         * of rows.
+         *
+         * @param table this model's Table instance
+         * @param numOfRows the total number of rows of the model
+         */
+        public TableModel(Table table, int numOfRows) {
+            this.table = table;
+            this.numOfRows = numOfRows;
+        }
+
+        /**
+         * Returns the row at the specified index, offsetted by the current
+         * table first row value.
+         *
+         * @param index the index of the row as viewed in the Table
+         * @return the the row at the specified index, offsetted by the
+         * current table first row value.
+         */
+        public Object get(final int index) {
+            int realIndex = index - table.getFirstRow();
+            return super.get(realIndex);
+        }
+
+        /**
+         * Always return the total number of rows even the number of entries
+         * are less.
+         */
+        public int size() {
+            return numOfRows;
+        }
+    }
+
+    // -------------------------------------------------------- Private Methods
+
+    private int getCustomerCount() {
+        return getCustomerService().getNumberOfCustomers();
+    }
+
+    private List getCustomers(int from, int to, int pageSize) {
+        // Below we retrieve only those customers between the from and to
+        // args. In a real application one would use an ORM or JDBC to only
+        // retrieve the needed rows
+        return getCustomerService().getCustomersForPage(from, pageSize);
+    }
+
+}

Modified: incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml?rev=756003&r1=756002&r2=756003&view=diff
==============================================================================
--- incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml (original)
+++ incubator/click/trunk/click/examples/webapp/WEB-INF/menu.xml Thu Mar 19 14:00:54 2009
@@ -110,6 +110,8 @@
     <menu separator="true"/>
     <menu label="Edit Table Pattern" path="table/edit-table.htm"/>
     <menu label="Search Table Pattern" path="table/search-table.htm"/>
+    <menu separator="true"/>
+    <menu label="Large Dataset Demo" path="table/large-dataset-demo.htm"/>
   </menu>
 
   <menu label=" Tree" path="#" imageSrc="/assets/images/tree.png">

Added: incubator/click/trunk/click/examples/webapp/table/large-dataset-demo.htm
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/examples/webapp/table/large-dataset-demo.htm?rev=756003&view=auto
==============================================================================
--- incubator/click/trunk/click/examples/webapp/table/large-dataset-demo.htm (added)
+++ incubator/click/trunk/click/examples/webapp/table/large-dataset-demo.htm Thu Mar 19 14:00:54 2009
@@ -0,0 +1 @@
+$table
\ No newline at end of file

Modified: incubator/click/trunk/click/framework/src/org/apache/click/control/Table.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/click/framework/src/org/apache/click/control/Table.java?rev=756003&r1=756002&r2=756003&view=diff
==============================================================================
--- incubator/click/trunk/click/framework/src/org/apache/click/control/Table.java (original)
+++ incubator/click/trunk/click/framework/src/org/apache/click/control/Table.java Thu Mar 19 14:00:54 2009
@@ -145,40 +145,50 @@
  * in your applications <tt>click-pages.properties</tt> file. For example:
  *
  * <pre class="codeConfig">
- * table-default-class=blue2
- * </pre>
+ * table-default-class=blue2 </pre>
  *
- * <a name="paging-and-sorting"></a>
- * <h4>Paging and Sorting</h4>
+ * <a name="paging"></a>
+ * <h4>Paging</h4>
  *
- * Table provides out-of-the-box paging and sorting.
+ * Table provides out-of-the-box paging.
  * <p/>
  * To enable Paging set the table's page size: {@link #setPageSize(int)} and
  * make the Table Banner visible: {@link #setShowBanner(boolean)}.
  * <p/>
+ * Table supports rendering different paginators through the method
+ * {@link #setPaginator(org.apache.click.control.Renderable) setPaginator}.
+ * The default Table Paginator is {@link TablePaginator}.
+ *
+ * <a name="sorting"></a>
+ * <h4>Sorting</h4>
+ * Table also has built in column sorting.
+ * <p/>
  * To enable/disable sorting use {@link #setSortable(boolean)}.
+ *
+ * <a name="custom-parameters"></a>
+ * <h4>Custom Parameters - preserve state when paging and sorting</h4>
+ *
+ * Its often necessary to add extra parameters on the Table links in order to
+ * preserve state when navigating between pages or sorting columns.
  * <p/>
- * You can also set parameters on links generated by the Table through
+ * One can easily add extra parameters to links generated by the Table through
  * the Table's {@link #getControlLink() controlLink}.
  * <p/>
- * One often needs to add extra parameters on the Table links in order to
- * preserve state when navigating between pages or sorting columns.
- * <p/>
  * For example:
  *
  * <pre class="prettyprint">
  * public CompanyPage extends BorderPage {
  *
  *      // companyId is the criteria used to limit Table rows to clients from
- *      // the specified company
+ *      // the specified company. This variable could be selected from a drop
+ *      // down list or similar means.
  *      public String companyId;
  *
  *      public Table table = new Table();
  *
  *      public onInit() {
- *          // companyId could be selected from a drop down list or similar means.
  *          // Set the companyId on the table's controlLink. If you view the
- *          // output rendered by Table you will note the companyId parameter
+ *          // output rendered by Table note that the companyId parameter
  *          // is rendered for each Paging and Sorting link.
  *          table.getControlLink().setParameter("companyId", companyId);
  *      }
@@ -192,15 +202,43 @@
  *      }
  * } </pre>
  *
- * Table supports rendering different paginators through the method
- * {@link #setPaginator(org.apache.click.control.Renderable)}. The default Table
- * Paginator is {@link TablePaginator}.
- *
  * <a name="row-attributes"></a>
  * <h4>Row Attributes</h4>
  *
  * Sometimes it is useful to add HTML attributes on individual rows. For these
- * cases one can override the method {@link #addRowAttributes(java.util.Map, java.lang.Object, int)}.
+ * cases one can override the method {@link #addRowAttributes(java.util.Map, java.lang.Object, int)}
+ * and add custom attributes to the row's attribute Map.
+ *
+ * <a name="large-datasets"></a>
+ * <h4>Large Datasets</h4>
+ *
+ * For large datasets Table provides automatic pagination to display a
+ * limited number of rows per page. However the Table's
+ * {@link #setRowList(java.util.List) row list} must still contain all the
+ * dataset entries. With very large datasets (e.g. 100,000 rows), its not
+ * possible to retrieve that many rows from the database.
+ * <p/>
+ * In these cases a custom List implementation can be used as the
+ * Table's {@link #setRowList(java.util.List) row list}. The custom List will
+ * only be populated with the rows that must be displayed for the selected page.
+ * <p/>
+ * The Table methods {@link #getFirstRow()}, {@link #getLastRow()} and
+ * {@link #getPageSize()} provides enough information to calculate which
+ * rows to display for the selected page. Most databases provide the ability
+ * to either limit retrieved rows to a start and end value or a start offset
+ * and max number of rows.
+ * <p/>
+ * A prerequisite is that the <tt>total number of rows</tt> must be retrieved
+ * beforehand, otherwise it won't be possible to calculate the {@link #getLastRow()
+ * last row}.
+ * <p/>
+ * A custom List have two responsibilities: it must override {@link java.util.List#size()
+ * List.size()} to return the <tt>total number of rows</tt> and it must override
+ * {@link java.util.List#get(int) List.get(index)} to ensure the List returns the
+ * correct row for the specified index.
+ * <p/>
+ * Please see the <a href="http://www.avoka.com/click-examples/table/large-dataset-demo.htm">Large Dataset Demo</a>
+ * which provides a custom List implementation as described above.
  * <p/>
  *
  * See also W3C HTML reference
@@ -1070,6 +1108,47 @@
     // --------------------------------------------------------- Public Methods
 
     /**
+     * Return the index of the first row to display. Index starts from 0.
+     * <p/>
+     * <b>Note:</b> {@link #setPageSize(int) page size} must be set for this
+     * method to correctly calculate the first row, otherwise this method will
+     * return 0.
+     *
+     * @return the index of the first row to display
+     */
+    public int getFirstRow() {
+        int firstRow = 0;
+
+        if (getPageSize() > 0) {
+            if (getPageNumber() > 0) {
+                firstRow = getPageSize() * getPageNumber();
+            }
+        }
+
+        return firstRow;
+    }
+
+    /**
+     * Return the index of the last row to diplay. Index starts from 0.
+     * <p/>
+     * <b>Note:</b> the Table {@link #setRowList(java.util.List) row list} and
+     * {@link #setPageSize(int) page size} must be set for this method to
+     * correctly calculate the last row, otherwise this method will return 0.
+     *
+     * @return the index of the last row to display
+     */
+    public int getLastRow() {
+        int numbRows = getRowList().size();
+        int lastRow = numbRows;
+
+        if (getPageSize() > 0) {
+            lastRow = getFirstRow() + getPageSize();
+            lastRow = Math.min(lastRow, numbRows);
+        }
+        return lastRow;
+    }
+
+    /**
      * Deploy the <tt>table.css</tt> and column sorting icon files to the
      * <tt>click</tt> web directory when the application is initialized.
      *
@@ -1278,39 +1357,6 @@
     // ------------------------------------------------------ Protected Methods
 
     /**
-     * Return the index of the first row to display. Index starts from 0.
-     *
-     * @return the index of the first row to display
-     */
-    protected int getFirstRow() {
-        int firstRow = 0;
-
-        if (getPageSize() > 0) {
-            if (getPageNumber() > 0) {
-                firstRow = getPageSize() * getPageNumber();
-            }
-        }
-
-        return firstRow;
-    }
-
-    /**
-     * Return the index of the last row to diplay. Index starts from 0.
-     *
-     * @return the index of the last row to display
-     */
-    protected int getLastRow() {
-        int numbRows = getRowList().size();
-        int lastRow = numbRows;
-
-        if (getPageSize() > 0) {
-            lastRow = getFirstRow() + getPageSize();
-            lastRow = Math.min(lastRow, numbRows);
-        }
-        return lastRow;
-    }
-
-    /**
      * Render the table header row of column names.
      *
      * @param buffer the StringBuffer to render the header row in