You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by Matthew Van Horn <ma...@yahoo.com> on 2004/08/08 09:49:29 UTC

AbstractPagerTool

> this does bring up an interesting point. not everyone who wants paging
> support will want it to be search oriented.  if no one beats me to it (which
> should be easy with how busy i am lately), i'll look into separating the
> paging support out into a separate tool.
> 
> Nathan Bubna
> nathan@esha.com
> 
> 
I needed this, so I've pulled out the critera/query/search stuff from
the AbstractSearchTool, and turned it into an AbstractPagerTool.
It works the same, you just need to do something like:

$pager.setResults(myList)

to give it a List to page through.

I know some people have asked about this, but I don't know the procedure
for submitting this to the project, as I've never really done it before,
and I'd want someone else to look it over, in case I screwed something
up.

What should I do?

-- 
Matthew Van Horn <ma...@yahoo.com>


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Nathan Bubna <na...@esha.com>.
Fernando said:
> Good idea... That's exactly what I need in my project.
> Just one thing that appears in my mind when I saw this code, is that,
> if we have this AbstractPagerTool class, maybe AbstractSearchTool
> could be subclass of it.

that was my thought all along.  in fact, i started working on this last night.
i'll see if i can find some time to finish it up soon and check these changes
in.

> Or we could have a PagerTool class with pager abstraction and
> AbstractPagerTool and AbstractSearchTool subclass of it.
>
> I don't know if it's applicable or a good sugestion....  but it's just
> something that I have in mind when I saw it. sorry if I'm wrong.

not at all.  it's good thinking.

Nathan Bubna
nathan@esha.com

> Fernando
>
>
>
> On Tue, 10 Aug 2004 07:17:39 +0900, Matthew Van Horn
> <ma...@yahoo.com> wrote:
> > On Tue, 2004-08-10 at 01:14, Nathan Bubna wrote:
> > > Matthew Van Horn said:
> > > > It works the same, you just need to do something like:
> > > >
> > > > $pager.setResults(myList)
> > > >
> > > > to give it a List to page through.
> > >
> > > so why is it abstract?
> >
> > Because I kept most of the AbstractSearchTool code, including an
> > abstract setup method where you could parse page size/index parameters,
> > etc. Without that, it could be made concrete. init() would have to
> > change too, so as not to call setup()
> >
> > I personally like keeping the parameter stuff centralized in the setup
> > method (rather than on the templates), but I leave it to the project
> > leaders to decide whether that should be enforced by making it abstract-
> > it is literally a 30 second/2 line change.
> >
> > > post it to the list.  say that you want to contribute it to the project.
then
> > > people (myself included) can look it over and post any feedback they
have on
> > > it.  then at some point i'll find some time to give it a quick test or
two,
> > > and if i like it, i'll commit it to CVS (unless, of course, one of the
other
> > > committers beats me to it).
> > >
> > > Nathan Bubna
> > > nathan@esha.com
> >
> > OK, here it is - I want to contribute it to the project (although my
> > contribution is mostly subtractive):
> >
> > package org.apache.velocity.tools.view.tools;
> >
> > import java.util.ArrayList;
> > import java.util.Collections;
> > import java.util.List;
> >
> > import javax.servlet.http.HttpServletRequest;
> > import javax.servlet.http.HttpSession;
> >
> > import org.apache.velocity.tools.view.context.ViewContext;
> > import org.apache.velocity.tools.view.tools.ViewTool;
> >
> > public abstract class AbstractPagerTool implements ViewTool{
> >     /** the default number of results shown per page */
> >     public static final int DEFAULT_ITEMS_PER_PAGE = 10;
> >
> >     /** the default max number of result page indices to list */
> >     public static final int DEFAULT_SLIP_SIZE = 20;
> >
> >     /** the key under which StoredResults are kept in session */
> >     protected static final String STORED_RESULTS_KEY =
> >         AbstractPagerTool.class.getName();
> >
> >     private List results;
> >     private int index = 0;
> >     private int slipSize = DEFAULT_SLIP_SIZE;
> >     private int itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
> >     protected HttpSession session;
> >
> >     /**
> >      * Initializes this instance by grabbing the request
> >      * and session objects from the current ViewContext.
> >      *
> >      * @param obj the current ViewContext
> >      * @throws ClassCastException if the param is not a ViewContext
> >      */
> >     public void init(Object obj)
> >     {
> >         ViewContext context = (ViewContext)obj;
> >         HttpServletRequest request = context.getRequest();
> >         session = request.getSession(false);
> >         setup(request);
> >     }
> >
> >     /**
> >      * Abstract method to make it as obvious as possible just
> >      * where implementing classes should be retrieving and configuring
> >      * display parameters.
> >      * <p>A simple implementation would be:
> >      * <pre>
> >      * public void setup(HttpServletRequest req)
> >      * {
> >      *     ParameterParser pp = new ParameterParser(req);
> >      *     setIndex(pp.getInt("index", 0));
> >      *     setItemsPerPage(pp.getInt("show", DEFAULT_ITEMS_PER_PAGE));
> >      * }
> >      * </pre>
> >      *
> >      * @param request the current HttpServletRequest
> >      */
> >     public abstract void setup(HttpServletRequest request);
> >
> >     /*  ---------------------- mutators -----------------------------
> > */
> >
> >     /**
> >      * Sets the criteria and results to null, page index to zero, and
> >      * items per page to the default.
> >      */
> >     public void reset()
> >     {
> >         results = null;
> >         index = 0;
> >         itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
> >     }
> >
> >     /**
> >      * Sets the List to page through.
> >      *
> >      * @param results - the  {@link List} of results to be paged through
> >      */
> >     public void setResults(List results)
> >     {
> >         this.results = results;
> >         setStoredResults(results);
> >     }
> >
> >     /**
> >      * Sets the index of the first result in the current page
> >      *
> >      * @param index the result index to start the current page with
> >      */
> >     public void setIndex(int index)
> >     {
> >         if (index < 0)
> >         {
> >             /* quietly override to a reasonable value */
> >             index = 0;
> >         }
> >         this.index = index;
> >     }
> >
> >     /**
> >      * Sets the number of items returned in a page of results
> >      *
> >      * @param itemsPerPage the number of items to be returned per page
> >      */
> >     public void setItemsPerPage(int itemsPerPage)
> >     {
> >         if (itemsPerPage < 1)
> >         {
> >             /* quietly override to a reasonable value */
> >             itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
> >         }
> >         this.itemsPerPage = itemsPerPage;
> >     }
> >
> >     /**
> >      * Sets the number of result page indices for {@link #getSlip} to
> > list.
> >      * (for google-ish result page links).
> >      *
> >      * @see #getSlip
> >      * @param slipSize - the number of result page indices to list
> >      */
> >     public void setSlipSize(int slipSize)
> >     {
> >         if (slipSize < 2)
> >         {
> >             /* quietly override to a reasonable value */
> >             slipSize = DEFAULT_SLIP_SIZE;
> >         }
> >         this.slipSize = slipSize;
> >     }
> >
> >     /*  ---------------------- accessors -----------------------------
> > */
> >
> >     /**
> >      * Return the set number of items to be displayed per page of
> > results
> >      *
> >      * @return current number of results shown per page
> >      */
> >     public int getItemsPerPage()
> >     {
> >         return itemsPerPage;
> >     }
> >
> >     /**
> >      * Returns the number of result page indices {@link #getSlip}
> >      * will return per request (if available).
> >      *
> >      * @return the number of result page indices {@link #getSlip}
> >      *         will try to return
> >      */
> >     public int getSlipSize()
> >     {
> >         return slipSize;
> >     }
> >
> >     /**
> >      * Return the current search result index.
> >      *
> >      * @return the index for the beginning of the current page
> >      */
> >     public int getIndex()
> >     {
> >         return index;
> >     }
> >
> >     /**
> >      * Checks whether or not the result list is empty.
> >      *
> >      * @return <code>true</code> if the result list is not empty.
> >      */
> >     public boolean hasResults()
> >     {
> >         return !getResults().isEmpty();
> >     }
> >
> >     /**
> >      * Return the results for the given criteria.  This is guaranteed
> >      * to never return <code>null</code>.
> >      *
> >      * @return {@link List} of all results for the criteria
> >      */
> >     public List getResults()
> >     {
> >         if (results == null)
> >         {
> >             results = getStoredResults();
> >         }
> >
> >         return (results != null) ? results : Collections.EMPTY_LIST;
> >     }
> >
> >     /**
> >      * Return the index for the next page of results
> >      * (as determined by the current index, items per page, and
> >      * the number of results).  If no "next page" exists, then null is
> >      * returned.
> >      *
> >      * @return index for the next page or <code>null</code> if none
> > exists
> >      */
> >     public Integer getNextIndex()
> >     {
> >         int next = index + itemsPerPage;
> >         if (next < getResults().size())
> >         {
> >             return new Integer(next);
> >         }
> >         return null;
> >     }
> >
> >     /**
> >      * Return the index for the previous page of results
> >      * (as determined by the current index, items per page, and
> >      * the number of results).  If no "next page" exists, then null is
> >      * returned.
> >      *
> >      * @return index for the previous page or <code>null</code> if none
> > exists
> >      */
> >     public Integer getPrevIndex()
> >     {
> >         int prev = Math.min(index, getResults().size()) - itemsPerPage;
> >         if (index > 0)
> >         {
> >             return new Integer(Math.max(0, prev));
> >         }
> >         return null;
> >     }
> >
> >     /**
> >      * Return the number of pages that can be made from this list
> >      * given the set number of items per page.
> >      */
> >     public int getPagesAvailable()
> >     {
> >         return (int)Math.ceil(getResults().size() /
> > (double)itemsPerPage);
> >     }
> >
> >     /**
> >      * Return the current "page" of search results.
> >      *
> >      * @return a {@link List} of results for the "current page"
> >      */
> >     public List getPage()
> >     {
> >         /* return null if we have no results */
> >         if (!hasResults())
> >         {
> >             return null;
> >         }
> >         /* quietly keep the page indices to legal values for robustness'
> > sake */
> >         int start = Math.min(getResults().size() - 1, index);
> >         int end = Math.min(getResults().size(), index + itemsPerPage);
> >         return getResults().subList(start, end);
> >     }
> >
> >     /**
> >      * Returns the "page number" for the specified index.  Because the
> > page
> >      * number is used for the user interface, the page numbers are
> > 1-based.
> >      *
> >      * @param i the index that you want the page number for
> >      * @return the approximate "page number" for the specified index or
> >      *         <code>null</code> if there are no results
> >      */
> >     public Integer getPageNumber(int i)
> >     {
> >         if (!hasResults())
> >         {
> >             return null;
> >         }
> >         return new Integer(1 + i / itemsPerPage);
> >     }
> >
> >     /**
> >      * Returns the "page number" for the current index.  Because the
> > page
> >      * number is used for the user interface, the page numbers are
> > 1-based.
> >      *
> >      * @return the approximate "page number" for the current index or
> >      *         <code>null</code> if there are no results
> >      */
> >     public Integer getPageNumber()
> >     {
> >         return getPageNumber(index);
> >     }
> >
> >     /**
> >      * <p>Returns a description of the current page.  This
> > implementation
> >      * displays a 1-based range of result indices and the total number
> >      * of results.  (e.g. "1 - 10 of 42" or "7 of 7")</p>
> >      *
> >      * <p>Sub-classes may override this to provide a customized
> >      * description (such as one in another language).</p>
> >      *
> >      * @return a description of the current page
> >      */
> >     public String getPageDescription()
> >     {
> >         StringBuffer out = new StringBuffer();
> >         int first = index + 1;
> >         int total = getResults().size();
> >         if (first >= total)
> >         {
> >             out.append(total);
> >             out.append(" of ");
> >             out.append(total);
> >         }
> >         else
> >         {
> >             int last = Math.min(index + itemsPerPage, total);
> >             out.append(first);
> >             out.append(" - ");
> >             out.append(last);
> >             out.append(" of ");
> >             out.append(total);
> >         }
> >         return out.toString();
> >     }
> >
> >     /**
> >      * Return a <b>S</b>liding <b>L</b>ist of <b>I</b>ndices for
> > <b>P</b>ages
> >      * of search results.
> >      *
> >      * <p>Essentially, this returns a list of result indices that
> > correspond
> >      * to available pages of search results (as based on the set
> >      * items-per-page). This makes it relativly easy to do a google-ish
> > set
> >      * of links to result pages.</p>
> >      *
> >      * <p>Note that this list of Integers is 0-based to correspond with
> > the
> >      * underlying result indices and not the displayed page numbers (see
> >      * {@link #getPageNumber}).</p>
> >      *
> >      * @return {@link List} of Integers representing the indices of
> > result
> >      *         pages or empty list if there's one or less pages
> > available
> >      */
> >     public List getSlip()
> >     {
> >         /* return an empty list if there's no pages to list */
> >         int totalPgs = getPagesAvailable();
> >         if (totalPgs <= 1)
> >         {
> >             return Collections.EMPTY_LIST;
> >         }
> >
> >         /* page number is 1-based so decrement it */
> >         int curPg = getPageNumber().intValue() - 1;
> >
> >         /* don't include current page in slip size calcs */
> >         int adjSlipSize = slipSize - 1;
> >
> >         /* start at zero or just under half of max slip size
> >          * this keeps "forward" and "back" pages about even
> >          * but gives preference to "forward" pages */
> >         int slipStart = Math.max(0, (curPg - (adjSlipSize / 2)));
> >
> >         /* push slip end as far as possible */
> >         int slipEnd = Math.min(totalPgs, (slipStart + adjSlipSize));
> >
> >         /* if we're out of "forward" pages, then push the
> >          * slip start toward zero to maintain slip size */
> >         if (slipEnd - slipStart < adjSlipSize)
> >         {
> >             slipStart = Math.max(0, slipEnd - adjSlipSize);
> >         }
> >
> >         /* convert 0-based page numbers to indices and create list */
> >         List slip = new ArrayList((slipEnd - slipStart) + 1);
> >         for (int i=slipStart; i < slipEnd; i++)
> >         {
> >             slip.add(new Integer(i * itemsPerPage));
> >         }
> >         return slip;
> >     }
> >
> >     /*  ---------------------- private methods
> > -----------------------------  */
> >
> >     /**
> >      * Retrieves stored search results (if any) from the user's
> >      * session attributes.
> >      *
> >      * @return the {@link StoredResults} retrieved from memory
> >      */
> >     protected List getStoredResults()
> >     {
> >         if (session != null)
> >         {
> >             return (List)session.getAttribute(STORED_RESULTS_KEY);
> >         }
> >         return null;
> >     }
> >
> >     /**
> >      * Stores current search results in the user's session attributes
> >      * (if one currently exists) in order to do efficient result
> > pagination.
> >      *
> >      * <p>Override this to store search results somewhere besides the
> >      * HttpSession or to prevent storage of results across requests. In
> >      * the former situation, you must also override
> > getStoredResults().</p>
> >      *
> >      * @param results the {@link StoredResults} to be stored
> >      */
> >     protected void setStoredResults(List results)
> >     {
> >         if (session != null)
> >         {
> >             session.setAttribute(STORED_RESULTS_KEY, results);
> >
> >
> >         }
> >     }
> >
> > }
> >
> > --
> > Matthew Van Horn <ma...@yahoo.com>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: velocity-user-help@jakarta.apache.org
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: velocity-user-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Fernando <fg...@gmail.com>.
Good idea... That's exactly what I need in my project.
Just one thing that appears in my mind when I saw this code, is that,
if we have this AbstractPagerTool class, maybe AbstractSearchTool
could be subclass of it.
Or we could have a PagerTool class with pager abstraction and
AbstractPagerTool and AbstractSearchTool subclass of it.

I don't know if it's applicable or a good sugestion....  but it's just
something that I have in mind when I saw it. sorry if I'm wrong.

Fernando



On Tue, 10 Aug 2004 07:17:39 +0900, Matthew Van Horn
<ma...@yahoo.com> wrote:
> On Tue, 2004-08-10 at 01:14, Nathan Bubna wrote:
> > Matthew Van Horn said:
> > > It works the same, you just need to do something like:
> > >
> > > $pager.setResults(myList)
> > >
> > > to give it a List to page through.
> >
> > so why is it abstract?
> 
> Because I kept most of the AbstractSearchTool code, including an
> abstract setup method where you could parse page size/index parameters,
> etc. Without that, it could be made concrete. init() would have to
> change too, so as not to call setup()
> 
> I personally like keeping the parameter stuff centralized in the setup
> method (rather than on the templates), but I leave it to the project
> leaders to decide whether that should be enforced by making it abstract-
> it is literally a 30 second/2 line change.
> 
> > post it to the list.  say that you want to contribute it to the project.  then
> > people (myself included) can look it over and post any feedback they have on
> > it.  then at some point i'll find some time to give it a quick test or two,
> > and if i like it, i'll commit it to CVS (unless, of course, one of the other
> > committers beats me to it).
> >
> > Nathan Bubna
> > nathan@esha.com
> 
> OK, here it is - I want to contribute it to the project (although my
> contribution is mostly subtractive):
> 
> package org.apache.velocity.tools.view.tools;
> 
> import java.util.ArrayList;
> import java.util.Collections;
> import java.util.List;
> 
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpSession;
> 
> import org.apache.velocity.tools.view.context.ViewContext;
> import org.apache.velocity.tools.view.tools.ViewTool;
> 
> public abstract class AbstractPagerTool implements ViewTool{
>     /** the default number of results shown per page */
>     public static final int DEFAULT_ITEMS_PER_PAGE = 10;
> 
>     /** the default max number of result page indices to list */
>     public static final int DEFAULT_SLIP_SIZE = 20;
> 
>     /** the key under which StoredResults are kept in session */
>     protected static final String STORED_RESULTS_KEY =
>         AbstractPagerTool.class.getName();
> 
>     private List results;
>     private int index = 0;
>     private int slipSize = DEFAULT_SLIP_SIZE;
>     private int itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
>     protected HttpSession session;
> 
>     /**
>      * Initializes this instance by grabbing the request
>      * and session objects from the current ViewContext.
>      *
>      * @param obj the current ViewContext
>      * @throws ClassCastException if the param is not a ViewContext
>      */
>     public void init(Object obj)
>     {
>         ViewContext context = (ViewContext)obj;
>         HttpServletRequest request = context.getRequest();
>         session = request.getSession(false);
>         setup(request);
>     }
> 
>     /**
>      * Abstract method to make it as obvious as possible just
>      * where implementing classes should be retrieving and configuring
>      * display parameters.
>      * <p>A simple implementation would be:
>      * <pre>
>      * public void setup(HttpServletRequest req)
>      * {
>      *     ParameterParser pp = new ParameterParser(req);
>      *     setIndex(pp.getInt("index", 0));
>      *     setItemsPerPage(pp.getInt("show", DEFAULT_ITEMS_PER_PAGE));
>      * }
>      * </pre>
>      *
>      * @param request the current HttpServletRequest
>      */
>     public abstract void setup(HttpServletRequest request);
> 
>     /*  ---------------------- mutators -----------------------------
> */
> 
>     /**
>      * Sets the criteria and results to null, page index to zero, and
>      * items per page to the default.
>      */
>     public void reset()
>     {
>         results = null;
>         index = 0;
>         itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
>     }
> 
>     /**
>      * Sets the List to page through.
>      *
>      * @param results - the  {@link List} of results to be paged through
>      */
>     public void setResults(List results)
>     {
>         this.results = results;
>         setStoredResults(results);
>     }
> 
>     /**
>      * Sets the index of the first result in the current page
>      *
>      * @param index the result index to start the current page with
>      */
>     public void setIndex(int index)
>     {
>         if (index < 0)
>         {
>             /* quietly override to a reasonable value */
>             index = 0;
>         }
>         this.index = index;
>     }
> 
>     /**
>      * Sets the number of items returned in a page of results
>      *
>      * @param itemsPerPage the number of items to be returned per page
>      */
>     public void setItemsPerPage(int itemsPerPage)
>     {
>         if (itemsPerPage < 1)
>         {
>             /* quietly override to a reasonable value */
>             itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
>         }
>         this.itemsPerPage = itemsPerPage;
>     }
> 
>     /**
>      * Sets the number of result page indices for {@link #getSlip} to
> list.
>      * (for google-ish result page links).
>      *
>      * @see #getSlip
>      * @param slipSize - the number of result page indices to list
>      */
>     public void setSlipSize(int slipSize)
>     {
>         if (slipSize < 2)
>         {
>             /* quietly override to a reasonable value */
>             slipSize = DEFAULT_SLIP_SIZE;
>         }
>         this.slipSize = slipSize;
>     }
> 
>     /*  ---------------------- accessors -----------------------------
> */
> 
>     /**
>      * Return the set number of items to be displayed per page of
> results
>      *
>      * @return current number of results shown per page
>      */
>     public int getItemsPerPage()
>     {
>         return itemsPerPage;
>     }
> 
>     /**
>      * Returns the number of result page indices {@link #getSlip}
>      * will return per request (if available).
>      *
>      * @return the number of result page indices {@link #getSlip}
>      *         will try to return
>      */
>     public int getSlipSize()
>     {
>         return slipSize;
>     }
> 
>     /**
>      * Return the current search result index.
>      *
>      * @return the index for the beginning of the current page
>      */
>     public int getIndex()
>     {
>         return index;
>     }
> 
>     /**
>      * Checks whether or not the result list is empty.
>      *
>      * @return <code>true</code> if the result list is not empty.
>      */
>     public boolean hasResults()
>     {
>         return !getResults().isEmpty();
>     }
> 
>     /**
>      * Return the results for the given criteria.  This is guaranteed
>      * to never return <code>null</code>.
>      *
>      * @return {@link List} of all results for the criteria
>      */
>     public List getResults()
>     {
>         if (results == null)
>         {
>             results = getStoredResults();
>         }
> 
>         return (results != null) ? results : Collections.EMPTY_LIST;
>     }
> 
>     /**
>      * Return the index for the next page of results
>      * (as determined by the current index, items per page, and
>      * the number of results).  If no "next page" exists, then null is
>      * returned.
>      *
>      * @return index for the next page or <code>null</code> if none
> exists
>      */
>     public Integer getNextIndex()
>     {
>         int next = index + itemsPerPage;
>         if (next < getResults().size())
>         {
>             return new Integer(next);
>         }
>         return null;
>     }
> 
>     /**
>      * Return the index for the previous page of results
>      * (as determined by the current index, items per page, and
>      * the number of results).  If no "next page" exists, then null is
>      * returned.
>      *
>      * @return index for the previous page or <code>null</code> if none
> exists
>      */
>     public Integer getPrevIndex()
>     {
>         int prev = Math.min(index, getResults().size()) - itemsPerPage;
>         if (index > 0)
>         {
>             return new Integer(Math.max(0, prev));
>         }
>         return null;
>     }
> 
>     /**
>      * Return the number of pages that can be made from this list
>      * given the set number of items per page.
>      */
>     public int getPagesAvailable()
>     {
>         return (int)Math.ceil(getResults().size() /
> (double)itemsPerPage);
>     }
> 
>     /**
>      * Return the current "page" of search results.
>      *
>      * @return a {@link List} of results for the "current page"
>      */
>     public List getPage()
>     {
>         /* return null if we have no results */
>         if (!hasResults())
>         {
>             return null;
>         }
>         /* quietly keep the page indices to legal values for robustness'
> sake */
>         int start = Math.min(getResults().size() - 1, index);
>         int end = Math.min(getResults().size(), index + itemsPerPage);
>         return getResults().subList(start, end);
>     }
> 
>     /**
>      * Returns the "page number" for the specified index.  Because the
> page
>      * number is used for the user interface, the page numbers are
> 1-based.
>      *
>      * @param i the index that you want the page number for
>      * @return the approximate "page number" for the specified index or
>      *         <code>null</code> if there are no results
>      */
>     public Integer getPageNumber(int i)
>     {
>         if (!hasResults())
>         {
>             return null;
>         }
>         return new Integer(1 + i / itemsPerPage);
>     }
> 
>     /**
>      * Returns the "page number" for the current index.  Because the
> page
>      * number is used for the user interface, the page numbers are
> 1-based.
>      *
>      * @return the approximate "page number" for the current index or
>      *         <code>null</code> if there are no results
>      */
>     public Integer getPageNumber()
>     {
>         return getPageNumber(index);
>     }
> 
>     /**
>      * <p>Returns a description of the current page.  This
> implementation
>      * displays a 1-based range of result indices and the total number
>      * of results.  (e.g. "1 - 10 of 42" or "7 of 7")</p>
>      *
>      * <p>Sub-classes may override this to provide a customized
>      * description (such as one in another language).</p>
>      *
>      * @return a description of the current page
>      */
>     public String getPageDescription()
>     {
>         StringBuffer out = new StringBuffer();
>         int first = index + 1;
>         int total = getResults().size();
>         if (first >= total)
>         {
>             out.append(total);
>             out.append(" of ");
>             out.append(total);
>         }
>         else
>         {
>             int last = Math.min(index + itemsPerPage, total);
>             out.append(first);
>             out.append(" - ");
>             out.append(last);
>             out.append(" of ");
>             out.append(total);
>         }
>         return out.toString();
>     }
> 
>     /**
>      * Return a <b>S</b>liding <b>L</b>ist of <b>I</b>ndices for
> <b>P</b>ages
>      * of search results.
>      *
>      * <p>Essentially, this returns a list of result indices that
> correspond
>      * to available pages of search results (as based on the set
>      * items-per-page). This makes it relativly easy to do a google-ish
> set
>      * of links to result pages.</p>
>      *
>      * <p>Note that this list of Integers is 0-based to correspond with
> the
>      * underlying result indices and not the displayed page numbers (see
>      * {@link #getPageNumber}).</p>
>      *
>      * @return {@link List} of Integers representing the indices of
> result
>      *         pages or empty list if there's one or less pages
> available
>      */
>     public List getSlip()
>     {
>         /* return an empty list if there's no pages to list */
>         int totalPgs = getPagesAvailable();
>         if (totalPgs <= 1)
>         {
>             return Collections.EMPTY_LIST;
>         }
> 
>         /* page number is 1-based so decrement it */
>         int curPg = getPageNumber().intValue() - 1;
> 
>         /* don't include current page in slip size calcs */
>         int adjSlipSize = slipSize - 1;
> 
>         /* start at zero or just under half of max slip size
>          * this keeps "forward" and "back" pages about even
>          * but gives preference to "forward" pages */
>         int slipStart = Math.max(0, (curPg - (adjSlipSize / 2)));
> 
>         /* push slip end as far as possible */
>         int slipEnd = Math.min(totalPgs, (slipStart + adjSlipSize));
> 
>         /* if we're out of "forward" pages, then push the
>          * slip start toward zero to maintain slip size */
>         if (slipEnd - slipStart < adjSlipSize)
>         {
>             slipStart = Math.max(0, slipEnd - adjSlipSize);
>         }
> 
>         /* convert 0-based page numbers to indices and create list */
>         List slip = new ArrayList((slipEnd - slipStart) + 1);
>         for (int i=slipStart; i < slipEnd; i++)
>         {
>             slip.add(new Integer(i * itemsPerPage));
>         }
>         return slip;
>     }
> 
>     /*  ---------------------- private methods
> -----------------------------  */
> 
>     /**
>      * Retrieves stored search results (if any) from the user's
>      * session attributes.
>      *
>      * @return the {@link StoredResults} retrieved from memory
>      */
>     protected List getStoredResults()
>     {
>         if (session != null)
>         {
>             return (List)session.getAttribute(STORED_RESULTS_KEY);
>         }
>         return null;
>     }
> 
>     /**
>      * Stores current search results in the user's session attributes
>      * (if one currently exists) in order to do efficient result
> pagination.
>      *
>      * <p>Override this to store search results somewhere besides the
>      * HttpSession or to prevent storage of results across requests. In
>      * the former situation, you must also override
> getStoredResults().</p>
>      *
>      * @param results the {@link StoredResults} to be stored
>      */
>     protected void setStoredResults(List results)
>     {
>         if (session != null)
>         {
>             session.setAttribute(STORED_RESULTS_KEY, results);
> 
> 
>         }
>     }
> 
> }
> 
> --
> Matthew Van Horn <ma...@yahoo.com>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: velocity-user-help@jakarta.apache.org
> 
>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Nathan Bubna <na...@esha.com>.
Matthew Van Horn said:
> On Tue, 2004-08-10 at 23:50, Nathan Bubna wrote:
> > Matthew Van Horn said:
...
> > the tool looks pretty good.  the only real change i made while playing
with it
> > last night (and make AbstractSearchTool a subclass) was to change the
> > terminology (and method/variable naming) from "results" to plain "items",
> > because "results" implies a query to me and the pager tool doesn't do
that.
> > what do you think about that?
>
> Sounds good to me. I didn't like 'results' either, but I was just too
> tired to think of something else. 'Items' is good. *smacks forehead*

:)

> Now, I've got another itch to scratch with the link tool. Maybe there is
> alread a good way of doing this, but I haven't seen it yet. (Did I
> mention I'm tired...:)
>
> When I am using paging, I end up with two parameters in the query
> string. However, other stuff on the page requires some parameters as
> well. So I have a URL like:
>
> http://mysite.com/mypage.do?pagesize=10&index=20&sortby=name&sortdir=desc
>
> If I copy the whole querystring, and the do addQueryData('index', 30)
> I will get:
>
http://mysite.com/mypage.do?pagesize=10&index=20&sortby=name&sortdir=desc&index=30
> which is wrong, since there are 2 index params.
>
> I am thinking there should be a
> updateQueryData(String name, String value) which would add the
> name/value but if it already existed, it would overwrite the old value.

sounds useful, but it would probably be better named
setQueryData(String,Object).

> Right now, I am using too much logic in my template to do this.
> (checking the name of each param in a loop, before calling addQueryData)
> It is not as maintainable as I'd like.
>
> What do you think of this idea? The way the QueryPairs are stored, I
> probably have to do the same loop w/ conditional over the ArrayList, but
> at least template designers don't have to hard code the parameter names
> to check for.

it's a good idea.  wanna contribute a patch? (preferrably as diff -u)

Nathan Bubna
nathan@esha.com


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Matthew Van Horn <ma...@yahoo.com>.
On Tue, 2004-08-10 at 23:50, Nathan Bubna wrote:
> Matthew Van Horn said:

> still counts in my book.  :)
> 
> the tool looks pretty good.  the only real change i made while playing with it
> last night (and make AbstractSearchTool a subclass) was to change the
> terminology (and method/variable naming) from "results" to plain "items",
> because "results" implies a query to me and the pager tool doesn't do that.
> what do you think about that?

Sounds good to me. I didn't like 'results' either, but I was just too
tired to think of something else. 'Items' is good. *smacks forehead*

Now, I've got another itch to scratch with the link tool. Maybe there is
alread a good way of doing this, but I haven't seen it yet. (Did I
mention I'm tired...:) 

When I am using paging, I end up with two parameters in the query
string. However, other stuff on the page requires some parameters as
well. So I have a URL like:

http://mysite.com/mypage.do?pagesize=10&index=20&sortby=name&sortdir=desc

If I copy the whole querystring, and the do addQueryData('index', 30)
I will get:
http://mysite.com/mypage.do?pagesize=10&index=20&sortby=name&sortdir=desc&index=30
which is wrong, since there are 2 index params.

I am thinking there should be a 
updateQueryData(String name, String value) which would add the
name/value but if it already existed, it would overwrite the old value.
Right now, I am using too much logic in my template to do this.
(checking the name of each param in a loop, before calling addQueryData)
It is not as maintainable as I'd like.

What do you think of this idea? The way the QueryPairs are stored, I
probably have to do the same loop w/ conditional over the ArrayList, but
at least template designers don't have to hard code the parameter names
to check for.

-- 
Matthew Van Horn <ma...@yahoo.com>


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Nathan Bubna <na...@esha.com>.
Matthew Van Horn said:
> On Tue, 2004-08-10 at 01:14, Nathan Bubna wrote:
> > Matthew Van Horn said:
> > > It works the same, you just need to do something like:
> > >
> > > $pager.setResults(myList)
> > >
> > > to give it a List to page through.
> >
> > so why is it abstract?
>
> Because I kept most of the AbstractSearchTool code, including an
> abstract setup method where you could parse page size/index parameters,
> etc. Without that, it could be made concrete. init() would have to
> change too, so as not to call setup()

makes sense.

> I personally like keeping the parameter stuff centralized in the setup
> method (rather than on the templates), but I leave it to the project
> leaders to decide whether that should be enforced by making it abstract-
> it is literally a 30 second/2 line change.
>
> > post it to the list.  say that you want to contribute it to the project.
then
> > people (myself included) can look it over and post any feedback they have
on
> > it.  then at some point i'll find some time to give it a quick test or
two,
> > and if i like it, i'll commit it to CVS (unless, of course, one of the
other
> > committers beats me to it).
...
> OK, here it is - I want to contribute it to the project (although my
> contribution is mostly subtractive):
...

still counts in my book.  :)

the tool looks pretty good.  the only real change i made while playing with it
last night (and make AbstractSearchTool a subclass) was to change the
terminology (and method/variable naming) from "results" to plain "items",
because "results" implies a query to me and the pager tool doesn't do that.
what do you think about that?

Nathan Bubna
nathan@esha.com


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Matthew Van Horn <ma...@yahoo.com>.
On Tue, 2004-08-10 at 01:14, Nathan Bubna wrote:
> Matthew Van Horn said:
> > It works the same, you just need to do something like:
> >
> > $pager.setResults(myList)
> >
> > to give it a List to page through.
> 
> so why is it abstract?

Because I kept most of the AbstractSearchTool code, including an
abstract setup method where you could parse page size/index parameters,
etc. Without that, it could be made concrete. init() would have to
change too, so as not to call setup() 

I personally like keeping the parameter stuff centralized in the setup
method (rather than on the templates), but I leave it to the project
leaders to decide whether that should be enforced by making it abstract-
it is literally a 30 second/2 line change.

> post it to the list.  say that you want to contribute it to the project.  then
> people (myself included) can look it over and post any feedback they have on
> it.  then at some point i'll find some time to give it a quick test or two,
> and if i like it, i'll commit it to CVS (unless, of course, one of the other
> committers beats me to it).
> 
> Nathan Bubna
> nathan@esha.com

OK, here it is - I want to contribute it to the project (although my
contribution is mostly subtractive):

package org.apache.velocity.tools.view.tools;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.velocity.tools.view.context.ViewContext;
import org.apache.velocity.tools.view.tools.ViewTool;

public abstract class AbstractPagerTool implements ViewTool{
    /** the default number of results shown per page */
    public static final int DEFAULT_ITEMS_PER_PAGE = 10;

    /** the default max number of result page indices to list */
    public static final int DEFAULT_SLIP_SIZE = 20;

    /** the key under which StoredResults are kept in session */
    protected static final String STORED_RESULTS_KEY = 
        AbstractPagerTool.class.getName();
    
    private List results;
    private int index = 0;
    private int slipSize = DEFAULT_SLIP_SIZE;
    private int itemsPerPage = DEFAULT_ITEMS_PER_PAGE;    
    protected HttpSession session;
    
    /**
     * Initializes this instance by grabbing the request
     * and session objects from the current ViewContext.
     *
     * @param obj the current ViewContext
     * @throws ClassCastException if the param is not a ViewContext
     */
    public void init(Object obj)
    {
        ViewContext context = (ViewContext)obj;
        HttpServletRequest request = context.getRequest();
        session = request.getSession(false);
        setup(request);        
    }
    
    /**
     * Abstract method to make it as obvious as possible just
     * where implementing classes should be retrieving and configuring
     * display parameters. 
     * <p>A simple implementation would be:
     * <pre>
     * public void setup(HttpServletRequest req)
     * {
     *     ParameterParser pp = new ParameterParser(req);
     *     setIndex(pp.getInt("index", 0));
     *     setItemsPerPage(pp.getInt("show", DEFAULT_ITEMS_PER_PAGE));
     * }
     * </pre>
     *
     * @param request the current HttpServletRequest
     */
    public abstract void setup(HttpServletRequest request);
    
    /*  ---------------------- mutators ----------------------------- 
*/


    /**
     * Sets the criteria and results to null, page index to zero, and
     * items per page to the default.
     */
    public void reset()
    {
        results = null;
        index = 0;
        itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
    }
    
    /**
     * Sets the List to page through.
     *
     * @param results - the  {@link List} of results to be paged through
     */
    public void setResults(List results)
    {
        this.results = results;
        setStoredResults(results);
    }    
    
    /**
     * Sets the index of the first result in the current page
     *
     * @param index the result index to start the current page with
     */
    public void setIndex(int index)
    {
        if (index < 0)
        {
            /* quietly override to a reasonable value */
            index = 0;
        }
        this.index = index;
    }    
    
    /**
     * Sets the number of items returned in a page of results
     *
     * @param itemsPerPage the number of items to be returned per page
     */
    public void setItemsPerPage(int itemsPerPage)
    {
        if (itemsPerPage < 1)
        {
            /* quietly override to a reasonable value */
            itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
        }
        this.itemsPerPage = itemsPerPage;
    }
    
    /**
     * Sets the number of result page indices for {@link #getSlip} to
list.
     * (for google-ish result page links).
     *
     * @see #getSlip
     * @param slipSize - the number of result page indices to list
     */
    public void setSlipSize(int slipSize)
    {
        if (slipSize < 2)
        {
            /* quietly override to a reasonable value */
            slipSize = DEFAULT_SLIP_SIZE;
        }
        this.slipSize = slipSize;
    }
    
    /*  ---------------------- accessors ----------------------------- 
*/

    /**
     * Return the set number of items to be displayed per page of
results
     *
     * @return current number of results shown per page
     */
    public int getItemsPerPage()
    {
        return itemsPerPage;
    }

    /**
     * Returns the number of result page indices {@link #getSlip} 
     * will return per request (if available).
     *
     * @return the number of result page indices {@link #getSlip} 
     *         will try to return
     */
    public int getSlipSize()
    {
        return slipSize;
    }


    /**
     * Return the current search result index.
     *
     * @return the index for the beginning of the current page
     */
    public int getIndex()
    {
        return index;
    }


    /**
     * Checks whether or not the result list is empty.
     *
     * @return <code>true</code> if the result list is not empty.
     */
    public boolean hasResults()
    {
        return !getResults().isEmpty();
    }

    /**
     * Return the results for the given criteria.  This is guaranteed
     * to never return <code>null</code>.
     *
     * @return {@link List} of all results for the criteria
     */
    public List getResults()
    {
        if (results == null)
        {
            results = getStoredResults();
        }
        
        return (results != null) ? results : Collections.EMPTY_LIST;
    }    
    
    /**
     * Return the index for the next page of results
     * (as determined by the current index, items per page, and 
     * the number of results).  If no "next page" exists, then null is
     * returned.
     *
     * @return index for the next page or <code>null</code> if none
exists
     */
    public Integer getNextIndex()
    {
        int next = index + itemsPerPage;
        if (next < getResults().size())
        {
            return new Integer(next);
        }
        return null;
    }
    

    /**
     * Return the index for the previous page of results
     * (as determined by the current index, items per page, and 
     * the number of results).  If no "next page" exists, then null is
     * returned.
     *
     * @return index for the previous page or <code>null</code> if none
exists
     */
    public Integer getPrevIndex()
    {
        int prev = Math.min(index, getResults().size()) - itemsPerPage;
        if (index > 0)
        {
            return new Integer(Math.max(0, prev));
        }
        return null;
    }
    
    /**
     * Return the number of pages that can be made from this list
     * given the set number of items per page.
     */
    public int getPagesAvailable()
    {
        return (int)Math.ceil(getResults().size() /
(double)itemsPerPage);
    }


    /**
     * Return the current "page" of search results.
     *
     * @return a {@link List} of results for the "current page"
     */
    public List getPage()
    {
        /* return null if we have no results */
        if (!hasResults())
        {
            return null;
        }
        /* quietly keep the page indices to legal values for robustness'
sake */
        int start = Math.min(getResults().size() - 1, index);
        int end = Math.min(getResults().size(), index + itemsPerPage);
        return getResults().subList(start, end);
    }
    
    /**
     * Returns the "page number" for the specified index.  Because the
page
     * number is used for the user interface, the page numbers are
1-based.
     *
     * @param i the index that you want the page number for
     * @return the approximate "page number" for the specified index or 
     *         <code>null</code> if there are no results
     */
    public Integer getPageNumber(int i)
    {
        if (!hasResults())
        {
            return null;
        }
        return new Integer(1 + i / itemsPerPage);
    }


    /**
     * Returns the "page number" for the current index.  Because the
page
     * number is used for the user interface, the page numbers are
1-based.
     *
     * @return the approximate "page number" for the current index or 
     *         <code>null</code> if there are no results
     */
    public Integer getPageNumber()
    {
        return getPageNumber(index);
    }

    /**
     * <p>Returns a description of the current page.  This
implementation
     * displays a 1-based range of result indices and the total number 
     * of results.  (e.g. "1 - 10 of 42" or "7 of 7")</p>
     *
     * <p>Sub-classes may override this to provide a customized 
     * description (such as one in another language).</p>
     *
     * @return a description of the current page
     */
    public String getPageDescription()
    {
        StringBuffer out = new StringBuffer();
        int first = index + 1;
        int total = getResults().size();
        if (first >= total)
        {
            out.append(total);
            out.append(" of ");
            out.append(total);
        }
        else
        {
            int last = Math.min(index + itemsPerPage, total);
            out.append(first);
            out.append(" - ");
            out.append(last);
            out.append(" of ");
            out.append(total);
        }
        return out.toString();
    }
    
    /**
     * Return a <b>S</b>liding <b>L</b>ist of <b>I</b>ndices for
<b>P</b>ages
     * of search results.
     *
     * <p>Essentially, this returns a list of result indices that
correspond
     * to available pages of search results (as based on the set 
     * items-per-page). This makes it relativly easy to do a google-ish
set 
     * of links to result pages.</p>
     *
     * <p>Note that this list of Integers is 0-based to correspond with
the
     * underlying result indices and not the displayed page numbers (see
     * {@link #getPageNumber}).</p>
     *
     * @return {@link List} of Integers representing the indices of
result 
     *         pages or empty list if there's one or less pages
available
     */
    public List getSlip()
    {
        /* return an empty list if there's no pages to list */
        int totalPgs = getPagesAvailable();
        if (totalPgs <= 1)
        {
            return Collections.EMPTY_LIST;
        }

        /* page number is 1-based so decrement it */
        int curPg = getPageNumber().intValue() - 1;

        /* don't include current page in slip size calcs */
        int adjSlipSize = slipSize - 1;

        /* start at zero or just under half of max slip size 
         * this keeps "forward" and "back" pages about even
         * but gives preference to "forward" pages */
        int slipStart = Math.max(0, (curPg - (adjSlipSize / 2)));

        /* push slip end as far as possible */
        int slipEnd = Math.min(totalPgs, (slipStart + adjSlipSize));

        /* if we're out of "forward" pages, then push the 
         * slip start toward zero to maintain slip size */
        if (slipEnd - slipStart < adjSlipSize)
        {
            slipStart = Math.max(0, slipEnd - adjSlipSize);
        }

        /* convert 0-based page numbers to indices and create list */
        List slip = new ArrayList((slipEnd - slipStart) + 1);
        for (int i=slipStart; i < slipEnd; i++)
        {
            slip.add(new Integer(i * itemsPerPage));
        }
        return slip;
    }

    /*  ---------------------- private methods
-----------------------------  */

    /**
     * Retrieves stored search results (if any) from the user's
     * session attributes.
     *
     * @return the {@link StoredResults} retrieved from memory
     */
    protected List getStoredResults()
    {
        if (session != null)
        {
            return (List)session.getAttribute(STORED_RESULTS_KEY);
        }
        return null;
    }


    /**
     * Stores current search results in the user's session attributes
     * (if one currently exists) in order to do efficient result
pagination.
     *
     * <p>Override this to store search results somewhere besides the
     * HttpSession or to prevent storage of results across requests. In
     * the former situation, you must also override
getStoredResults().</p>
     *
     * @param results the {@link StoredResults} to be stored
     */
    protected void setStoredResults(List results)
    {
        if (session != null)
        {
            session.setAttribute(STORED_RESULTS_KEY, results);
        }
    }

}




-- 
Matthew Van Horn <ma...@yahoo.com>


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: macro names from variables?

Posted by Geir Magnusson Jr <ge...@4quarters.com>.
On Aug 13, 2004, at 1:49 PM, Robert Brandner wrote:

> Hello!
>
> Is it possible do get the name of a macro to call from a variable?
>
> something like:
>
> #set($macroname = 'foo')
>
> #$macroname($parameters)   ## <-- something like that, to call the 
> macro
>
> #macro(foo $parameters)
>     ##
>     ## something wonderful is to happen here.
>     ##
> #end
>
> I tries with double quotes but had no success.
>
> Any ideas? Is it possible at all?

The only way is with an evaluation tool, that takes a string arg and 
treats it like a template.

There should be something in velocity tools.

geir

>
> Best regards
> Robert
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: velocity-user-help@jakarta.apache.org
>
>
-- 
Geir Magnusson Jr                                   203-247-1713(m)
geir@4quarters.com


-- 
Geir Magnusson Jr                                   203-247-1713(m)
geir@4quarters.com 
                                  


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


macro names from variables?

Posted by Robert Brandner <ro...@chello.at>.
Hello!

Is it possible do get the name of a macro to call from a variable?

something like:

#set($macroname = 'foo')

#$macroname($parameters)   ## <-- something like that, to call the macro

#macro(foo $parameters)
     ##
     ## something wonderful is to happen here.
     ##
#end

I tries with double quotes but had no success.

Any ideas? Is it possible at all?

Best regards
Robert


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org


Re: AbstractPagerTool

Posted by Nathan Bubna <na...@esha.com>.
Matthew Van Horn said:
> > this does bring up an interesting point. not everyone who wants paging
> > support will want it to be search oriented.  if no one beats me to it
(which
> > should be easy with how busy i am lately), i'll look into separating the
> > paging support out into a separate tool.
> >
> > Nathan Bubna
> > nathan@esha.com
> >
> >
> I needed this, so I've pulled out the critera/query/search stuff from
> the AbstractSearchTool, and turned it into an AbstractPagerTool.

cool.

> It works the same, you just need to do something like:
>
> $pager.setResults(myList)
>
> to give it a List to page through.

so why is it abstract?

> I know some people have asked about this, but I don't know the procedure
> for submitting this to the project, as I've never really done it before,
> and I'd want someone else to look it over, in case I screwed something
> up.
>
> What should I do?

post it to the list.  say that you want to contribute it to the project.  then
people (myself included) can look it over and post any feedback they have on
it.  then at some point i'll find some time to give it a quick test or two,
and if i like it, i'll commit it to CVS (unless, of course, one of the other
committers beats me to it).

Nathan Bubna
nathan@esha.com


---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-user-help@jakarta.apache.org