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    
015    package org.apache.tapestry.contrib.table.components;
016    
017    import java.util.Iterator;
018    import java.util.Map;
019    
020    import org.apache.tapestry.IRequestCycle;
021    import 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     */
049    public 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    }