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
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            setComparator(new DefaultTableComparator());
135            setDisplayName(strDisplayName);
136            setColumnRendererSource(DEFAULT_COLUMN_RENDERER_SOURCE);
137            setValueRendererSource(DEFAULT_VALUE_RENDERER_SOURCE);
138            setEvaluator(objEvaluator);
139        }
140    
141        /**
142         * Returns the display name of the column that will be used in the table
143         * header. Override for internationalization.
144         * 
145         * @return String the display name of the column
146         */
147        public String getDisplayName()
148        {
149            m_strDisplayName.replace('.', '_'); // added from patch
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            if (objEvaluator != null)
211                return objEvaluator.getColumnValue(this, objRow);
212    
213            // default fallback
214            return objRow.toString();
215        }
216    
217        /**
218         * Use the column name to get the display name, as well as the column and
219         * value renderer sources from the provided component.
220         * 
221         * @param objSettingsContainer
222         *            the component from which to get the settings
223         */
224        public void loadSettings(IComponent objSettingsContainer)
225        {
226            String strDisplayName = objSettingsContainer.getMessages().getMessage(
227                    getColumnName());
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("[")) setDisplayName(strDisplayName);
235    
236            super.loadSettings(objSettingsContainer);
237        }
238    
239        /**
240         * 
241         * @author mb
242         */
243        public class DefaultTableComparator implements Comparator, Serializable
244        {
245    
246            private static final long serialVersionUID = 1L;
247    
248            public int compare(Object objRow1, Object objRow2)
249            {
250                Object objValue1 = getColumnValue(objRow1);
251                Object objValue2 = getColumnValue(objRow2);
252    
253                if (objValue1 == objValue2) return 0;
254    
255                boolean bComparable1 = objValue1 instanceof Comparable;
256                boolean bComparable2 = objValue2 instanceof Comparable;
257    
258                // non-comparable values are considered equal
259                if (!bComparable1 && !bComparable2) return 0;
260    
261                // non-comparable values (null included) are considered smaller
262                // than the comparable ones
263                if (!bComparable1) return -1;
264    
265                if (!bComparable2) return 1;
266    
267                return ((Comparable) objValue1).compareTo(objValue2);
268            }
269        }
270    
271    }