001 /*
002 * Created on Nov 23, 2009
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. 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 distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 *
014 * Copyright @2009 the original author or authors.
015 */
016 package org.fest.reflect.beanproperty;
017
018 import static org.fest.reflect.beanproperty.PropertyType.newPropertyType;
019 import static org.fest.reflect.beanproperty.PropertyTypeRef.newPropertyTypeRef;
020 import static org.fest.util.Strings.isEmpty;
021
022 import org.fest.reflect.reference.TypeRef;
023
024
025 /**
026 * Understands the name of a property to access using Bean Introspection.
027 * <p>
028 * The following is an example of proper usage of this class:
029 * <pre>
030 * // Retrieves the value of the property "name"
031 * String name = {@link org.fest.reflect.core.Reflection#property(String) property}("name").{@link PropertyName#ofType(Class) ofType}(String.class).{@link PropertyType#in(Object) in}(person).{@link Invoker#get() get}();
032 *
033 * // Sets the value of the property "name" to "Yoda"
034 * {@link org.fest.reflect.core.Reflection#property(String) property}("name").{@link PropertyName#ofType(Class) ofType}(String.class).{@link PropertyType#in(Object) in}(person).{@link Invoker#set(Object) set}("Yoda");
035 *
036 * // Retrieves the value of the property "powers"
037 * List<String> powers = {@link org.fest.reflect.core.Reflection#property(String) property}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link PropertyTypeRef#in(Object) in}(jedi).{@link Invoker#get() get}();
038 *
039 * // Sets the value of the property "powers"
040 * List<String> powers = new ArrayList<String>();
041 * powers.add("heal");
042 * {@link org.fest.reflect.core.Reflection#property(String) property}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link PropertyTypeRef#in(Object) in}(jedi).{@link Invoker#set(Object) set}(powers);
043 * </pre>
044 * </p>
045 *
046 * @author Alex Ruiz
047 *
048 * @since 1.2
049 */
050 public final class PropertyName {
051
052 /**
053 * Creates a new <code>{@link PropertyName}</code>: the starting point of the fluent interface for accessing
054 * properties using Bean Introspection.
055 * @param name the name of the property to access using Bean Introspection.
056 * @return the created <code>PropertyName</code>.
057 * @throws NullPointerException if the given name is <code>null</code>.
058 * @throws IllegalArgumentException if the given name is empty.
059 */
060 public static PropertyName startPropertyAccess(String name) {
061 validateIsNotNullOrEmpty(name);
062 return new PropertyName(name);
063 }
064
065 private static void validateIsNotNullOrEmpty(String name) {
066 if (name == null)
067 throw new NullPointerException("The name of the property to access should not be null");
068 if (isEmpty(name))
069 throw new IllegalArgumentException("The name of the property to access should not be empty");
070 }
071
072 private final String name;
073
074 private PropertyName(String name) {
075 this.name = name;
076 }
077
078 /**
079 * Sets the type of the property to access.
080 * @param <T> the generic type of the property type.
081 * @param type the type of the property to access.
082 * @return a recipient for the property type.
083 * @throws NullPointerException if the given type is <code>null</code>.
084 */
085 public <T> PropertyType<T> ofType(Class<T> type) {
086 return newPropertyType(name, type);
087 }
088
089 /**
090 * Sets the type reference of the property to access. This method reduces casting when the type of the property to
091 * access uses generics.
092 * <p>
093 * For example:
094 * <pre>
095 * List<String> powers = {@link org.fest.reflect.core.Reflection#property(String) property}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link PropertyTypeRef#in(Object) in}(jedi).{@link Invoker#get() get}();
096 * </pre>
097 * </p>
098 * @param <T> the generic type of the property type.
099 * @param type the type of the property to access.
100 * @return a recipient for the property type.
101 * @throws NullPointerException if the given type reference is <code>null</code>.
102 */
103 public <T> PropertyTypeRef<T> ofType(TypeRef<T> type) {
104 return newPropertyTypeRef(name, type);
105 }
106 }