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