Using Iterators

printer-friendly version of this section  Print  e-mail this section  E-Mail  add a public, group or private note  Add Note  add a bookmark about this section  Add Bookmark    

JSTL: JSP Standard Tag Library Kick Start
By Jeff Heaton

Table of Contents
Chapter 5.  Collections, Loops, and Iterators


Now that you have seen the <c:forEach> tag, let's look at a few examples of iterators. There are many common uses for iterators in JSP pages, and the following sections examine the most useful ones.

Iterating over Strings

As we mentioned earlier, the iterator tags can iterate over strings if the strings are comma delimited. Listing 5.1 shows a program that iterates over a string of comma-separated values.

Listing 5.1 Iteration and Strings (string.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html>   <head>     <title>String Collection Examples</title>   </head>   <body>     <h3>String Collection Example</h3>     <c:set var="str"     value="Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,   Saturday" />     <b>Input String:</b>     <br />     <br />     <c:out value="${str}" />     <br />     <br />     <b>Iterating:</b>     <br />     <br />     <c:forEach var="day" items="${str}">       <c:out value="${day}" />       <br />     </c:forEach>   </body> </html> 

In Listing 5.1, a string is assigned to hold the days of the week. Then a <c:forEach> tag is used to iterate through the list of string values. The following lines of code do this:

<c:forEach var="day" items="${str}">   <c:out value="${day}" />   <br /> </c:forEach> 

As you can see, the string is sent to the tag as the items attribute, and each element of the string will be copied to the day scoped variable. This variable is then printed out through each round of the iteration. The output from this program is shown in Figure 5.1.

Figure 5.1. Iteration over a string.

graphics/05fig01.jpg

Fixed-Length Loops

Collections are not the only sort of loop that can be done with the <c:forEach> tag. You may also use fixed loops that will count between a specified range of numbers. These loops resemble the for loops that the Java programming language provides. Listing 5.2 shows a program that makes use of fixed-length loops.

Listing 5.2 Fixed-Length Loops (fixed.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html>   <head>     <title>Count to 10 Example (using JSTL)</title>   </head>   <body>     <table border="1">       <tr>         <td valign="top">           <h3>From 1 to 10</h3>           <c:forEach var="i" begin="1" end="10">             <c:out value="${i}" />             <br />           </c:forEach>         </td>         <td valign="top">           <h3>From 10 to 1</h3>           <c:forEach var="i" begin="1" end="10">             <c:out value="${11-i}" />             <br />           </c:forEach>         </td>       </tr>       <tr>         <td>           <h3>By Twos</h3>           <c:forEach var="i" begin="2" end="10" step="2">             <c:out value="${i}" />             <br />           </c:forEach>         </td>         <td valign="top">&nbsp;         </td>       </tr>     </table>   </body> </html> 

The program in Listing 5.2 actually displays four types of loops. The first loop is just a simple count from 1 to 10, using the following lines of code:

<c:forEach var="i" begin="1" end="10">   <c:out value="${i}" />   <br /> </c:forEach> 

This simple loop specifies a begin attribute of 1 and an end attribute of 10.

The second loop counts from 10 to 1 backward, using the following lines of code:

<c:forEach var="i" begin="1" end="10">   <c:out value="${11-i}" />   <br /> </c:forEach> 

As we mentioned earlier, the iteration tags are not capable of counting backward. Because of this, we use nearly the same <c:for> tag as the count-to-10 example. The only difference is that the out tag uses the expression ${11-i} to adjust the output from this loop to appear as if the program is counting backward from 10.

The next loop shows how to use the step attribute. If a step attribute is specified, the count can skip numbers. The following lines of code count from 2 to 10 by twos:

<c:forEach var="i" begin="2" end="10" step="2">   <c:out value="${i}" />   <br /> </c:forEach> 

Keep in mind that the beginning index must not be greater than the ending index. This will cause an exception to be raised, as shown here:

<c:forEach var="i" begin="101" end="100" step="500">   <c:out value="${i}" /> </c:forEach> 

This program shows three different ways the <c:forEach> tag can be used to create fixed strings. The program's output is shown in Figure 5.2.

Figure 5.2. Fixed-length loops.

graphics/05fig02.jpg

The <c:forTokens> Tag

The <c:forEach> tag has the ability to iterate over a string of comma-delineated items. JSTL also provides the more general <c:forTokens> tag, which allows you to iterate over a string that is delimited by values other than commas. Here is one form of the <c:forTokens> tag:

<c:forTokens items="stringOfTokens" delims="delimiters" [var="varName"] [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]> body content </c:forEach> 

The <c:forTokens> tag's syntax closely resembles that of the <c:forEach> tag. The attribute items is used to pass in the string to be parsed. The attributes begin and end allow you to specify beginning and ending items, which means you can make the iteration skip elements from the beginning or end of the list. The step attribute allows you to skip elements within the list for example, a step attribute with the value of 2 would process only every other item.

The delims attribute allows you to specify what delimiters to use. JSTL can parse only single-character delimiters. If you specify more than one character as the delimiter, JSTL will end an item on any of the characters that you provided as a delimiter. For example, the delimiter string,;: would break up items based on the occurrence of the comma(,), semicolon(;), or colon(:).

The <c:forTokens> tag also includes the varStatus attribute. This attribute enables you to obtain information about the iteration as it progresses.

Using the <c:forTokens> tag, you can easily process delimiters other than the comma. Listing 5.3 shows a program that will separate a sentence into its component words.

Listing 5.3 Iterating over Tokens (token.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <html>   <head>     <title>Updatable Collections</title>   </head>   <body>     <table border="0">       <form method="post">         <tr bgcolor="blue">           <td>             <p align="center">               <b>                 <font color="#FFFFFF">Parse for Tokens</font>               </b>             </p>           </td>         </tr>         <tr>           <td valign="top">             <p align="left">Enter a sentence:             <br />             <input width="20" maxwidth="20" name="text"             size="50" />             <br />             &#160;</p>           </td>         </tr>         <tr>           <td valign="top">             <p align="center">               <input type="submit" name="parse" value="Parse" />             </p>           </td>         </tr>       </form>     </table>     <c:if test="${pageContext.request.method=='POST'}">       <table border="1">         <c:set var="i" value="1" />         <c:forTokens items="${param.text}" var="word"         delims=" ,.?! \'">           <c:set var="i" value="${i+1}" />           <tr>             <td>               <b>Word               <c:out value="${i}" />               </b>             </td>             <td>               <c:out value="${word}" />             </td>           </tr>         </c:forTokens>       </table>     </c:if>   </body> </html> 

The program in Listing 5.3 begins with a typical HTML form that asks the user to input a sentence. When the user does so, the sentence is broken down into its component words and displayed to the user. Our program uses the <c:forTokens> tag to break up this string, as shown here:

<c:forTokens items="${param.text}" var="word" delims=" ,.?!\'"> 

As you can see, this code specifies several delimiters. Most of the normal English punctuation characters are used as delimiters, and thus would count as an end to a word. As our program loops through the string, each word is printed out. The program also maintains a counter variable, i, to display the current position in the loop. (You could also keep count by using a varStatus attribute. We discuss the varStatus attribute again in the section "Tag Collaboration with a Fixed Loop" section later in this chapter.) The output from this program is shown in Figure 5.3.

Figure 5.3. Iterating over tokens.

graphics/05fig03.jpg

Modifying a Collection

So far, the collections that we have examined have remained static. In this section, we show you how to create a comma-delineated collection that can have elements dynamically added and removed from it. Listing 5.4 shows this program.

Listing 5.4 Modifying a Collection (modify.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <c:if test="${pageContext.request.method=='POST'}">   <c:choose>     <c:when test="${param.add!=null}">       <c:if test="${sessionScope.list!=null and sessionScope.   list!=''}">         <c:set var="list" value="${list}," scope="session" />       </c:if>       <c:set var="list" value="${list}${param.item}"       scope="session" />     </c:when>     <c:when test="${param.remove!=null}">       <c:set var="list2" value="" />       <c:forEach var="item" items="${sessionScope.list}">         <c:if test="${item!=param.item}">           <c:if test="${list2!=''}">             <c:set var="list2" value="${list2}," />           </c:if>           <c:set var="list2" value="${list2}${item}" />         </c:if>       </c:forEach>       <c:set var="list" value="${list2}" scope="session" />       <c:remove var="list2" />     </c:when>   </c:choose> </c:if> <html>   <head>     <title>Updatable Collections</title>   </head>   <body>     <table border="0">       <form method="post">         <tr bgcolor="blue">           <td colspan="2">             <font color="white">Updatable Collections</font>           </td>         </tr>         <tr>           <td valign="top">             <select NAME="choice" SIZE="5" width="20">               <c:forEach var="item" items="${sessionScope.list}">                 <option>                   <c:out value="${item}" />                 </option>               </c:forEach>             </select>           </td>           <td valign="top">Enter a item to add or remove.           <br />           <input width="20" maxwidth="20" name="item" size="20" />           <br />           <input type="submit" name="add" value="Add" />           <input type="submit" name="remove" value="Remove" />           </td>         </tr>       </form>     </table>   </body> </html> 

The program in Listing 5.4 works by displaying a list box next to a text field and two buttons. The user enters a value in the text field, and uses the buttons to either add or remove that item from the list box.

First, let's explain how to add a string to the list box. The contents of the list box are stored as a comma-delimited list in a session variable named list. When the first item is to be added to the list box, the list session variable is examined to see if there are any current values. If values already exist, the program appends a comma to the end of the list. After this, the new item that the user entered is appended to the list. The following lines of code do this:

<c:if test="${sessionScope.list!=null and sessionScope.list!=''}">   <c:set var="list" value="${list}," scope="session" /> </c:if> <c:set var="list" value="${list}${param.item}" scope="session" /> 

The process of removing an item from the list is more complex. It is possible that the item to be removed might exist anywhere in the comma-separated list. To remove this item, the program must rebuild the list line by line. First, a page-scoped variable named list2 is initialized to an empty string. This variable will receive the contents of the new list:

<c:set var="list2" value="" /> 

Next, the program must iterate through the current list. The following <c:forEach> tag sets up to iterate through the current list:

<c:forEach var="item" items="${sessionScope.list}"> 

As items are encountered in the list, they are added to the newly created list in the variable list2. However, we must filter out the item that we want removed. If we fail to do this, we will simply re-create the list with the item still in the list. This is done with the following line of code:

<c:if test="${item!=param.item}"> 

Once we have verified that the current item is not the one that is to be removed, we must add it to the list. First, we must see if the new list is empty if it is, then a comma will be appended to the list. This prevents the new list from starting with a comma rather than the first value. The following line of code makes this test and adds the comma if it is required:

<c:if test="${list2!=''}"> 

If the program finds that the list is not empty, then it adds a comma to separate the new item from what is already in the list:

  <c:set var="list2" value="${list2}," /> </c:if> 

Now that the comma has been added to the list, we can add the new item. The following lines of code complete this process:

    <c:set var="list2" value="${list2}${item}" />   </c:if> </c:forEach> 

At this point, the list has been re-created in the new list2 variable. The next step is to copy the new variable back to the old session list. The following line of code performs this step:

<c:set var="list" value="${list2}" scope="session" /> 

Now that the new list has been copied, the temporary list, stored in list2, can be deleted. This is done with the following <c:remove> tag:

<c:remove var="list2" /> 

This program demonstrates most of the concepts of iteration. The output can be seen in Figure 5.4.

Figure 5.4. Modifying a collection.

graphics/05fig04.jpg

Tag Collaboration with a Fixed Loop

Displaying lists is common in Web applications. Often, these lists are displayed in alternating colors. This resembles the lines of a ledger, such as one for a checking account.

Reproducing this ledger look in a Web application is a good use for the varStatus attribute of both the <c:forEach> and the <c:forTokens> tags. By using the getCount() method of the varStatus variable, you can determine whether you are on an even or odd row. Your program can then display the appropriate color because it alternates the background color for even and odd rows.

Let's look at an example. Listing 5.5 shows how the varStatus attribute can be used to alternate colors on a fixed-size loop.

Listing 5.5 Tag Collaboration (evenodd.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/core-rt" prefix="c-rt" %> <html>   <head>     <title>Count to 10 Example(tracking even and odd)</title>   </head>   <body>     <table border="0">       <c:forEach var="i" begin="1" end="10" varStatus="status">         <jsp:useBean          type="javax.servlet.jsp.jstl.core.LoopTagStatus" />         <c-rt:choose>           <c-rt:when test="<%=status.getCount()%2==0%>">             <c:set var="color" value="#eeeeee" />           </c-rt:when>           <c-rt:otherwise>             <c:set var="color" value="#dddddd" />           </c-rt:otherwise>         </c-rt:choose>         <tr>           <td width="200" bgcolor="<c:out value="${color}"/>">           <c:out value="${i}" />           </td>         </tr>       </c:forEach>     </table>   </body> </html> 

In Listing 5.5, the program's loop is simple and is identical in concept to the count-to-10 example. The primary difference is that we use the varStatus attribute to gain access to the row counter. As shown here, this loop starts off just like the count-to-10 example:

<c:forEach var="i" begin="1" end="10" varStatus="status"> 

The primary difference in this loop is that the scoped variable status is specified in the varStatus attribute. This will make the status information available as the loop processes.

To take advantage of the status variable, we must map that variable to a bean. This is because the status object returns most of its information through method calls. The EL expression language is not capable of receiving information this way. Therefore, we'll use the RT expression language. As explained in Chapter 4, when using the RT expression language, all objects that are to be used must be mapped to beans. The following code maps the status variable to a bean:

<jsp:useBean        type="javax.servlet.jsp.jstl.core.LoopTagStatus" /> 

Now that the RT expression language has access to the status object, we must check the count. This is done by using a <c-rt:choose> tag. Here, we can compare the count and take two alternating actions, depending on whether the current row is even or odd. The following code checks to see whether the row is even:

<c-rt:choose>   <c-rt:when test="<%=status.getCount()%2==0%>">     <c:set var="color" value="#eeeeee" />   </c-rt:when> 

If the row is found to be even, then a color is assigned to the page-scoped variable named color. To handle odd values, we use this code:

  <c-rt:otherwise>     <c:set var="color" value="#dddddd" />   </c-rt:otherwise> </c-rt:choose> 

For odd values, a different color is saved to the color page-scoped variable.

Now that our program has determined the color, it must use that color in the HTML. The following code causes the color to appear as the background color of table rows:

<tr>  <td width="200" bgcolor="<c:out value="${color}"/>">  <c:out value="${i}" />  </td> 

Figure 5.5 shows the output from this program.

Figure 5.5. Tag collaboration.

graphics/05fig05.jpg

Tag Collaboration with a Collection

The varStatus attribute can be used with collections as well as fixed-loop tags. Both the <c:forEach> and the <c:forTokens> tags support the use of a varStatus tag. Listing 5.6 shows a collections-based program that makes use of the varStatus attribute as well.

Listing 5.6 Collections-Based Tag Collaboration (evenoddlist.jsp)
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jstl/core-rt" prefix="c-rt" %> <html>   <head>     <title>Count to 10 Example(tracking even and odd)</title>   </head>   <body>     <c:set var="days"     value="Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday" />     <table border="0">       <c:forEach var="i" items="${days}" varStatus="status">         <jsp:useBean          type="javax.servlet.jsp.jstl.core.LoopTagStatus" />         <c-rt:choose>           <c-rt:when test="<%=status.getCount()%2==0%>">             <c:set var="color" value="#eeeeee" />           </c-rt:when>           <c-rt:otherwise>             <c:set var="color" value="#dddddd" />           </c-rt:otherwise>         </c-rt:choose>         <tr>           <td width="200" bgcolor="<c:out value="${color}"/>">           <c:out value="${i}" />           </td>         </tr>       </c:forEach>     </table>   </body> </html> 

As you can see in Listing 5.6, the basic loop construct is the same as in our previous example. This makes the <c:forEach> and <c:forTokens> tags interchangeable. Figure 5.6 shows the output from this program.

Figure 5.6. Tag collaboration with a collection.

graphics/05fig06.jpg


    printer-friendly version of this section  Print  e-mail this section  E-Mail  add a public, group or private note  Add Note  add a bookmark about this section  Add Bookmark    
    Top

    [0672324504/ch05lev1sec3]

     
     


    JSTL. JSP Standard Tag Library Kick Start
    JSTL: JSP Standard Tag Library Kick Start
    ISBN: 0672324504
    EAN: 2147483647
    Year: 2001
    Pages: 93
    Authors: Jeff Heaton

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net