head	1.31;
access;
symbols
	TIGRIS_1_1_0RC2:1.22.6.1
	TIGRIS_1_1_0RC1:1.22.6.1
	TIGRIS_1_1:1.22.6.1.0.2
	TIGRIS_1_0_8:1.22.6.1
	TIGRIS_1_0_8RC3:1.22.6.1
	TIGRIS_1_0_8RC2:1.22.6.1
	TIGRIS_1_0_8RC1:1.22.6.1
	TIGRIS_1_0_7:1.22.6.1
	TIGRIS_1_0_7RC3:1.22.6.1
	TIGRIS_1_0_7RC2:1.22.6.1
	TIGRIS_1_0_7RC1:1.22.6.1
	TIGRIS_1_0_6:1.22.6.1
	TIGRIS_1_0_6RC5:1.22.6.1
	TIGRIS_1_0_6RC4:1.22.6.1
	TIGRIS_1_0_6RC3:1.22.6.1
	TIGRIS_1_0_6RC2:1.22.6.1
	TIGRIS_1_0_6RC1:1.22.6.1
	TIGRIS_1_0_5:1.22.6.1
	TIGRIS_1_0_5RC6:1.22.6.1
	TIGRIS_1_0_5RC5:1.22.6.1
	TIGRIS_1_0_5RC4:1.22.6.1
	TIGRIS_1_0_5RC3:1.22.6.1
	TIGRIS_1_0_5RC2:1.22.6.1
	TIGRIS_1_0_5RC1:1.22.6.1
	TIGRIS_1_0_4:1.22.6.1
	TIGRIS_1_0_3:1.22
	TIGRIS_1_0_2:1.22
	TIGRIS_1_0_1:1.22
	TIGRIS_1_0:1.22.0.6
	TIGRIS_1_0_0:1.22
	TIGRIS_1_0_0_RC1:1.22.0.2
	dlr:1.1.1
	TIGRIS_0_9_2_4:1.16
	TIGRIS_0_9_2_3:1.16
	HELM_PEER_PORT_BRANCH:1.1.1.1
	TURBINE_PEER:1.18
	TIGRIS_0_9_2_1:1.18
	TIGRIS_0_9_2:1.16.0.2
	TIGRIS_0_9_0:1.5.0.2;
locks; strict;
comment	@# @;


1.31
date	2001.08.29.18.50.01;	author dlr;	state Exp;
branches;
next	1.30;

1.30
date	2001.08.11.09.08.10;	author dlr;	state Exp;
branches;
next	1.29;

1.29
date	2001.07.19.19.08.44;	author dlr;	state Exp;
branches;
next	1.28;

1.28
date	2001.07.02.22.53.29;	author leonardr;	state Exp;
branches;
next	1.27;

1.27
date	2001.06.12.23.10.43;	author leonardr;	state Exp;
branches;
next	1.26;

1.26
date	2001.05.23.01.50.23;	author dlr;	state Exp;
branches;
next	1.25;

1.25
date	2001.04.20.19.07.17;	author leonardr;	state Exp;
branches;
next	1.24;

1.24
date	2001.04.09.20.38.38;	author dlr;	state Exp;
branches;
next	1.23;

1.23
date	2001.04.09.16.50.50;	author leonardr;	state Exp;
branches;
next	1.22;

1.22
date	2001.02.23.23.09.00;	author leonardr;	state Exp;
branches
	1.22.6.1;
next	1.21;

1.21
date	2001.02.23.23.08.09;	author leonardr;	state Exp;
branches;
next	1.20;

1.20
date	2001.02.22.17.15.53;	author leonardr;	state Exp;
branches;
next	1.19;

1.19
date	2001.02.21.01.08.27;	author dlr;	state Exp;
branches;
next	1.18;

1.18
date	2001.01.26.18.29.11;	author edk;	state Exp;
branches
	1.18.2.1;
next	1.17;

1.17
date	2001.01.26.05.24.08;	author edk;	state dead;
branches;
next	1.16;

1.16
date	2001.01.05.01.47.03;	author leonardr;	state Exp;
branches;
next	1.15;

1.15
date	2001.01.03.22.06.35;	author leonardr;	state Exp;
branches;
next	1.14;

1.14
date	2001.01.02.19.32.36;	author leonardr;	state Exp;
branches;
next	1.13;

1.13
date	2001.01.02.18.30.50;	author leonardr;	state Exp;
branches;
next	1.12;

1.12
date	2001.01.02.17.19.57;	author leonardr;	state Exp;
branches;
next	1.11;

1.11
date	2000.12.30.01.03.32;	author leonardr;	state Exp;
branches;
next	1.10;

1.10
date	2000.12.29.21.05.55;	author leonardr;	state Exp;
branches;
next	1.9;

1.9
date	2000.12.29.17.11.54;	author leonardr;	state Exp;
branches;
next	1.8;

1.8
date	2000.12.28.00.12.44;	author leonardr;	state Exp;
branches;
next	1.7;

1.7
date	2000.12.27.17.38.29;	author leonardr;	state Exp;
branches;
next	1.6;

1.6
date	2000.12.27.17.21.38;	author leonardr;	state Exp;
branches;
next	1.5;

1.5
date	2000.12.20.23.21.13;	author kmaples;	state Exp;
branches;
next	1.4;

1.4
date	2000.12.20.20.14.50;	author leonardr;	state Exp;
branches;
next	1.3;

1.3
date	2000.12.20.19.27.03;	author leonardr;	state Exp;
branches;
next	1.2;

1.2
date	2000.12.20.18.39.56;	author leonardr;	state Exp;
branches;
next	1.1;

1.1
date	2000.12.20.00.25.32;	author leonardr;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2001.02.21.00.35.36;	author dlr;	state Exp;
branches;
next	;

1.18.2.1
date	2001.01.28.01.02.20;	author dlr;	state dead;
branches;
next	1.18.2.2;

1.18.2.2
date	2001.02.07.02.24.51;	author leonardr;	state Exp;
branches;
next	1.18.2.3;

1.18.2.3
date	2001.02.15.20.50.45;	author leonardr;	state Exp;
branches;
next	;

1.22.6.1
date	2001.05.02.15.47.36;	author leonardr;	state Exp;
branches;
next	;


desc
@@


1.31
log
@Clean up.
@
text
@/* ================================================================
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by CollabNet (http://www.collab.net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 * 
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of CollabNet.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals on behalf of CollabNet.
 */

package org.tigris.helm.tool.paginate;

import java.util.*;

import org.apache.turbine.util.Log;
import org.apache.commons.util.exception.NestableException;

import org.tigris.helm.util.URL;

/**
 * An abstract class describing a list which can be paginated.
 *
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
 * @@version $Id: PaginatableList.java,v 1.30 2001/08/11 09:08:10 dlr Exp $
 */
abstract public class PaginatableList extends ArrayList
{   
    protected int itemsPerPage;

    private static final boolean debug = true;

    /**
     * Returns a sublist of this list, the contents determined by
     * the page requested.
     */
    public List getPage(Integer page) 
        throws Exception
    {
        int start = firstItem(page);
        int finish = lastItem(page);
        return subList(start,finish);
    }

    /**
     * Prints out an HTML navigation bar for the given page; 
     */
    public String navigationBar(String linkText, Integer page)
        throws Exception
    {
        if (numberOfPages() <= 1) return "";

        boolean prependDots = false;
        boolean appendDots = false;
        int pageNo = page.intValue();
        int pages = numberOfPages();
        int startPage = pageNo - 5;
        if (startPage <= 0) startPage = 1;
        if (startPage > 1) prependDots = true;
        int endPage = pageNo + 4;
        if (endPage < 10) endPage = 10;
        if (endPage > pages) endPage = pages;
        if (endPage < (pages-1)) appendDots = true;
        
        String extra = appendQueryString();
        if (!extra.equals(""))
        {
            if (linkText.lastIndexOf("?") == -1) 
            {                
                if (extra.lastIndexOf("?") == -1)
                {
                    linkText += "?";
                }
            }
            else 
            { 
                linkText += "&"; 
            }
            linkText += extra;
        }

        StringBuffer bar = new StringBuffer();
        if (startPage != endPage)
        {
            if (pageNo != 1)
            {
                bar.append(makeLink(linkText, pageNo-1, "Prev"));
            } 
            else 
            {
                bar.append("Prev");
            }
            bar.append(" | ");

            if (prependDots) bar.append(" ... | ");

            for (int i = startPage; i <= endPage; i++)
            {
                String linkedText = i + "&nbsp;" + makeGuide(new Integer(i));

                if (i == pageNo)
                {
                    bar.append(linkedText);
                } 
                else 
                {
                    bar.append(makeLink(linkText, i, linkedText));
                }
                if (i < endPage)
                {
                    bar.append (" | ");
                }
            }

            bar.append(" | ");

            if (prependDots) bar.append(" ... | ");

            if (pageNo != endPage)
            {
                bar.append(makeLink(linkText, pageNo+1, "Next"));
            } 
            else 
            {
                bar.append("Next");
            }
        }
        return bar.toString();
    }

    /**
     * Makes a link to the given page.
     */    
    protected String makeLink(String linkText, int pageNo, String linkedText)
    {
        StringBuffer link = new StringBuffer();
        link.append("<a href=\"").append(linkText);
        URL.appendCGISeparator(link, linkText);
        link.append("paginated_page=").append(pageNo).append("\">")
            .append(linkedText).append("</a>");
        return link.toString();
    }

    /**
     * Makes a guide to the given page for use in the navbar. A
     * list of Users, for instance, might print "(A-N)" for a page
     * in which the first entry had a name beginning with A and the
     * last entry had a name beginning with N.
     */
    public String makeGuide(Integer page) 
        throws Exception
    {
        return "";
    }

    /**
     * Generate whatever text is neccessary to mantain this list's
     * state in a link to another page. A list which had had a filter
     * applied to it would need to return fields which would reinstate
     * the filter.
     */
    public String appendQueryString()
    {
        return "";
    }

    /**
     * Returns the number of items in the list.
     */
    public int numberOfItems() 
    {
        return size();
    }

    /**
     * Returns the number of pages the list will occupy.
     */
    public int numberOfPages() 
    {
        int pages;
        if (itemsPerPage == 0)
        {
            pages = 1;
        }
        else
        {
            int entries = numberOfItems();
            pages = entries / itemsPerPage;
            int entriesOnExtraPage = entries % itemsPerPage;
            if (entriesOnExtraPage != 0) pages++;
        }
        return pages;
    }

    /**
     * Returns the maximum number of items that should be on any given
     * page. If the list was created with 0 items per page, that means
     * the first (and only) page should contain the entire list.  
     */
    public int itemsOnPage() 
    {
        int itemsOnPage;
        if (itemsPerPage == 0)
        {
            itemsOnPage = numberOfItems();
        } else {            
            itemsOnPage = itemsPerPage;
        }
        return itemsOnPage;
    }

    /**
     * Returns the index of the first item on the given page.
     */
    public int firstItem(Integer pageNo)
    {
        int itemsOnThisPage = itemsOnPage();
        
        int start = ((pageNo.intValue()-1) * itemsOnThisPage);
        if (start >= numberOfItems())
        {
            start = 0;
        }
        return start;
    }

    /**
     * Returns the index of the last item on the given page.
     */
    public int lastItem(Integer pageNo)
    {
        int finish = firstItem(pageNo) + itemsOnPage();
        if (finish >= numberOfItems())
        {
            finish = numberOfItems();
        }
        return finish;
    }

}
@


1.30
log
@Upgrading to Turbine 3.0-dev, Fulcrum 1.0, and Torque 1.0.
@
text
@d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.29 2001/07/19 19:08:44 dlr Exp $
d219 2
a220 1
        } else 
@


1.29
log
@Updated to use Helm URL class (just ported from Joist).
@
text
@d52 1
a52 1
import org.apache.turbine.util.TurbineException;
d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.28 2001/07/02 22:53:29 leonardr Exp $
@


1.28
log
@Don't allow line breaks between the number and the page guide.
@
text
@d54 1
a54 1
import org.joist.util.URL;
d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.27 2001/06/12 23:10:43 leonardr Exp $
@


1.27
log
@PeerBackedList performance boost and refactoring. This may be more complicated than it needs to be; rather than getting ever-increasing proportions of the table, it might be faster in most cases to get the whole table, so long as you stop processing results when the list is full enough.
@
text
@d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.26 2001/05/23 01:50:23 dlr Exp $
d109 3
a111 1
            } else { 
d123 3
a125 1
            } else {
d134 1
a134 1
                String linkedText = i + " " + makeGuide(new Integer(i));
d139 3
a141 1
                } else {
d157 3
a159 1
            } else {
@


1.26
log
@Ported Helm from WebMacro to Velocity.
@
text
@d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.25 2001/04/20 19:07:17 leonardr Exp $
d73 1
d84 1
d178 1
d211 2
a212 1
        } else {
@


1.25
log
@Removed unneccessary debugging.
@
text
@d52 1
d60 1
a60 1
 * @@version $Id: PaginatableList.java,v 1.24 2001/04/09 20:38:38 dlr Exp $
@


1.24
log
@Refactored makeLink() to leverage Joist method.
@
text
@d59 1
a59 1
 * @@version $Id: PaginatableList.java,v 1.23 2001/04/09 16:50:50 leonardr Exp $
a82 1
        Log.debug("Initial linkText: " + linkText);
@


1.23
log
@Pagination on filtered data should work now.
@
text
@d53 2
d59 1
a59 1
 * @@version $Id: PaginatableList.java,v 1.22 2001/02/23 23:09:00 leonardr Exp $
d163 3
a165 8
        if (linkText.lastIndexOf("?") == -1) 
        {
            link.append("?");
        } else { 
            link.append("&"); 
        }
        link.append("paginated_page=").append(pageNo).append("\">").append(linkedText);
        link.append("</a>");
@


1.22
log
@The = makes the difference.
@
text
@d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.21 2001/02/23 23:08:09 leonardr Exp $
d81 1
d100 5
a104 2
            {
                linkText += "?";
@


1.22.6.1
log
@Backporting fixes for pagination of filtered data.
@
text
@a52 2
import org.joist.util.URL;

d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.25 2001/04/20 19:07:17 leonardr Exp $
d99 2
a100 5
            {                
                if (extra.lastIndexOf("?") == -1)
                {
                    linkText += "?";
                }
d157 8
a164 3
        URL.appendCGISeparator(link, linkText);
        link.append("paginated_page=").append(pageNo).append("\">")
            .append(linkedText).append("</a>");
@


1.21
log
@Handle better the case where itemsPerPage=0.
@
text
@d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.20 2001/02/22 17:15:53 leonardr Exp $
d204 1
a204 1
        if (itemsPerPage = 0)
@


1.20
log
@Don't print a navigation bar if there are fewer than two pages.
@
text
@d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.19 2001/02/21 01:08:27 dlr Exp $
d203 10
a212 4
        int entries = numberOfItems();
        int pages = entries / itemsPerPage;
        int entriesOnExtraPage = entries % itemsPerPage;
        if (entriesOnExtraPage != 0) pages++;
d223 2
a224 2
        int itemsOnPage = itemsPerPage;
        if (itemsOnPage == 0)
d227 2
@


1.19
log
@This is the highest revision from the HELM_PEER_PORT_BRANCH.  The previous import caused too many conflicts to resolve manually
@
text
@d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.18.2.3 2001/02/15 20:50:45 leonardr Exp $
d81 2
@


1.18
log
@readding all the files as part of the process of returning to the way
things were as of tuesday
@
text
@d2 1
a2 1
 * Copyright (c) 2000 CollabNet.  All rights reserved.
a49 1
import java.sql.*;
d51 1
a51 8
import gnu.regexp.*;

import org.webmacro.util.Log;
import org.webmacro.servlet.WebContext;

import com.workingdogs.village.*;

import org.joist.database.*;
d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.16 2001/01/05 01:47:03 leonardr Exp $
a62 1
    private static Log log = new Log("PList", "PaginatableList");
a69 1
        throws DataSetException, SQLException
a79 1
        throws DataSetException, SQLException
d172 1
a172 1
    public String makeGuide(Integer page) throws DataSetException, SQLException
d191 1
a191 1
    public int numberOfItems() throws DataSetException, SQLException
d199 1
a199 2
    public int numberOfPages()
        throws DataSetException, SQLException
d209 3
a211 3
     * Returns the maximum number of items that should be on any
     * given page. If the list was created with 0 items per page,
     * display the whole list.
d213 1
a213 2
    public int itemsOnPage()
        throws DataSetException, SQLException
a226 1
        throws DataSetException, SQLException
a241 1
        throws DataSetException, SQLException
@


1.18.2.1
log
@Porting to the Turbine Peer system.  -dlr and leonardr
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.18 2001/01/26 18:29:11 edk Exp $
@


1.18.2.2
log
@Ported pagination scheme to new helm. Simple filter still won't work.
@
text
@d50 1
d52 8
a59 1
import org.apache.turbine.util.Log;
d71 1
d79 1
d90 1
d183 1
a183 1
    public String makeGuide(Integer page) 
d202 1
a202 1
    public int numberOfItems() 
d210 2
a211 1
    public int numberOfPages() 
d221 3
a223 3
     * Returns the maximum number of items that should be on any given
     * page. If the list was created with 0 items per page, that means
     * the first (and only) page should contain the entire list.  
d225 2
a226 1
    public int itemsOnPage() 
d240 1
d256 1
@


1.18.2.3
log
@Normalized copyright dates.
@
text
@d2 1
a2 1
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
d57 1
a57 1
 * @@version $Id: PaginatableList.java,v 1.18.2.2 2001/02/07 02:24:51 leonardr Exp $
@


1.17
log
@revert this stuff to its state as of 2001/01/24 12:42:00 GMT -- with
the following exceptions, which have some different modifications so
they'll work with changes which have happened in joist:

ProjectNewsEdit.java
SkinManager.java
SkinStyleElementValueManager.java
StyleElementManager.java
StyleManager.java

it compiles.  i dunno if it works, though.
@
text
@@


1.16
log
@Added elipses for pages in which the full navigation bar is not displayed.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.15 2001/01/03 22:06:35 leonardr Exp $
@


1.15
log
@Added Javadoc and rearranged methods.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.14 2001/01/02 19:32:36 leonardr Exp $
d92 2
d98 1
d102 1
d127 2
d146 3
@


1.14
log
@Show 'Prev' and 'Next' even if they aren't links
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.13 2001/01/02 18:30:50 leonardr Exp $
d75 2
a76 1
     * Returns a sublist of this list.
a86 58
     * Makes a guide to the given page for use in the navbar.
     */
    public String makeGuide(Integer page) throws DataSetException, SQLException
    {
        return "";
    }

    /**
     * Generate whatever text is neccessary to mantain this list's
     * state in a link to another page.
     */
    public String appendQueryString()
    {
        return "";
    }

    public int itemsOnPage()
        throws DataSetException, SQLException
    {
        int itemsOnPage = itemsPerPage;
        if (itemsOnPage == 0)
        {
            itemsOnPage = numberOfItems();
        }
        return itemsOnPage;
    }

    /**
     * Returns the index of the first item on the given page.
     */
    public int firstItem(Integer pageNo)
        throws DataSetException, SQLException
    {
        int itemsOnThisPage = itemsOnPage();
        
        int start = ((pageNo.intValue()-1) * itemsOnThisPage);
        if (start >= numberOfItems())
        {
            start = 0;
        }
        return start;
    }

    /**
     * Returns the index of the last item on the given page.
     */
    public int lastItem(Integer pageNo)
        throws DataSetException, SQLException
    {
        int finish = firstItem(pageNo) + itemsOnPage();
        if (finish >= numberOfItems())
        {
            finish = numberOfItems();
        }
        return finish;
    }

    /**
d149 4
a152 1
    
d168 25
d198 3
a200 1

d209 46
@


1.13
log
@First use of PaginatablePrebuiltList
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.12 2001/01/02 17:19:57 leonardr Exp $
d174 3
a176 1
                bar.append(makeLink(linkText, pageNo-1, "Prev")).append(" | ");
d178 1
d196 1
d199 3
a201 1
                bar.append(" | ").append(makeLink(linkText, pageNo+1, "Next"));
@


1.12
log
@Split PaginatableList into subclasses PaginatableDatabaseBackedList and PaginatablePrebuiltList. If you want to do simple pagination without messing with the database, use PaginatablePrebuiltList. Note that your list will not be filterable.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.11 2000/12/30 01:03:32 leonardr Exp $
d97 4
a100 1
    public abstract String appendQueryString();
d216 4
a219 1
    public abstract int numberOfItems() throws DataSetException, SQLException;
@


1.11
log
@More pagination changes--allow paginated lists to filter out items already in a group.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.10 2000/12/29 21:05:55 leonardr Exp $
a68 3
    protected Connection connection;
    protected DataManager dMgr;

a69 8
    protected String baseQuery;
    protected Criterion searchCriterion;
    protected String orderBy;
    protected List matchingRecords;

    protected boolean dirty;

    public static final Map filterableFields = new HashMap();
a73 15
    public Map getFilterableFields()
    {
        return filterableFields;
    }

    public Iterator iterator()
    {
        return matchingRecords.iterator();
    }

    public int size()
    {
        return matchingRecords.size();
    }

d75 1
a75 1
     * A basic constructor.
d77 2
a78 3
    public PaginatableList(Connection connection, DataManager dMgr,
                           Integer itemsPerPage, String baseQuery,
                           Criterion criterion, String orderBy)
d80 3
a82 20
        this.connection = connection;
        this.dMgr = dMgr;
        this.itemsPerPage = itemsPerPage.intValue();
        this.baseQuery = baseQuery;
        this.searchCriterion = criterion;
        this.orderBy = orderBy;
        this.matchingRecords = new ArrayList();
        dirty = true;
    }
    
    public String toString()
    {
        StringBuffer d = new StringBuffer();
        d.append("\nPaginatableList subclass with query \"")
            .append(baseQuery).append("\", criterion \"")
            .append(searchCriterion.toString())
            .append("\", order clause \"").append(orderBy)
            .append("\", currently holding ").append(matchingRecords.size())
            .append(" entries.\n");
        return d.toString();
d86 1
a86 3
     * Changes the extra criteria used to filter records, and marks
     * the record list as dirty so that the next page request will hit
     * the database.  
d88 1
a88 1
    public void changeCriterion(Criterion c)
d90 1
a90 2
        this.searchCriterion = c;
        dirty = true;
d94 2
a95 2
     * Returns the field, if any, which should be used to display alphabetic
     * guides in the navbar.
d97 1
a97 4
    public String alphabetizedByField()
    {
        return null;
    }
d99 1
a99 5
    /**
     * Retrieves records from the database if neccessary, and turns
     * the requested record range into business objects.
     */
    public List getPage(Integer page)
d102 6
a107 2
        List objects = objectifyRecords(getPageRecords(page));
        return objects;
d111 1
a111 2
     * Retrieves records from the database if neccessary, and returns a
     * List of the records corresponding to the requested page.
d113 1
a113 1
    public List getPageRecords(Integer page)
d116 4
a119 3
        List records = null;
        int pageNo = page.intValue();
        if (dirty == true)
d121 1
a121 7
            retrieveRecords();
        }

        int itemsOnThisPage = itemsPerPage;
        if (itemsOnThisPage == 0)
        {
            itemsOnThisPage = matchingRecords.size();
d123 2
a125 19
        if (matchingRecords.isEmpty())
        {
            records = new ArrayList();
        } else {
            int start = ((pageNo-1) * itemsOnThisPage);
            if (start >= matchingRecords.size())
            {
                start = 0;
            }
            int finish = start + itemsPerPage;
            if (finish >= matchingRecords.size())
            {
                finish = matchingRecords.size();
            }
            records = matchingRecords.subList(start, finish);
        }
        return records;
    }
    
d127 1
a127 1
     * Makes a guide to the given page for use in the navbar.
d129 1
a129 1
    public String makeGuide(Integer page)
d132 2
a133 8
        String guideField = alphabetizedByField();
        if (guideField == null) return "";
        List records = getPageRecords(page);
        StringBuffer guide = new StringBuffer("(");
        String firstVal = guideLetter((Record)records.get(0));
        String lastVal = guideLetter((Record)records.get(records.size()-1));
        guide.append(firstVal);
        if (!firstVal.equals(lastVal))
d135 1
a135 1
            guide.append("-").append(lastVal);
d137 1
a137 11
        guide.append(")");
        return guide.toString();
    }

    /**
     * Gets the first letter of the appropriate field.
     */
    private String guideLetter(Record r)
        throws DataSetException, SQLException
    {
        return r.getValue(alphabetizedByField()).asString().substring(0,1).toUpperCase();
d154 2
a155 2
        String appendQueryString = searchCriterion.toQueryString();
        if (!appendQueryString.equals(""))
d161 1
a161 1
                linkText += ("&"); 
d163 1
a163 1
            linkText += "FILTER+CHECK=TRUE" + "&" + appendQueryString;
d213 1
a213 11
    /**
     * retrieveRecords should set dirty to false and turn the
     * baseQuery and criterion into a List of Record objects,
     * doing whatever additional filtering is needed.
     */
    public void retrieveRecords()
        throws DataSetException, SQLException
    {
        matchingRecords = runQuery();
        dirty = false;
    }
a214 9
    public int numberOfEntries()
        throws DataSetException, SQLException
    {
        if (dirty)
        {
            retrieveRecords();
        }
        return matchingRecords.size();
    }
d219 1
a219 1
        int entries = numberOfEntries();
a225 46
    protected List runQuery()
        throws DataSetException, SQLException
    {
        StringBuffer statement = new StringBuffer();
        /*
         * TODO: This could break in the unlikely situation that
         * "WHERE" appears in a table name or something. Make it more
         * robust.  
         */
        String connector = "WHERE";                
        int index = baseQuery.toLowerCase().indexOf("where");
        if(index != -1)
        {
            connector = "AND";
        }
        
        statement.append(baseQuery);       
        if (searchCriterion.toString() != "")
        {
            statement.append(" ").append(connector).append(" ");
            statement.append(searchCriterion.toString());        
        }

        if (orderBy != null && !(orderBy.equals("")))
        {
            statement.append(" ORDER BY ").append(orderBy);
        }

        QueryDataSet qds = new QueryDataSet(connection, statement.toString());
        dMgr.registerToClose(qds);
        qds.fetchRecords();

        List records = new ArrayList();
        for (int i = 0; i < qds.size(); i++)
        {
            records.add(qds.getRecord(i));            
        }
        return records;
    }

    /**
     * This method takes a list of Records and turns the records of
     * the list into the appropriate type of business object.
     */
    protected abstract List objectifyRecords(List records) 
        throws DataSetException;
@


1.10
log
@Pagination and filtration are now miscible.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.9 2000/12/29 17:11:54 leonardr Exp $
d90 10
d307 1
a307 1
    protected void retrieveRecords()
@


1.9
log
@Many, many pagination changes.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.8 2000/12/28 00:12:44 leonardr Exp $
d232 12
@


1.8
log
@PaginatableLists can now request alphabetic guides on their navbars. Project lists which are sorted by project name currently make use of this.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.7 2000/12/27 17:38:29 leonardr Exp $
d164 6
d174 1
a174 1
            int start = ((pageNo-1) * itemsPerPage);
d196 1
a196 1
        if (guideField == null) return null;
d227 1
a227 1
        int startPage = pageNo - 10;
d229 2
a230 1
        int endPage = pageNo + 10;
d238 1
a238 1
                bar.append(makeLink(linkText, pageNo-1, "Prev"));
a242 1
                bar.append (" | ");
d251 4
a254 5
            }

            if (startPage < endPage)
            {
                bar.append(" | ");
d259 1
a259 1
                bar.append(makeLink(linkText, pageNo+1, "Next"));
@


1.7
log
@Don't print bar if there's only one page.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.6 2000/12/27 17:21:38 leonardr Exp $
d131 9
d146 12
a158 1
        List objects = null;
d166 1
a166 1
            objects = new ArrayList();
d178 21
a198 2
            List records = matchingRecords.subList(start, finish);
            objects = objectifyRecords(records);
d200 11
a210 1
        return objects;
d237 2
d241 1
a241 1
                    bar.append(i + " ");
d243 1
a243 1
                    bar.append(makeLink(linkText, i, ""+i));
@


1.6
log
@Added capability to specify an ORDER clause in pagination query.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.5 2000/12/20 23:21:13 kmaples Exp $
d178 1
a178 1
        if (pageNo != 1)
d180 4
a183 2
            bar.append(makeLink(linkText, pageNo-1, "Prev"));
        }
d185 1
a185 4
        for (int i = startPage; i <= endPage; i++)
        {
            bar.append (" | ");
            if (i == pageNo)
d187 7
a193 3
                bar.append(i + " ");
            } else {
                bar.append(makeLink(linkText, i, ""+i));
a194 1
        }
d196 4
a199 4
        if (startPage < endPage)
        {
            bar.append(" | ");
        }
d201 4
a204 3
        if (pageNo != endPage)
        {
            bar.append(makeLink(linkText, pageNo+1, "Next"));
@


1.5
log
@Changed key 'page' to 'paginated_page' to avoid name clash w/ a noodle key named 'page'
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.4 2000/12/20 20:14:50 leonardr Exp $
d75 1
d95 1
a95 1
                           Criterion criterion)
d102 1
d111 1
a111 1
            .append(baseQuery).append("\" and criterion \"")
d113 1
d275 6
@


1.4
log
@Added prev/next links and corrected off-by-one error.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.3 2000/12/20 19:27:03 leonardr Exp $
d213 1
a213 1
        link.append("page=").append(pageNo).append("\">").append(linkedText);
@


1.3
log
@The new pagination regime marches on. All hail PaginatableList!
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.2 2000/12/20 18:39:56 leonardr Exp $
d175 6
a180 1
        for (int i = startPage; i < endPage; i++)
d187 1
a187 9
                bar.append("<a href=\"").append(linkText);
                if (linkText.lastIndexOf("?") == -1) 
                {
                    bar.append("?");
                } else { 
                    bar.append("&"); 
                }
                bar.append("page=").append(i).append("\">").append(i);
                bar.append("</a>");
d190 1
d195 5
d203 15
@


1.2
log
@First tenative steps towards the new pagination/filtering regime.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.1 2000/12/20 00:25:32 leonardr Exp $
d177 1
d180 1
a180 1
                bar.append (" " + i + " ");
d182 1
a182 1
                bar.append(" | ").append("<a href=\"").append(linkText);
@


1.1
log
@The dawning of the new pagination regime.
@
text
@d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.1 2000/12/14 03:10:00 leonardr Exp $
d79 2
d84 5
d93 1
a93 1
                           int itemsPerPage, String baseQuery,
d98 1
a98 1
        this.itemsPerPage = itemsPerPage;
d101 2
d105 11
d131 1
a131 1
    public List getPage(int pageNo)
d134 2
d140 19
a158 5
        
        int start = (pageNo * (itemsPerPage-1)) + 1;
        int finish = start + itemsPerPage - 1;
        List records = matchingRecords.subList(start, finish);
        return objectifyRecords(records);
d164 1
a164 1
    public String navigationBar(String linkText, int pageNo)
d167 1
d170 1
a170 1
        if (startPage < 0) startPage = 0;
d192 4
a195 1
        bar.append(" | ");
a234 1
        String SQL_RE = "WHERE";
d240 3
a242 4
        String connector = "WHERE";
        
        RE sqlRE = null;
        try
d244 1
a244 5
            sqlRE= new RE(SQL_RE, RE.REG_ICASE);
            if(sqlRE.isMatch(baseQuery))
            {
                connector = "AND";
            }
d246 3
a248 1
        catch (REException e)
d250 2
a251 1
            log.exception(e);
a252 4

        statement.append(baseQuery);       
        statement.append(" ").append(connector).append(" ");
        statement.append(searchCriterion.toString());        
@


1.1.1.1
log
@Replacing the HEAD with the HELM_PEER_PORT_BRANCH.
@
text
@d2 1
a2 1
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
d50 1
d52 8
a59 1
import org.apache.turbine.util.Log;
d65 1
a65 1
 * @@version $Id: PaginatableList.java,v 1.18.2.3 2001/02/15 20:50:45 leonardr Exp $
d69 3
d73 5
d79 1
d83 27
a109 2
     * Returns a sublist of this list, the contents determined by
     * the page requested.
d111 2
a112 1
    public List getPage(Integer page) 
d114 9
a122 3
        int start = firstItem(page);
        int finish = lastItem(page);
        return subList(start,finish);
d128 2
a129 1
    public String navigationBar(String linkText, Integer page)
a130 3
        boolean prependDots = false;
        boolean appendDots = false;
        int pageNo = page.intValue();
d132 3
a134 5
        int startPage = pageNo - 5;
        if (startPage <= 0) startPage = 1;
        if (startPage > 1) prependDots = true;
        int endPage = pageNo + 4;
        if (endPage < 10) endPage = 10;
a135 13
        if (endPage < (pages-1)) appendDots = true;
        
        String extra = appendQueryString();
        if (!extra.equals(""))
        {
            if (linkText.lastIndexOf("?") == -1) 
            {
                linkText += "?";
            } else { 
                linkText += "&"; 
            }
            linkText += extra;
        }
d138 1
a138 1
        if (startPage != endPage)
d140 1
a140 1
            if (pageNo != 1)
d142 1
a142 1
                bar.append(makeLink(linkText, pageNo-1, "Prev"));
d144 2
a145 11
                bar.append("Prev");
            }
            bar.append(" | ");

            if (prependDots) bar.append(" ... | ");

            for (int i = startPage; i <= endPage; i++)
            {
                String linkedText = i + " " + makeGuide(new Integer(i));

                if (i == pageNo)
d147 3
a149 7
                    bar.append(linkedText);
                } else {
                    bar.append(makeLink(linkText, i, linkedText));
                }
                if (i < endPage)
                {
                    bar.append (" | ");
d151 2
a152 11
            }

            bar.append(" | ");

            if (prependDots) bar.append(" ... | ");

            if (pageNo != endPage)
            {
                bar.append(makeLink(linkText, pageNo+1, "Next"));
            } else {
                bar.append("Next");
d155 1
d158 1
a158 1

d160 3
a162 22
     * Makes a link to the given page.
     */    
    protected String makeLink(String linkText, int pageNo, String linkedText)
    {
        StringBuffer link = new StringBuffer();
        link.append("<a href=\"").append(linkText);
        if (linkText.lastIndexOf("?") == -1) 
        {
            link.append("?");
        } else { 
            link.append("&"); 
        }
        link.append("paginated_page=").append(pageNo).append("\">").append(linkedText);
        link.append("</a>");
        return link.toString();
    }

    /**
     * Makes a guide to the given page for use in the navbar. A
     * list of Users, for instance, might print "(A-N)" for a page
     * in which the first entry had a name beginning with A and the
     * last entry had a name beginning with N.
d164 2
a165 1
    public String makeGuide(Integer page) 
d167 2
a168 1
        return "";
d171 2
a172 7
    /**
     * Generate whatever text is neccessary to mantain this list's
     * state in a link to another page. A list which had had a filter
     * applied to it would need to return fields which would reinstate
     * the filter.
     */
    public String appendQueryString()
d174 5
a178 1
        return "";
d181 2
a182 4
    /**
     * Returns the number of items in the list.
     */
    public int numberOfItems() 
d184 1
a184 9
        return size();
    }

    /**
     * Returns the number of pages the list will occupy.
     */
    public int numberOfPages() 
    {
        int entries = numberOfItems();
d191 2
a192 6
    /**
     * Returns the maximum number of items that should be on any given
     * page. If the list was created with 0 items per page, that means
     * the first (and only) page should contain the entire list.  
     */
    public int itemsOnPage() 
d194 11
a204 2
        int itemsOnPage = itemsPerPage;
        if (itemsOnPage == 0)
d206 5
a210 1
            itemsOnPage = numberOfItems();
d212 11
a222 2
        return itemsOnPage;
    }
d224 2
a225 9
    /**
     * Returns the index of the first item on the given page.
     */
    public int firstItem(Integer pageNo)
    {
        int itemsOnThisPage = itemsOnPage();
        
        int start = ((pageNo.intValue()-1) * itemsOnThisPage);
        if (start >= numberOfItems())
d227 1
a227 1
            start = 0;
d229 1
a229 1
        return start;
d233 2
a234 1
     * Returns the index of the last item on the given page.
d236 2
a237 10
    public int lastItem(Integer pageNo)
    {
        int finish = firstItem(pageNo) + itemsOnPage();
        if (finish >= numberOfItems())
        {
            finish = numberOfItems();
        }
        return finish;
    }

@


