001    // Copyright 2007, 2008, 2010, 2011, 2014 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.internal.beaneditor;
016    
017    import org.apache.tapestry5.PropertyConduit;
018    import org.apache.tapestry5.beaneditor.BeanModel;
019    import org.apache.tapestry5.beaneditor.PropertyModel;
020    import org.apache.tapestry5.beaneditor.Sortable;
021    import org.apache.tapestry5.internal.TapestryInternalUtils;
022    import org.apache.tapestry5.ioc.Messages;
023    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
024    import org.apache.tapestry5.plastic.PlasticUtils;
025    
026    import java.lang.annotation.Annotation;
027    
028    @SuppressWarnings("all")
029    public class PropertyModelImpl implements PropertyModel
030    {
031        private final BeanModel model;
032    
033        private final String name;
034    
035        private final PropertyConduit conduit;
036    
037        private final String id;
038    
039        private String label;
040    
041        private String dataType;
042    
043        private boolean sortable;
044    
045        public PropertyModelImpl(BeanModel model, String name, PropertyConduit conduit, Messages messages)
046        {
047            this.model = model;
048            this.name = name;
049            this.conduit = conduit;
050    
051            id = TapestryInternalUtils.extractIdFromPropertyExpression(name);
052    
053            label = TapestryInternalUtils.defaultLabel(id, messages, name);
054    
055            // TAP5-2305
056            Sortable sortableAnnotation = conduit != null ? conduit.getAnnotation(Sortable.class) : null;
057            if (sortableAnnotation != null) 
058            {
059                sortable = sortableAnnotation.value();
060            }
061            else
062            {
063                // Primitive types need to be converted to wrapper types before checking to see
064                // if they are sortable.
065                Class wrapperType = PlasticUtils.toWrapperType(getPropertyType());
066                sortable = Comparable.class.isAssignableFrom(wrapperType);
067            }
068        }
069    
070        public String getId()
071        {
072            return id;
073        }
074    
075        public Class getPropertyType()
076        {
077            return conduit == null ? Object.class : conduit.getPropertyType();
078        }
079    
080        public PropertyConduit getConduit()
081        {
082            return conduit;
083        }
084    
085        public PropertyModel label(String label)
086        {
087            assert InternalUtils.isNonBlank(label);
088            this.label = label;
089    
090            return this;
091        }
092    
093        public String getLabel()
094        {
095            return label;
096        }
097    
098        public String getPropertyName()
099        {
100            return name;
101        }
102    
103        public BeanModel model()
104        {
105            return model;
106        }
107    
108        public PropertyModel dataType(String dataType)
109        {
110            this.dataType = dataType;
111    
112            return this;
113        }
114    
115        public String getDataType()
116        {
117            return dataType;
118        }
119    
120        public boolean isSortable()
121        {
122            return sortable;
123        }
124    
125        public PropertyModel sortable(boolean sortable)
126        {
127            this.sortable = sortable;
128    
129            return this;
130        }
131    
132        public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
133        {
134            return conduit == null ? null : conduit.getAnnotation(annotationClass);
135        }
136    }