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.model.simple;
016    
017    import java.io.Serializable;
018    import java.util.Comparator;
019    
020    import org.apache.tapestry.IComponent;
021    import org.apache.tapestry.contrib.table.model.ITableRendererSource;
022    import org.apache.tapestry.contrib.table.model.common.AbstractTableColumn;
023    
024    /**
025     * A simple minimal implementation of the
026     * {@link org.apache.tapestry.contrib.table.model.ITableColumn}interface that provides all the
027     * basic services for displaying a column.
028     * 
029     * @author mindbridge
030     */
031    public class SimpleTableColumn extends AbstractTableColumn
032    {
033            private static final long serialVersionUID = 1L;
034    
035            // TODO: Unify SimpleTableColumnRendererSource and SimpleTableColumnFormRendererSource
036            // and implement the configuration with HiveMind
037            
038        public static final ITableRendererSource DEFAULT_COLUMN_RENDERER_SOURCE = new SimpleTableColumnRendererSource();
039    
040        public static final ITableRendererSource FORM_COLUMN_RENDERER_SOURCE = new SimpleTableColumnFormRendererSource();
041    
042        public static final ITableRendererSource DEFAULT_VALUE_RENDERER_SOURCE = new SimpleTableValueRendererSource();
043    
044        private String m_strDisplayName;
045    
046        private ITableColumnEvaluator m_objEvaluator;
047    
048        /**
049         * Creates a SimpleTableColumn
050         * 
051         * @param strColumnName
052         *            the identifying name and display name of the column
053         */
054        public SimpleTableColumn(String strColumnName)
055        {
056            this(strColumnName, strColumnName);
057        }
058    
059        /**
060         * Creates a SimpleTableColumn
061         * 
062         * @param strColumnName
063         *            the identifying name and display name of the column
064         * @param bSortable
065         *            whether the column is sortable
066         */
067        public SimpleTableColumn(String strColumnName, boolean bSortable)
068        {
069            this(strColumnName, strColumnName, bSortable);
070        }
071    
072        /**
073         * Creates a SimpleTableColumn
074         * 
075         * @param strColumnName
076         *            the identifying name and display name of the column
077         * @param bSortable
078         *            whether the column is sortable
079         * @param objEvaluator
080         *            the evaluator to extract the column value from the row
081         */
082        public SimpleTableColumn(String strColumnName, ITableColumnEvaluator objEvaluator,
083                boolean bSortable)
084        {
085            this(strColumnName, strColumnName, objEvaluator, bSortable);
086        }
087    
088        /**
089         * Creates a SimpleTableColumn
090         * 
091         * @param strColumnName
092         *            the identifying name of the column
093         * @param strDisplayName
094         *            the display name of the column
095         */
096        public SimpleTableColumn(String strColumnName, String strDisplayName)
097        {
098            this(strColumnName, strDisplayName, false);
099        }
100    
101        /**
102         * Creates a SimpleTableColumn
103         * 
104         * @param strColumnName
105         *            the identifying name of the column
106         * @param strDisplayName
107         *            the display name of the column
108         * @param bSortable
109         *            whether the column is sortable
110         */
111        public SimpleTableColumn(String strColumnName, String strDisplayName, boolean bSortable)
112        {
113            this(strColumnName, strDisplayName, null, bSortable);
114        }
115    
116        /**
117         * Creates a SimpleTableColumn
118         * 
119         * @param strColumnName
120         *            the identifying name of the column
121         * @param strDisplayName
122         *            the display name of the column
123         * @param bSortable
124         *            whether the column is sortable
125         * @param objEvaluator
126         *            the evaluator to extract the column value from the row
127         */
128        public SimpleTableColumn(String strColumnName, String strDisplayName,
129                ITableColumnEvaluator objEvaluator, boolean bSortable)
130        {
131            super(strColumnName, bSortable, null);
132            setComparator(new DefaultTableComparator());
133            setDisplayName(strDisplayName);
134            setColumnRendererSource(DEFAULT_COLUMN_RENDERER_SOURCE);
135            setValueRendererSource(DEFAULT_VALUE_RENDERER_SOURCE);
136            setEvaluator(objEvaluator);
137        }
138    
139        /**
140         * Returns the display name of the column that will be used in the table header. Override for
141         * internationalization.
142         * 
143         * @return String the display name of the column
144         */
145        public String getDisplayName()
146        {
147            return m_strDisplayName;
148        }
149        
150        /**
151         * Sets the displayName.
152         * 
153         * @param displayName
154         *            The displayName to set
155         */
156        public void setDisplayName(String displayName)
157        {
158            m_strDisplayName = displayName;
159        }
160    
161        /**
162         * Returns the evaluator.
163         * 
164         * @return ITableColumnEvaluator
165         */
166        public ITableColumnEvaluator getEvaluator()
167        {
168            return m_objEvaluator;
169        }
170    
171        /**
172         * Sets the evaluator.
173         * 
174         * @param evaluator
175         *            The evaluator to set
176         */
177        public void setEvaluator(ITableColumnEvaluator evaluator)
178        {
179            m_objEvaluator = evaluator;
180        }
181    
182        /**
183         * Sets a comparator that compares the values of this column rather than the objects
184         * representing the full rows. <br>
185         * This method allows easier use of standard comparators for sorting the column. It simply wraps
186         * the provided comparator with a row-to-column convertor and invokes the setComparator()
187         * method.
188         * 
189         * @param comparator
190         *            The column value comparator
191         */
192        public void setColumnComparator(Comparator comparator)
193        {
194            setComparator(new ColumnComparator(this, comparator));
195        }
196    
197        /**
198         * Extracts the value of the column from the row object
199         * 
200         * @param objRow
201         *            the row object
202         * @return Object the column value
203         */
204        public Object getColumnValue(Object objRow)
205        {
206            ITableColumnEvaluator objEvaluator = getEvaluator();
207            if (objEvaluator != null)
208                return objEvaluator.getColumnValue(this, objRow);
209    
210            // default fallback
211            return objRow.toString();
212        }
213    
214        /**
215         * Use the column name to get the display name, as well as the column and value renderer sources
216         * from the provided component.
217         * 
218         * @param objSettingsContainer
219         *            the component from which to get the settings
220         */
221        public void loadSettings(IComponent objSettingsContainer)
222        {
223            String strDisplayName = objSettingsContainer.getMessages().getMessage(getColumnName());
224    
225            // Hack! the Messages inteface needs to restore the getMessage(key, default), or needs
226            // to add a containsKey(key) method. Looking for the '[' used with invalid/unknown keys.
227    
228            if (!strDisplayName.startsWith("["))
229                setDisplayName(strDisplayName);
230    
231            super.loadSettings(objSettingsContainer);
232        }
233    
234        public class DefaultTableComparator implements Comparator, Serializable
235        {
236            private static final long serialVersionUID = 1L;
237            
238            public int compare(Object objRow1, Object objRow2)
239            {
240                Object objValue1 = getColumnValue(objRow1);
241                Object objValue2 = getColumnValue(objRow2);
242    
243                if (objValue1 == objValue2)
244                    return 0;
245    
246                boolean bComparable1 = objValue1 instanceof Comparable;
247                boolean bComparable2 = objValue2 instanceof Comparable;
248    
249                // non-comparable values are considered equal
250                if (!bComparable1 && !bComparable2)
251                    return 0;
252    
253                // non-comparable values (null included) are considered smaller
254                // than the comparable ones
255                if (!bComparable1)
256                    return -1;
257    
258                if (!bComparable2)
259                    return 1;
260    
261                return ((Comparable) objValue1).compareTo(objValue2);
262            }
263        }
264    
265    }