    001    // Copyright 2006, 2007, 2008, 2010, 2011 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.tapestry5.ioc.internal.services;
    016
    017    import org.apache.tapestry5.ioc.internal.util.GenericsUtils;
    018    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    019    import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
    020    import org.apache.tapestry5.ioc.services.PropertyAdapter;
    021
    022    import java.beans.PropertyDescriptor;
    023    import java.lang.reflect.Field;
    024    import java.lang.reflect.Method;
    025    import java.util.List;
    026    import java.util.Map;
    027
    028    import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newCaseInsensitiveMap;
    029
    030    public class ClassPropertyAdapterImpl implements ClassPropertyAdapter
    031    {
    032        private final Map<String, PropertyAdapter> adapters = newCaseInsensitiveMap();
    033
    034        private final Class beanType;
    035
    036        public ClassPropertyAdapterImpl(Class beanType, List<PropertyDescriptor> descriptors)
    037        {
    038            this.beanType = beanType;
    039
    040            for (PropertyDescriptor pd : descriptors)
    041            {
    042                // Indexed properties will have a null propertyType (and a non-null
    043                // indexedPropertyType). We ignore indexed properties.
    044
    045                if (pd.getPropertyType() == null)
    046                    continue;
    047
    048                Method readMethod = pd.getReadMethod();
    049
    050                Class propertyType = readMethod == null ? pd.getPropertyType() : GenericsUtils.extractGenericReturnType(
    051                        beanType, readMethod);
    052
    053                PropertyAdapter pa = new PropertyAdapterImpl(this, pd.getName(), propertyType, readMethod, pd
    054                        .getWriteMethod());
    055
    056                adapters.put(pa.getName(), pa);
    057            }
    058
    059            // Now, add any public fields (even if static) that do not conflict
    060
    061            for (Field f : beanType.getFields())
    062            {
    063                String name = f.getName();
    064
    065                if (!adapters.containsKey(name))
    066                {
    067                    Class propertyType = GenericsUtils.extractGenericFieldType(beanType, f);
    068                    PropertyAdapter pa = new PropertyAdapterImpl(this, name, propertyType, f);
    069
    070                    adapters.put(name, pa);
    071                }
    072            }
    073        }
    074
    075        public Class getBeanType()
    076        {
    077            return beanType;
    078        }
    079
    080        @Override
    081        public String toString()
    082        {
    083            String names = InternalUtils.joinSorted(adapters.keySet());
    084
    085            return String.format("<ClassPropertyAdaptor %s : %s>", beanType.getName(), names);
    086        }
    087
    088        public List<String> getPropertyNames()
    089        {
    090            return InternalUtils.sortedKeys(adapters);
    091        }
    092
    093        public PropertyAdapter getPropertyAdapter(String name)
    094        {
    095            return adapters.get(name);
    096        }
    097
    098        public Object get(Object instance, String propertyName)
    099        {
    100            return adaptorFor(propertyName).get(instance);
    101        }
    102
    103        public void set(Object instance, String propertyName, Object value)
    104        {
    105            adaptorFor(propertyName).set(instance, value);
    106        }
    107
    108        private PropertyAdapter adaptorFor(String name)
    109        {
    110            PropertyAdapter pa = adapters.get(name);
    111
    112            if (pa == null)
    113                throw new IllegalArgumentException(ServiceMessages.noSuchProperty(beanType, name));
    114
    115            return pa;
    116        }
    117
    118    }