001    // Copyright Jul 30, 2006 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    package org.apache.tapestry.dojo.form;
015    
016    import org.apache.commons.beanutils.PropertyUtils;
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.util.Defense;
019    
020    import java.util.ArrayList;
021    import java.util.List;
022    
023    
024    /**
025     * Default simple implementation of {@link IAutocompleteModel}. This class relies
026     * on the java beans specification to resolve key fields of an incoming 
027     * {@link List}. 
028     * 
029     * <p>
030     *  If you had an object type of <code>User</code>, with the primary/unique id of 
031     *  each <code>User</code> object stored as a member with a name of <code>id</code> 
032     *  you would pass something like this into the model(don't forget that javabeans syntax
033     *  requires a corresponding getId() for members):
034     * </p>
035     * 
036     * <pre>
037     *  IAutocompleteModel model = new DefaultAutocompleteModel(List users, "id", "name");
038     * </pre>
039     * 
040     * @see "http://jakarta.apache.org/commons/beanutils/commons-beanutils-1.6.1/docs/api/org/apache/commons/beanutils/PropertyUtils.html"
041     * @author jkuhnert
042     */
043    public class DefaultAutocompleteModel implements IAutocompleteModel
044    {
045    
046        private List _values;
047        
048        private String _keyExpression;
049        
050        private String _labelExpression;
051        
052        /**
053         * Create a new model using java beans syntax to access the key/label
054         * for the list using the specified bean expressions.
055         * 
056         * @param values 
057         *          The list of values to manage.
058         * @param keyField 
059         *          The java beans expression for getting the primary key of each object
060         *          in the list. {@link #getPrimaryKey(Object)}.
061         * @param labelField
062         *          The java beans expression for getting the label of each object
063         *          in the list. {@link #getLabelFor(Object)}.
064         */
065        public DefaultAutocompleteModel(List values, String keyField, String labelField) 
066        {
067            Defense.notNull(values, "Value list can't be null.");
068            Defense.notNull(keyField, "Model keyField java beans expression can't be null.");
069            Defense.notNull(labelField, "Model labelField java beans expression can't be null.");
070            
071            _values = values;
072            _keyExpression = keyField;
073            _labelExpression = labelField;
074        }
075        
076        /**
077         * {@inheritDoc}
078         */
079        public List getValues(String match)
080        {
081            List ret = new ArrayList();
082            
083            if (match == null)
084                return ret;
085            
086            String filter = match.trim().toLowerCase();
087            
088            for (int i = 0; i < _values.size(); i++)
089            {    
090                Object value = _values.get(i);
091                String label = getLabelFor(value);
092                
093                if (label.toLowerCase().indexOf(filter) > -1)
094                    ret.add(value);
095            }
096            
097            return ret;
098        }
099        
100        /** 
101         * {@inheritDoc}
102         */
103        public String getLabelFor(Object value)
104        {
105            try
106            {
107                return PropertyUtils.getProperty(value, _labelExpression).toString();
108            } catch (Exception e)
109            {
110                throw new ApplicationRuntimeException(e);
111            }
112        }
113    
114        /** 
115         * {@inheritDoc}
116         */
117        public Object getPrimaryKey(Object value)
118        {
119            try
120            {
121                return PropertyUtils.getProperty(value, _keyExpression);   
122            } catch (Exception e)
123            {
124                throw new ApplicationRuntimeException(e);
125            }
126        }
127    
128        /** 
129         * {@inheritDoc}
130         */
131        public Object getValue(Object primaryKey)
132        {
133            for (int i = 0; i < _values.size(); i++)
134            {    
135                Object value = _values.get(i);
136                
137                if (getPrimaryKey(value).toString().equals(primaryKey.toString()))
138                    return value;
139            }
140            
141            return null;
142        }
143    
144    }