001    /*
002     * Created on Oct 31, 2006
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * 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 is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2006-2009 the original author or authors.
014     */
015    package org.fest.reflect.core;
016    
017    import static org.fest.reflect.beanproperty.PropertyName.startPropertyAccess;
018    import static org.fest.reflect.constructor.TargetType.startConstructorAccess;
019    import static org.fest.reflect.field.FieldName.beginFieldAccess;
020    import static org.fest.reflect.field.StaticFieldName.beginStaticFieldAccess;
021    import static org.fest.reflect.innerclass.StaticInnerClassName.startStaticInnerClassAccess;
022    import static org.fest.reflect.method.MethodName.startMethodAccess;
023    import static org.fest.reflect.method.StaticMethodName.startStaticMethodAccess;
024    import static org.fest.reflect.type.Type.newType;
025    
026    import org.fest.reflect.beanproperty.PropertyName;
027    import org.fest.reflect.beanproperty.PropertyType;
028    import org.fest.reflect.constructor.TargetType;
029    import org.fest.reflect.field.FieldName;
030    import org.fest.reflect.field.FieldTypeRef;
031    import org.fest.reflect.field.StaticFieldName;
032    import org.fest.reflect.field.StaticFieldType;
033    import org.fest.reflect.field.StaticFieldTypeRef;
034    import org.fest.reflect.innerclass.StaticInnerClassName;
035    import org.fest.reflect.method.Invoker;
036    import org.fest.reflect.method.MethodName;
037    import org.fest.reflect.method.MethodReturnTypeRef;
038    import org.fest.reflect.method.StaticMethodName;
039    import org.fest.reflect.method.StaticMethodReturnTypeRef;
040    import org.fest.reflect.reference.TypeRef;
041    import org.fest.reflect.type.Type;
042    
043    /**
044     * Understands the entry point for the classes in this package.
045     * The following is an example of proper usage of the classes in this package:
046     * <pre>
047     *   // Loads the class 'org.republic.Jedi'
048     *   Class&lt;?&gt; jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#load() load}();
049     *
050     *   // Loads the class 'org.republic.Jedi' as 'org.republic.Person' (Jedi extends Person)
051     *   Class&lt;Person&gt; jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#loadAs(Class) loadAs}(Person.class);
052     *
053     *   // Loads the class 'org.republic.Jedi' using a custom class loader
054     *   Class&lt;?&gt; jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link org.fest.reflect.type.TypeLoader#load() load}();
055     *
056     *   // Gets the inner class 'Master' in the declaring class 'Jedi':
057     *   Class&lt;?&gt; masterClass = {@link org.fest.reflect.core.Reflection#staticInnerClass(String) staticInnerClass}("Master").{@link org.fest.reflect.innerclass.StaticInnerClassName#in(Class) in}(Jedi.class).{@link org.fest.reflect.innerclass.Invoker#get() get}();
058     *
059     *   // Equivalent to call 'new Person()'
060     *   Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#in in}(Person.class).{@link org.fest.reflect.constructor.Invoker#newInstance(Object...) newInstance}();
061     *
062     *   // Equivalent to call 'new Person("Yoda")'
063     *   Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#withParameterTypes(Class...) withParameterTypes}(String.class).{@link org.fest.reflect.constructor.ParameterTypes#in(Class) in}(Person.class).{@link org.fest.reflect.constructor.Invoker#newInstance(Object...) newInstance}("Yoda");
064     *
065     *   // Retrieves the value of the field "name"
066     *   String name = {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link org.fest.reflect.field.FieldName#ofType(Class) ofType}(String.class).{@link org.fest.reflect.field.FieldType#in(Object) in}(person).{@link org.fest.reflect.field.Invoker#get() get}();
067     *
068     *   // Sets the value of the field "name" to "Yoda"
069     *   {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link org.fest.reflect.field.FieldName#ofType(Class) ofType}(String.class).{@link org.fest.reflect.field.FieldType#in(Object) in}(person).{@link org.fest.reflect.field.Invoker#set(Object) set}("Yoda");
070     *
071     *   // Retrieves the value of the field "powers"
072     *   List&lt;String&gt; powers = {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link FieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}&lt;List&lt;String&gt;&gt;() {}).{@link FieldTypeRef#in(Object) in}(jedi).{@link org.fest.reflect.field.Invoker#get() get}();
073     *
074     *   // Equivalent to call 'person.setName("Luke")'
075     *   {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link org.fest.reflect.method.MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
076     *                    .{@link org.fest.reflect.method.MethodParameterTypes#in(Object) in}(person)
077     *                    .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Luke");
078     *
079     *   // Equivalent to call 'jedi.getPowers()'
080     *   List&lt;String&gt; powers = {@link org.fest.reflect.core.Reflection#method(String) method}("getPowers").{@link MethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}&lt;List&lt;String&gt;&gt;() {})
081     *                                            .{@link MethodReturnTypeRef#in(Object) in}(person)
082     *                                            .{@link Invoker#invoke(Object...) invoke}();
083     *
084     *   // Retrieves the value of the static field "count" in Person.class
085     *   int count = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("count").{@link StaticFieldName#ofType(Class) ofType}(int.class).{@link StaticFieldType#in(Class) in}(Person.class).{@link org.fest.reflect.field.Invoker#get() get}();
086     *
087     *   // Sets the value of the static field "count" to 3 in Person.class
088     *   {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("count").{@link StaticFieldName#ofType(Class) ofType}(int.class).{@link StaticFieldType#in(Class) in}(Person.class).{@link org.fest.reflect.field.Invoker#set(Object) set}(3);
089     *
090     *   // Retrieves the value of the static field "commonPowers" in Jedi.class
091     *   List&lt;String&gt; commmonPowers = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link StaticFieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}&lt;List&lt;String&gt;&gt;() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link org.fest.reflect.field.Invoker#get() get}();
092     *
093     *   // Equivalent to call 'person.concentrate()'
094     *   {@link org.fest.reflect.core.Reflection#method(String) method}("concentrate").{@link org.fest.reflect.method.MethodName#in(Object) in}(person).{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
095     *
096     *   // Equivalent to call 'person.getName()'
097     *   String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link org.fest.reflect.method.MethodName#withReturnType(Class) withReturnType}(String.class)
098     *                                  .{@link org.fest.reflect.method.MethodReturnType#in(Object) in}(person)
099     *                                  .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
100     *
101     *   // Equivalent to call 'Jedi.setCommonPower("Jump")'
102     *   {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link org.fest.reflect.method.StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
103     *                                 .{@link org.fest.reflect.method.StaticMethodParameterTypes#in(Class) in}(Jedi.class)
104     *                                 .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Jump");
105     *
106     *   // Equivalent to call 'Jedi.addPadawan()'
107     *   {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("addPadawan").{@link org.fest.reflect.method.StaticMethodName#in(Class) in}(Jedi.class).{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
108     *
109     *   // Equivalent to call 'Jedi.commonPowerCount()'
110     *   String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link org.fest.reflect.method.StaticMethodName#withReturnType(Class) withReturnType}(String.class)
111     *                                                 .{@link org.fest.reflect.method.StaticMethodReturnType#in(Class) in}(Jedi.class)
112     *                                                 .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
113     *
114     *   // Equivalent to call 'Jedi.getCommonPowers()'
115     *   List&lt;String&gt; powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}&lt;List&lt;String&gt;&gt;() {})
116     *                                                        .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
117     *                                                        .{@link Invoker#invoke(Object...) invoke}();
118     *
119     *   // Retrieves the value of the property "name"
120     *   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 org.fest.reflect.beanproperty.Invoker#get() get}();
121     *
122     *   // Sets the value of the property "name" to "Yoda"
123     *   {@link org.fest.reflect.core.Reflection#property(String) property}("name").{@link PropertyName#ofType(Class) ofType}(String.class).{@link PropertyType#in(Object) in}(person).{@link org.fest.reflect.beanproperty.Invoker#set(Object) set}("Yoda");
124     * </pre>
125     * </p>
126     *
127     * @author Alex Ruiz
128     * @author Yvonne Wang
129     */
130    public final class Reflection {
131    
132      /**
133       * Starting point of the fluent interface for loading a class dynamically.
134       * @param name the name of the class to load.
135       * @return the starting point of the method chain.
136       * @throws NullPointerException if the given name is <code>null</code>.
137       * @throws IllegalArgumentException if the given name is empty.
138       * @since 1.1
139       */
140      public static Type type(String name) { return newType(name); }
141    
142      /**
143       * Starting point of the fluent interface for accessing static inner class via reflection.
144       * @param name the name of the static inner class to access.
145       * @return the starting point of the method chain.
146       * @throws NullPointerException if the given name is <code>null</code>.
147       * @throws IllegalArgumentException if the given name is empty.
148       * @since 1.1
149       */
150      public static StaticInnerClassName staticInnerClass(String name) { return startStaticInnerClassAccess(name); }
151    
152      /**
153       * Starting point of the fluent interface for accessing fields via reflection.
154       * @param name the name of the field to access.
155       * @return the starting point of the method chain.
156       * @throws NullPointerException if the given name is <code>null</code>.
157       * @throws IllegalArgumentException if the given name is empty.
158       */
159      public static FieldName field(String name) { return beginFieldAccess(name); }
160    
161      /**
162       * Starting point of the fluent interface for accessing static fields via reflection.
163       * @param name the name of the static field to access.
164       * @return the starting point of the method chain.
165       * @throws NullPointerException if the given name is <code>null</code>.
166       * @throws IllegalArgumentException if the given name is empty.
167       */
168      public static StaticFieldName staticField(String name) { return beginStaticFieldAccess(name); }
169    
170      /**
171       * Starting point of the fluent interface for invoking methods via reflection.
172       * @param name the name of the method to invoke.
173       * @return the starting point of the method chain.
174       * @throws NullPointerException if the given name is <code>null</code>.
175       * @throws IllegalArgumentException if the given name is empty.
176       */
177      public static MethodName method(String name) { return startMethodAccess(name); }
178    
179      /**
180       * Starting point of the fluent interface for invoking static methods via reflection.
181       * @param name the name of the static method to invoke.
182       * @return the starting point of the static method chain.
183       * @throws NullPointerException if the given name is <code>null</code>.
184       * @throws IllegalArgumentException if the given name is empty.
185       */
186      public static StaticMethodName staticMethod(String name) { return startStaticMethodAccess(name); }
187    
188      /**
189       * Starting point of the fluent interface for invoking constructors via reflection.
190       * @return the starting point of the method chain.
191       */
192      public static TargetType constructor() { return startConstructorAccess(); }
193    
194      /**
195       * Starting point of the fluent interface for accessing properties via Bean Introspection.
196       * @param name the name of the property to access.
197       * @return the starting point of the method chain.
198       * @throws NullPointerException if the given name is <code>null</code>.
199       * @throws IllegalArgumentException if the given name is empty.
200       * @since 1.2
201       */
202      public static PropertyName property(String name) { return startPropertyAccess(name); }
203    
204      private Reflection() {}
205    }