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;
017    
018    import java.lang.annotation.Annotation;
019    import java.lang.reflect.Type;
020    import java.util.List;
021    import java.util.NoSuchElementException;
022    
023    /**
024     * A meta-property, defining those aspects of a property which are not specific
025     * to a particular bean, such as the property type and name.
026     * 
027     * @param <P>  the type of the property content
028     * @author Stephen Colebourne
029     */
030    public interface MetaProperty<P> extends BeanQuery<P> {
031    
032        /**
033         * Creates a property that binds this meta-property to a specific bean.
034         * 
035         * @param bean  the bean to create the property for, not null
036         * @return the property, not null
037         */
038        Property<P> createProperty(Bean bean);
039    
040        //-----------------------------------------------------------------------
041        /**
042         * Gets the meta-bean which owns this meta-property.
043         * <p>
044         * Each meta-property is fully owned by a single bean.
045         * 
046         * @return the meta-bean, not null
047         */
048        MetaBean metaBean();
049    
050        /**
051         * Gets the property name.
052         * <p>
053         * The JavaBean style methods getFoo() and setFoo() will lead to a property
054         * name of 'foo' and so on.
055         * 
056         * @return the name of the property, not empty
057         */
058        String name();
059    
060        /**
061         * Get the type that declares the property, represented as a {@code Class}.
062         * 
063         * @return the type declaring the property, not null
064         */
065        Class<?> declaringType();
066    
067        /**
068         * Get the type of the property represented as a {@code Class}.
069         * 
070         * @return the type of the property, not null
071         */
072        Class<P> propertyType();
073    
074        /**
075         * Gets the generic types of the property.
076         * <p>
077         * This provides access to the generic type declared in the source code.
078         * 
079         * @return the full generic type of the property, unmodifiable, not null
080         */
081        Type propertyGenericType();
082    
083        /**
084         * Gets whether the property is read-only, read-write or write-only.
085         * 
086         * @return the property read-write type, not null
087         */
088        PropertyReadWrite readWrite();
089    
090        //-----------------------------------------------------------------------
091        /**
092         * Gets the annotations of the property.
093         * 
094         * @return the annotations, unmodifiable, not null
095         */
096        List<Annotation> annotations();
097    
098        /**
099         * Gets a specified annotation of the property.
100         * 
101         * @return the annotation, not null
102         * @throws NoSuchElementException if the annotation is not specified
103         */
104        <A extends Annotation> A annotation(Class<A> annotation);
105    
106        //-----------------------------------------------------------------------
107        /**
108         * Gets the value of the property for the specified bean.
109         * <p>
110         * For a standard JavaBean, this is equivalent to calling <code>getFoo()</code> on the bean.
111         * Alternate implementations may perform any logic to obtain the value.
112         * 
113         * @param bean  the bean to query, not null
114         * @return the value of the property on the specified bean, may be null
115         * @throws ClassCastException if the bean is of an incorrect type
116         * @throws UnsupportedOperationException if the property is write-only
117         */
118        P get(Bean bean);
119    
120        /**
121         * Sets the value of the property on the specified bean.
122         * <p>
123         * The value must be of the correct type for the property.
124         * For a standard JavaBean, this is equivalent to calling <code>setFoo()</code> on the bean.
125         * Alternate implementations may perform any logic to change the value.
126         * 
127         * @param bean  the bean to update, not null
128         * @param value  the value to set into the property on the specified bean, may be null
129         * @throws ClassCastException if the bean is of an incorrect type
130         * @throws ClassCastException if the value is of an invalid type for the property
131         * @throws UnsupportedOperationException if the property is read-only
132         * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses)
133         */
134        void set(Bean bean, Object value);
135    
136        /**
137         * Sets the value of the property on the associated bean and returns the previous value.
138         * <p>
139         * The value must be of the correct type for the property.
140         * This is a combination of the {@code get} and {@code set} methods that matches the definition
141         * of {@code put} in a {@code Map}.
142         * 
143         * @param bean  the bean to update, not null
144         * @param value  the value to set into the property on the specified bean, may be null
145         * @return the old value of the property, may be null
146         * @throws ClassCastException if the bean is of an incorrect type
147         * @throws ClassCastException if the value is of an invalid type for the property
148         * @throws UnsupportedOperationException if the property is read-only
149         * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses)
150         */
151        P put(Bean bean, Object value);
152    
153        //-----------------------------------------------------------------------
154        /**
155         * Gets the value of the property for the specified bean converted to a string.
156         * <p>
157         * This converts the result of {@link #get(Bean)} to a standard format string.
158         * Conversion uses Joda-Convert.
159         * Not all object types can be converted to a string, see Joda-Convert.
160         * <p>
161         * For a standard JavaBean, this is equivalent to calling <code>getFoo()</code> on the bean.
162         * Alternate implementations may perform any logic to obtain the value.
163         * 
164         * @param bean  the bean to query, not null
165         * @return the value of the property on the specified bean, may be null
166         * @throws ClassCastException if the bean is of an incorrect type
167         * @throws UnsupportedOperationException if the property is write-only
168         * @throws RuntimeException if the value cannot be converted to a string (use appropriate subclasses)
169         */
170        String getString(Bean bean);
171    
172        /**
173         * Sets the value of the property on the specified bean from a string by conversion.
174         * <p>
175         * This converts the string to the correct type for the property and then sets it
176         * using {@link #set(Bean, Object)}. Conversion uses Joda-Convert.
177         * 
178         * @param bean  the bean to update, not null
179         * @param value  the value to set into the property on the specified bean, may be null
180         * @throws ClassCastException if the bean is of an incorrect type
181         * @throws ClassCastException if the value is of an invalid type for the property
182         * @throws UnsupportedOperationException if the property is read-only
183         * @throws RuntimeException if the value is rejected by the property (use appropriate subclasses)
184         */
185        void setString(Bean bean, String value);
186    
187        //-----------------------------------------------------------------------
188        /**
189         * Checks if this meta-property equals another.
190         * <p>
191         * This compares the property name and declaring type.
192         * It does not compare the property or bean types.
193         * 
194         * @param obj  the other meta-property, null returns false
195         * @return true if equal
196         */
197        @Override
198        boolean equals(Object obj);
199    
200        /**
201         * Returns a suitable hash code.
202         * 
203         * @return the hash code
204         */
205        @Override
206        int hashCode();
207    
208    }