001    /*
002     *  Copyright 2001-2013 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.beans.impl;
017    
018    import java.lang.annotation.Annotation;
019    import java.util.List;
020    import java.util.NoSuchElementException;
021    
022    import org.joda.beans.Bean;
023    import org.joda.beans.JodaBeanUtils;
024    import org.joda.beans.MetaProperty;
025    import org.joda.beans.Property;
026    
027    /**
028     * An abstract base meta-property.
029     * 
030     * @param <P>  the type of the property content
031     * @author Stephen Colebourne
032     */
033    public abstract class BasicMetaProperty<P> implements MetaProperty<P> {
034    
035        /** The name of the property. */
036        private final String name;
037    
038        /**
039         * Constructor.
040         * 
041         * @param propertyName  the property name, not empty
042         */
043        protected BasicMetaProperty(String propertyName) {
044            if (propertyName == null || propertyName.length() == 0) {
045                throw new NullPointerException("Property name must not be null or empty");
046            }
047            this.name = propertyName;
048        }
049    
050        //-----------------------------------------------------------------------
051        @Override
052        public Property<P> createProperty(Bean bean) {
053            return BasicProperty.of(bean, this);
054        }
055    
056        @Override
057        public String name() {
058            return name;
059        }
060    
061        //-----------------------------------------------------------------------
062        @Override
063        public P put(Bean bean, Object value) {
064            P old = get(bean);
065            set(bean, value);
066            return old;
067        }
068    
069        //-----------------------------------------------------------------------
070        @Override
071        public String getString(Bean bean) {
072            P value = get(bean);
073            return JodaBeanUtils.stringConverter().convertToString(propertyType(), value);
074        }
075    
076        @Override
077        public void setString(Bean bean, String value) {
078            set(bean, JodaBeanUtils.stringConverter().convertFromString(propertyType(), value));
079        }
080    
081        //-----------------------------------------------------------------------
082        @SuppressWarnings("unchecked")
083        @Override
084        public <A extends Annotation> A annotation(Class<A> annotationClass) {
085            List<Annotation> annotations = annotations();
086            for (Annotation annotation : annotations) {
087                if (annotationClass.isInstance(annotation)) {
088                    return (A) annotation;
089                }
090            }
091            throw new NoSuchElementException("Unknown annotation: " + annotationClass.getName());
092        }
093    
094        //-----------------------------------------------------------------------
095        @Override
096        public boolean equals(Object obj) {
097            if (obj instanceof MetaProperty<?>) {
098                MetaProperty<?> other = (MetaProperty<?>) obj;
099                return name().equals(other.name()) && declaringType().equals(other.declaringType());
100            }
101            return false;
102        }
103    
104        @Override
105        public int hashCode() {
106            return name().hashCode() ^ declaringType().hashCode();
107        }
108    
109        /**
110         * Returns a string that summarises the meta-property.
111         * 
112         * @return a summary string, not null
113         */
114        @Override
115        public String toString() {
116            return declaringType().getSimpleName() + ":" + name();
117        }
118    
119    }