001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry.contrib.table.components;
016
017import java.util.Iterator;
018import java.util.Map;
019
020import org.apache.tapestry.IRequestCycle;
021import org.apache.tapestry.contrib.table.model.IPrimaryKeyConvertor;
022
023
024/**
025 * A low level Table component that generates the rows of the current page in the table.
026 * 
027 * This component is a variant of {@link org.apache.tapestry.contrib.table.components.TablePages},
028 * but is designed for operation in a form. The displayed rows are stored in 
029 * hidden form fields, which are then read during a rewind. This ensures that
030 * the form will rewind in exactly the same was as it was rendered even if the 
031 * TableModel has changed and no StaleLink exceptions will occur. 
032 * 
033 * The component must be wrapped by {@link org.apache.tapestry.contrib.table.components.TableView}.
034 * 
035 * <p>
036 * The component iterates over the rows of the current page in the table. 
037 * The rows are wrapped in 'tr' tags by default. 
038 * You can define columns manually within, or
039 * you can use {@link org.apache.tapestry.contrib.table.components.TableValues} 
040 * to generate the columns automatically.
041 * <p> 
042 * Please see the Component Reference for details on how to use this component. 
043 * 
044 *  [<a href="../../../../../../../ComponentReference/contrib.TableFormRows.html">Component Reference</a>]
045 * 
046 * @author mindbridge
047 *
048 */
049public abstract class TableFormRows extends TableRows
050{
051    public abstract IPrimaryKeyConvertor getConvertor();
052    public abstract IPrimaryKeyConvertor getConvertorCache();
053    public abstract void setConvertorCache(IPrimaryKeyConvertor convertor);
054    public abstract Map getConvertedValues();
055
056    /**
057     * Returns the PK convertor cached within the realm of the current request cycle.
058     *  
059     * @return the cached PK convertor
060     */
061    public IPrimaryKeyConvertor getCachedConvertor()
062    {
063        IPrimaryKeyConvertor objConvertor = getConvertorCache();
064        
065        if (objConvertor == null) {
066            objConvertor = getConvertor();
067            setConvertorCache(objConvertor);
068        }
069        
070        return objConvertor;
071    }
072
073    /**
074     * Get the list of all table rows to be displayed on this page, converted 
075     * using the PK.convertor.
076     * 
077     * @return an iterator of all converted table rows
078     */    
079    public Iterator getConvertedTableRowsIterator()
080    {
081        final Iterator objTableRowsIterator = getTableRowsIterator(); 
082        final IPrimaryKeyConvertor objConvertor = getCachedConvertor();
083        if (objConvertor == null)
084            return objTableRowsIterator;
085            
086        return new Iterator()
087        {
088            public boolean hasNext()
089            {
090                return objTableRowsIterator.hasNext();
091            }
092
093            public Object next()
094            {
095                Object objValue = objTableRowsIterator.next();
096                Object objPrimaryKey = objConvertor.getPrimaryKey(objValue);
097                Map mapConvertedValues = getConvertedValues(); 
098                mapConvertedValues.put(objPrimaryKey, objValue);
099                return objPrimaryKey;
100            }
101
102            public void remove()
103            {
104                objTableRowsIterator.remove();
105            }
106        };
107    }
108
109    /**
110     * Sets the current table row PK and invokes {@link #setTableRow(Object)} as a result.
111     * This method is for internal use only.
112     * 
113     * @param objConvertedTableRow The current converted table row (PK)
114     */
115    public void setConvertedTableRow(Object objConvertedTableRow)
116    {
117        Object objValue = objConvertedTableRow;
118
119        IPrimaryKeyConvertor objConvertor = getCachedConvertor();
120        if (objConvertor != null) {
121            IRequestCycle objCycle = getPage().getRequestCycle();
122            if (objCycle.isRewinding()) {
123                objValue = objConvertor.getValue(objConvertedTableRow);  
124            }
125            else {
126                Map mapConvertedValues = getConvertedValues(); 
127                objValue = mapConvertedValues.get(objConvertedTableRow);
128            }
129        }
130
131        setTableRow(objValue);
132    }
133}