[fest-reflect] 01/02: Imported Upstream version 1.4.1
Andreas Tille
tille at debian.org
Sun Apr 26 05:45:47 UTC 2015
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository fest-reflect.
commit 55147ad358df486d7c16a33aa69cf22561652db1
Author: Andreas Tille <tille at debian.org>
Date: Sun Apr 26 07:35:15 2015 +0200
Imported Upstream version 1.4.1
---
.gitignore | 5 +
LICENSE.txt | 202 +++++++++++
pom.xml | 62 ++++
.../org/fest/reflect/beanproperty/Invoker.java | 140 ++++++++
.../fest/reflect/beanproperty/PropertyName.java | 104 ++++++
.../fest/reflect/beanproperty/PropertyType.java | 67 ++++
.../fest/reflect/beanproperty/PropertyTypeRef.java | 69 ++++
.../org/fest/reflect/beanproperty/package.html | 41 +++
.../java/org/fest/reflect/constructor/Invoker.java | 95 ++++++
.../fest/reflect/constructor/ParameterTypes.java | 58 ++++
.../org/fest/reflect/constructor/TargetType.java | 69 ++++
.../java/org/fest/reflect/constructor/package.html | 41 +++
.../java/org/fest/reflect/core/Reflection.java | 260 +++++++++++++++
src/main/java/org/fest/reflect/core/package.html | 78 +++++
.../fest/reflect/exception/ReflectionError.java | 42 +++
.../java/org/fest/reflect/exception/package.html | 24 ++
.../org/fest/reflect/field/DecoratedInvoker.java | 146 ++++++++
.../java/org/fest/reflect/field/FieldName.java | 111 +++++++
.../java/org/fest/reflect/field/FieldType.java | 77 +++++
.../java/org/fest/reflect/field/FieldTypeRef.java | 80 +++++
src/main/java/org/fest/reflect/field/Invoker.java | 302 +++++++++++++++++
.../org/fest/reflect/field/StaticFieldName.java | 102 ++++++
.../org/fest/reflect/field/StaticFieldType.java | 64 ++++
.../org/fest/reflect/field/StaticFieldTypeRef.java | 69 ++++
.../decorator/DecoratorInvocationHandler.java | 82 +++++
.../reflect/field/decorator/PostDecorator.java | 48 +++
.../fest/reflect/field/decorator/PreDecorator.java | 47 +++
.../field/decorator/RuntimeExceptionShield.java | 61 ++++
src/main/java/org/fest/reflect/field/package.html | 47 +++
.../java/org/fest/reflect/innerclass/Invoker.java | 59 ++++
.../reflect/innerclass/StaticInnerClassName.java | 81 +++++
.../java/org/fest/reflect/innerclass/package.html | 37 +++
src/main/java/org/fest/reflect/method/Invoker.java | 134 ++++++++
.../java/org/fest/reflect/method/MethodName.java | 125 +++++++
.../fest/reflect/method/MethodParameterTypes.java | 70 ++++
.../org/fest/reflect/method/MethodReturnType.java | 79 +++++
.../fest/reflect/method/MethodReturnTypeRef.java | 74 +++++
.../org/fest/reflect/method/StaticMethodName.java | 123 +++++++
.../reflect/method/StaticMethodParameterTypes.java | 76 +++++
.../reflect/method/StaticMethodReturnType.java | 85 +++++
.../reflect/method/StaticMethodReturnTypeRef.java | 75 +++++
src/main/java/org/fest/reflect/method/package.html | 61 ++++
.../java/org/fest/reflect/reference/TypeRef.java | 54 +++
.../java/org/fest/reflect/reference/package.html | 25 ++
src/main/java/org/fest/reflect/type/Type.java | 113 +++++++
.../java/org/fest/reflect/type/TypeLoader.java | 99 ++++++
src/main/java/org/fest/reflect/type/package.html | 37 +++
.../java/org/fest/reflect/util/Accessibles.java | 76 +++++
.../java/org/fest/reflect/util/Throwables.java | 41 +++
src/main/java/org/fest/reflect/util/package.html | 24 ++
src/main/javadoc/overview.html | 17 +
src/site/changes.xml | 109 ++++++
src/site/resources/images/fest-reflect.png | Bin 0 -> 24936 bytes
src/site/site.vm | 369 +++++++++++++++++++++
src/site/site.xml | 25 ++
src/site/xdoc/index.xml | 14 +
src/test/java/org/fest/reflect/Jedi.java | 114 +++++++
src/test/java/org/fest/reflect/Person.java | 57 ++++
.../fest/reflect/beanproperty/Property_Test.java | 165 +++++++++
.../fest/reflect/constructor/Constructor_Test.java | 107 ++++++
.../core/FEST68_CatchingWrongExceptions_Test.java | 60 ++++
.../org/fest/reflect/core/Reflection_Test.java | 81 +++++
.../reflect/field/FieldDecoratorCombinedTest.java | 145 ++++++++
.../field/FieldDecoratorIgnoreExceptionTest.java | 204 ++++++++++++
...FieldDecoratorReturningDecoratorResultTest.java | 214 ++++++++++++
.../org/fest/reflect/field/FieldDecoratorTest.java | 184 ++++++++++
.../org/fest/reflect/field/Field_field_Test.java | 157 +++++++++
.../fest/reflect/field/Field_staticField_Test.java | 151 +++++++++
.../org/fest/reflect/field/NestedFieldTest.java | 197 +++++++++++
.../decorator/TestRuntimeExceptionShield.java | 79 +++++
.../org/fest/reflect/innerclass/OuterClass.java | 42 +++
.../reflect/innerclass/StaticInnerClass_Test.java | 84 +++++
.../fest/reflect/method/Method_method_Test.java | 208 ++++++++++++
.../reflect/method/Method_staticMethod_Test.java | 174 ++++++++++
src/test/java/org/fest/reflect/type/Type_Test.java | 120 +++++++
.../org/fest/reflect/util/ExpectedFailures.java | 42 +++
76 files changed, 7260 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ecd131a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+/bin
+/target
+.settings
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4cbbad2
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-reflect</artifactId>
+ <version>1.4.1</version>
+ <name>FEST Reflection</name>
+ <description>Fluent Interface that simplifies usage of Java Reflection</description>
+ <inceptionYear>2007</inceptionYear>
+ <url>http://fest.easytesting.org/reflect</url>
+ <parent>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest</artifactId>
+ <version>1.0.15</version>
+ </parent>
+ <mailingLists>
+ <mailingList>
+ <name>Easy Testing Group</name>
+ <post>http://groups.google.com/group/easytesting</post>
+ <subscribe>http://groups.google.com/group/easytesting</subscribe>
+ <unsubscribe>http://groups.google.com/group/easytesting</unsubscribe>
+ </mailingList>
+ </mailingLists>
+ <scm>
+ <developerConnection>scm:git:git at github.com:alexruiz/fest-reflect.git</developerConnection>
+ <connection>scm:git:git://github.com/alexruiz/fest-reflect.git</connection>
+ <url>https://github.com/alexruiz/fest-reflect</url>
+ </scm>
+ <issueManagement>
+ <system>JIRA</system>
+ <url>http://jira.codehaus.org/browse/FEST</url>
+ </issueManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-util</artifactId>
+ <version>1.2.4</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-test</artifactId>
+ <version>1.2</version>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ <version>1.9.0</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/src/main/java/org/fest/reflect/beanproperty/Invoker.java b/src/main/java/org/fest/reflect/beanproperty/Invoker.java
new file mode 100644
index 0000000..1039418
--- /dev/null
+++ b/src/main/java/org/fest/reflect/beanproperty/Invoker.java
@@ -0,0 +1,140 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.beanproperty;
+
+import static org.fest.util.Strings.concat;
+import static org.fest.util.Strings.quote;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.field.StaticFieldName;
+import org.fest.reflect.field.StaticFieldType;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the use of instrospection to access a property from a JavaBean.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the property "name"
+ * 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}();
+ *
+ * // Sets the value of the property "name" to "Yoda"
+ * {@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");
+ *
+ * // Retrieves the value of the static property "count"
+ * 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 Invoker#get() get}();
+ *
+ * // Sets the value of the static property "count" to 3
+ * {@link org.fest.reflect.core.Reflection#staticField(String) property}("count").{@link StaticFieldName#ofType(Class) ofType}(int.class).{@link StaticFieldType#in(Class) in}(Person.class).{@link Invoker#set(Object) set}(3);
+ * </pre>
+ * </p>
+ *
+ * @param <T> the declared type for the property to access.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.2
+ */
+public final class Invoker<T> {
+
+ static <T> Invoker<T> newInvoker(String name, TypeRef<T> expectedType, Object target) {
+ return createInvoker(name, expectedType.rawType(), target);
+ }
+
+ static <T> Invoker<T> newInvoker(String name, Class<T> expectedType, Object target) {
+ return createInvoker(name, expectedType, target);
+ }
+
+ private static <T> Invoker<T> createInvoker(String name, Class<?> expectedType, Object target) {
+ PropertyDescriptor descriptor = descriptorForProperty(name, target);
+ verifyCorrectType(name, target, expectedType, descriptor);
+ return new Invoker<T>(name, target, descriptor);
+ }
+
+ private static PropertyDescriptor descriptorForProperty(String propertyName, Object target) {
+ BeanInfo beanInfo = null;
+ Class<?> type = target.getClass();
+ try {
+ beanInfo = Introspector.getBeanInfo(type);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to get BeanInfo for type ", type.getName()), e);
+ }
+ for (PropertyDescriptor d : beanInfo.getPropertyDescriptors())
+ if (propertyName.equals(d.getName())) return d;
+ throw new ReflectionError(concat("Unable to find property ", quote(propertyName), " in ", type.getName()));
+ }
+
+ static void verifyCorrectType(String name, Object target, Class<?> expectedType, PropertyDescriptor descriptor) {
+ Class<?> actualType = descriptor.getPropertyType();
+ if (!expectedType.isAssignableFrom(actualType)) throw incorrectPropertyType(name, target, actualType, expectedType);
+ }
+
+ private static ReflectionError incorrectPropertyType(String name, Object target, Class<?> actual, Class<?> expected) {
+ String typeName = target.getClass().getName();
+ String msg = concat("The type of the property ", quote(name), " in ", typeName, " should be <", expected.getName(),
+ "> but was <", actual.getName(), ">");
+ throw new ReflectionError(msg);
+ }
+
+ private final String propertyName;
+ private final Object target;
+ private final PropertyDescriptor descriptor;
+
+ private Invoker(String propertyName, Object target, PropertyDescriptor descriptor) {
+ this.propertyName = propertyName;
+ this.target = target;
+ this.descriptor = descriptor;
+ }
+
+ /**
+ * Sets a value in the property managed by this class.
+ * @param value the value to set.
+ * @throws ReflectionError if the given value cannot be set.
+ */
+ public void set(T value) {
+ try {
+ descriptor.getWriteMethod().invoke(target, value);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to update the value in property ", quote(propertyName)), e);
+ }
+ }
+
+ /**
+ * Returns the value of the property managed by this class.
+ * @return the value of the property managed by this class.
+ * @throws ReflectionError if the value of the property cannot be retrieved.
+ */
+ @SuppressWarnings("unchecked")
+ public T get() {
+ try {
+ return (T) descriptor.getReadMethod().invoke(target);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to obtain the value in property " + quote(propertyName)), e);
+ }
+ }
+
+ /**
+ * Returns the "real" property managed by this class.
+ * @return the "real" property managed by this class.
+ */
+ public PropertyDescriptor info() {
+ return descriptor;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/beanproperty/PropertyName.java b/src/main/java/org/fest/reflect/beanproperty/PropertyName.java
new file mode 100644
index 0000000..483eca5
--- /dev/null
+++ b/src/main/java/org/fest/reflect/beanproperty/PropertyName.java
@@ -0,0 +1,104 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.beanproperty;
+
+import static org.fest.reflect.beanproperty.PropertyType.newPropertyType;
+import static org.fest.reflect.beanproperty.PropertyTypeRef.newPropertyTypeRef;
+import static org.fest.util.Strings.isEmpty;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the name of a property to access using Bean Introspection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the property "name"
+ * 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}();
+ *
+ * // Sets the value of the property "name" to "Yoda"
+ * {@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");
+ *
+ * // Retrieves the value of the property "powers"
+ * 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}();
+ *
+ * // Sets the value of the property "powers"
+ * List<String> powers = new ArrayList<String>();
+ * powers.add("heal");
+ * {@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);
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.2
+ */
+public final class PropertyName {
+
+ /**
+ * Creates a new <code>{@link PropertyName}</code>: the starting point of the fluent interface for accessing properties using
+ * Bean Introspection.
+ * @param name the name of the property to access using Bean Introspection.
+ * @return the created <code>PropertyName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static PropertyName startPropertyAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new PropertyName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the property to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the property to access should not be empty");
+ }
+
+ private final String name;
+
+ private PropertyName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the type of the property to access.
+ * @param <T> the generic type of the property type.
+ * @param type the type of the property to access.
+ * @return a recipient for the property type.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ */
+ public <T> PropertyType<T> ofType(Class<T> type) {
+ return newPropertyType(name, type);
+ }
+
+ /**
+ * Sets the type reference of the property to access. This method reduces casting when the type of the property to access uses
+ * generics.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * 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}();
+ * </pre>
+ * </p>
+ * @param <T> the generic type of the property type.
+ * @param type the type of the property to access.
+ * @return a recipient for the property type.
+ * @throws NullPointerException if the given type reference is <code>null</code>.
+ */
+ public <T> PropertyTypeRef<T> ofType(TypeRef<T> type) {
+ return newPropertyTypeRef(name, type);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/beanproperty/PropertyType.java b/src/main/java/org/fest/reflect/beanproperty/PropertyType.java
new file mode 100644
index 0000000..91a0ed7
--- /dev/null
+++ b/src/main/java/org/fest/reflect/beanproperty/PropertyType.java
@@ -0,0 +1,67 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.beanproperty;
+
+import static org.fest.reflect.beanproperty.Invoker.newInvoker;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands the type of a property to access using Bean Instrospection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the property "name"
+ * 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}();
+ *
+ * // Sets the value of the property "name" to "Yoda"
+ * {@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");
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the property.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.2
+ */
+public class PropertyType<T> {
+
+ static <T> PropertyType<T> newPropertyType(String name, Class<T> type) {
+ if (type == null) throw new NullPointerException("The type of the property to access should not be null");
+ return new PropertyType<T>(name, type);
+ }
+
+ private final String name;
+ private final Class<T> type;
+
+ private PropertyType(String name, Class<T> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Returns a new property invoker. A property invoker is capable of accessing (read/write) the underlying property.
+ * @param target the object containing the property of interest.
+ * @return the created property invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a property with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Object target) {
+ if (target == null) throw new NullPointerException("Target should not be null");
+ return newInvoker(name, type, target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/beanproperty/PropertyTypeRef.java b/src/main/java/org/fest/reflect/beanproperty/PropertyTypeRef.java
new file mode 100644
index 0000000..becd81c
--- /dev/null
+++ b/src/main/java/org/fest/reflect/beanproperty/PropertyTypeRef.java
@@ -0,0 +1,69 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.beanproperty;
+
+import static org.fest.reflect.beanproperty.Invoker.newInvoker;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the type of a property to access using Bean Instrospection. This implementation supports Java generics.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the property "powers"
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#property(String) property}("powers").{@link PropertyName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link #in(Object) in}(jedi).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the property "powers"
+ * List<String> powers = new ArrayList<String>();
+ * powers.add("heal");
+ * {@link org.fest.reflect.core.Reflection#property(String) property}("powers").{@link PropertyName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link #in(Object) in}(jedi).{@link Invoker#set(Object) set}(powers);
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the property.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.2
+ */
+public class PropertyTypeRef<T> {
+
+ static <T> PropertyTypeRef<T> newPropertyTypeRef(String name, TypeRef<T> type) {
+ if (type == null) throw new NullPointerException("The type reference of the property to access should not be null");
+ return new PropertyTypeRef<T>(name, type);
+ }
+
+ private final TypeRef<T> type;
+ private final String name;
+
+ private PropertyTypeRef(String name, TypeRef<T> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Returns a new property invoker. A property invoker is capable of accessing (read/write) the underlying property.
+ * @param target the object containing the property of interest.
+ * @return the created property invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a property with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Object target) {
+ return newInvoker(name, type, target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/beanproperty/package.html b/src/main/java/org/fest/reflect/beanproperty/package.html
new file mode 100644
index 0000000..e3ac600
--- /dev/null
+++ b/src/main/java/org/fest/reflect/beanproperty/package.html
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API
+for property access via the Bean Instrospection API.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Retrieves the value of the property "name"
+ String name = {@link org.fest.reflect.core.Reflection#property(String) property}("name").{@link org.fest.reflect.beanproperty.PropertyName#ofType(Class) ofType}(String.class).{@link org.fest.reflect.beanproperty.PropertyType#in(Object) in}(person).{@link org.fest.reflect.beanproperty.Invoker#get() get}();
+
+ // Sets the value of the property "name" to "Yoda"
+ {@link org.fest.reflect.core.Reflection#property(String) property}("name").{@link org.fest.reflect.beanproperty.PropertyName#ofType(Class) ofType}(String.class).{@link org.fest.reflect.beanproperty.PropertyType#in(Object) in}(person).{@link org.fest.reflect.beanproperty.Invoker#set(Object) set}("Yoda");
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/constructor/Invoker.java b/src/main/java/org/fest/reflect/constructor/Invoker.java
new file mode 100644
index 0000000..d4e56bf
--- /dev/null
+++ b/src/main/java/org/fest/reflect/constructor/Invoker.java
@@ -0,0 +1,95 @@
+/*
+ * Created on Oct 31, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.constructor;
+
+import static org.fest.reflect.util.Accessibles.makeAccessible;
+import static org.fest.reflect.util.Accessibles.setAccessibleIgnoringExceptions;
+import static org.fest.reflect.util.Throwables.targetOf;
+import static org.fest.util.Strings.concat;
+
+import java.lang.reflect.Constructor;
+import java.util.Arrays;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands the invocation of a constructor via Java Reflection.
+ * @param <T> the class in which the constructor is declared.
+ * <p>
+ * The following is an example of proper usage of the classes in this package:
+ *
+ * <pre>
+ * // Equivalent to call 'new Person()'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#in in}(Person.class).{@link #newInstance newInstance}();
+ *
+ * // Equivalent to call 'new Person("Yoda")'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#withParameterTypes(Class...) withParameterTypes}(String.class).{@link ParameterTypes#in(Class) in}(Person.class).{@link #newInstance newInstance}("Yoda");
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ */
+public final class Invoker<T> {
+
+ public static <T> Invoker<T> newInvoker(Class<T> target, Class<?>... parameterTypes) {
+ Constructor<T> constructor = constructor(target, parameterTypes);
+ return new Invoker<T>(constructor);
+ }
+
+ private static <T> Constructor<T> constructor(Class<T> target, Class<?>... parameterTypes) {
+ try {
+ return target.getDeclaredConstructor(parameterTypes);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to find constructor in type ", target.getName(), " with parameter types ",
+ Arrays.toString(parameterTypes)), e);
+ }
+ }
+
+ private final Constructor<T> constructor;
+
+ private Invoker(Constructor<T> constructor) {
+ this.constructor = constructor;
+ }
+
+ /**
+ * Creates a new instance of <code>T</code> by calling a constructor with the given arguments.
+ * @param args the arguments to pass to the constructor (can be zero or more).
+ * @return the created instance of <code>T</code>.
+ * @throws ReflectionError if a new instance cannot be created.
+ */
+ public T newInstance(Object... args) {
+ boolean accessible = constructor.isAccessible();
+ try {
+ makeAccessible(constructor);
+ T newInstance = constructor.newInstance(args);
+ return newInstance;
+ } catch (Throwable t) {
+ Throwable cause = targetOf(t);
+ if (cause instanceof RuntimeException) throw (RuntimeException) cause;
+ throw new ReflectionError("Unable to create a new object from the enclosed constructor", cause);
+ } finally {
+ setAccessibleIgnoringExceptions(constructor, accessible);
+ }
+ }
+
+ /**
+ * Returns the "real" constructor managed by this class.
+ * @return the "real" constructor managed by this class.
+ */
+ public Constructor<T> info() {
+ return constructor;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/constructor/ParameterTypes.java b/src/main/java/org/fest/reflect/constructor/ParameterTypes.java
new file mode 100644
index 0000000..7b77c15
--- /dev/null
+++ b/src/main/java/org/fest/reflect/constructor/ParameterTypes.java
@@ -0,0 +1,58 @@
+/*
+ * Created on Aug 17, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.constructor;
+
+import static org.fest.reflect.constructor.Invoker.newInvoker;
+
+/**
+ * Understands the parameter types for the constructor to invoke.
+ * <p>
+ * The following is an example of proper usage of the classes in this package:
+ *
+ * <pre>
+ * // Equivalent to call 'new Person()'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#in in}(Person.class).{@link Invoker#newInstance newInstance}();
+ *
+ * // Equivalent to call 'new Person("Yoda")'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#withParameterTypes(Class...) withParameterTypes}(String.class).{@link ParameterTypes#in(Class) in}(Person.class).{@link Invoker#newInstance newInstance}("Yoda");
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ */
+public final class ParameterTypes {
+
+ static ParameterTypes newParameterTypes(Class<?>[] parameterTypes) {
+ if (parameterTypes == null) throw new NullPointerException("The array of parameter types should not be null");
+ return new ParameterTypes(parameterTypes);
+ }
+
+ private final Class<?>[] parameterTypes;
+
+ private ParameterTypes(Class<?>[] parameterTypes) {
+ this.parameterTypes = parameterTypes;
+ }
+
+ /**
+ * Creates a new constructor invoker.
+ * @param <T> the generic type of the class containing the constructor to invoke.
+ * @param target the the type of object that the constructor invoker will create.
+ * @return the created constructor invoker.
+ */
+ public <T> Invoker<T> in(Class<T> target) {
+ return newInvoker(target, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/constructor/TargetType.java b/src/main/java/org/fest/reflect/constructor/TargetType.java
new file mode 100644
index 0000000..4d4a167
--- /dev/null
+++ b/src/main/java/org/fest/reflect/constructor/TargetType.java
@@ -0,0 +1,69 @@
+/*
+ * Created on Aug 17, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.constructor;
+
+import static org.fest.reflect.constructor.Invoker.newInvoker;
+import static org.fest.reflect.constructor.ParameterTypes.newParameterTypes;
+
+/**
+ * Understands the type of object that the constructor will create.
+ * <p>
+ * The following is an example of proper usage of the classes in this package:
+ *
+ * <pre>
+ * // Equivalent to call 'new Person()'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#in in}(Person.class).{@link Invoker#newInstance newInstance}();
+ *
+ * // Equivalent to call 'new Person("Yoda")'
+ * Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link TargetType#withParameterTypes(Class...) withParameterTypes}(String.class).{@link ParameterTypes#in(Class) in}(Person.class).{@link Invoker#newInstance newInstance}("Yoda");
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ */
+public final class TargetType {
+
+ /**
+ * Creates a new </code>{@link TargetType}</code>.
+ * @return the created <code>TargetType</code>.
+ */
+ public static TargetType startConstructorAccess() {
+ return new TargetType();
+ }
+
+ private TargetType() {}
+
+ /**
+ * Creates a new constructor invoker.
+ * @param <T> the generic type of the class containing the constructor to invoke.
+ * @param target the the type of object that the constructor invoker will create.
+ * @return the created constructor invoker.
+ */
+ public <T> Invoker<T> in(Class<T> target) {
+ return newInvoker(target);
+ }
+
+ /**
+ * Specifies the parameter types for the constructor to invoke. This method call is optional if the constructor to call does not
+ * accept arguments.
+ * @param parameterTypes the types of the parameters to pass to the constructor.
+ * @return the created parameter type holder.
+ * @throws NullPointerException if the given array is <code>null</code>.
+ */
+ public ParameterTypes withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/constructor/package.html b/src/main/java/org/fest/reflect/constructor/package.html
new file mode 100644
index 0000000..495a686
--- /dev/null
+++ b/src/main/java/org/fest/reflect/constructor/package.html
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API for
+constructor invocation via the Java Reflection API.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Equivalent to call 'new Person()'
+ Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link org.fest.reflect.constructor.TargetType#in in}(Person.class).{@link org.fest.reflect.constructor.Invoker#newInstance(Object...) newInstance}();
+
+ // Equivalent to call 'new Person("Yoda")'
+ Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link org.fest.reflect.constructor.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");
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/core/Reflection.java b/src/main/java/org/fest/reflect/core/Reflection.java
new file mode 100644
index 0000000..bd66f03
--- /dev/null
+++ b/src/main/java/org/fest/reflect/core/Reflection.java
@@ -0,0 +1,260 @@
+/*
+ * Created on Oct 31, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.core;
+
+import static org.fest.reflect.beanproperty.PropertyName.startPropertyAccess;
+import static org.fest.reflect.constructor.TargetType.startConstructorAccess;
+import static org.fest.reflect.field.FieldName.beginFieldAccess;
+import static org.fest.reflect.field.StaticFieldName.beginStaticFieldAccess;
+import static org.fest.reflect.innerclass.StaticInnerClassName.startStaticInnerClassAccess;
+import static org.fest.reflect.method.MethodName.startMethodAccess;
+import static org.fest.reflect.method.StaticMethodName.startStaticMethodAccess;
+import static org.fest.reflect.type.Type.newType;
+
+import org.fest.reflect.beanproperty.PropertyName;
+import org.fest.reflect.beanproperty.PropertyType;
+import org.fest.reflect.constructor.TargetType;
+import org.fest.reflect.field.FieldName;
+import org.fest.reflect.field.FieldTypeRef;
+import org.fest.reflect.field.StaticFieldName;
+import org.fest.reflect.field.StaticFieldType;
+import org.fest.reflect.field.StaticFieldTypeRef;
+import org.fest.reflect.innerclass.StaticInnerClassName;
+import org.fest.reflect.method.Invoker;
+import org.fest.reflect.method.MethodName;
+import org.fest.reflect.method.MethodReturnTypeRef;
+import org.fest.reflect.method.StaticMethodName;
+import org.fest.reflect.method.StaticMethodReturnTypeRef;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.reflect.type.Type;
+
+/**
+ * Understands the entry point for the classes in this package.
+ * <p>
+ * The following is an example of proper usage of the classes in this package:
+ *
+ * <pre>
+ * // Loads the class 'org.republic.Jedi'
+ * Class<?> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#load() load}();
+ *
+ * // Loads the class 'org.republic.Jedi' as 'org.republic.Person' (Jedi extends Person)
+ * Class<Person> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#loadAs(Class) loadAs}(Person.class);
+ *
+ * // Loads the class 'org.republic.Jedi' using a custom class loader
+ * Class<?> 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}();
+ *
+ * // Gets the inner class 'Master' in the declaring class 'Jedi':
+ * Class<?> 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}();
+ *
+ * // Equivalent to call 'new Person()'
+ * 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}();
+ *
+ * // Equivalent to call 'new Person("Yoda")'
+ * 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");
+ *
+ * // Retrieves the value of the field "name"
+ * 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}();
+ *
+ * // Sets the value of the field "name" to "Yoda"
+ * {@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");
+ *
+ * // Retrieves the value of the field "powers"
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link FieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link FieldTypeRef#in(Object) in}(jedi).{@link org.fest.reflect.field.Invoker#get() get}();
+ *
+ * // Equivalent to call 'person.setName("Luke")'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link org.fest.reflect.method.MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link org.fest.reflect.method.MethodParameterTypes#in(Object) in}(person)
+ * .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Luke");
+ *
+ * // Equivalent to call 'jedi.getPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#method(String) method}("getPowers").{@link MethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link MethodReturnTypeRef#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Retrieves the value of the static field "count" in Person.class
+ * 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}();
+ *
+ * // Sets the value of the static field "count" to 3 in Person.class
+ * {@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);
+ *
+ * // Retrieves the value of the static field "commonPowers" in Jedi.class
+ * List<String> commmonPowers = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link StaticFieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link org.fest.reflect.field.Invoker#get() get}();
+ *
+ * // Equivalent to call 'person.concentrate()'
+ * {@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}();
+ *
+ * // Equivalent to call 'person.getName()'
+ * String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link org.fest.reflect.method.MethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link org.fest.reflect.method.MethodReturnType#in(Object) in}(person)
+ * .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.setCommonPower("Jump")'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link org.fest.reflect.method.StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link org.fest.reflect.method.StaticMethodParameterTypes#in(Class) in}(Jedi.class)
+ * .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Jump");
+ *
+ * // Equivalent to call 'Jedi.addPadawan()'
+ * {@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}();
+ *
+ * // Equivalent to call 'Jedi.commonPowerCount()'
+ * String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link org.fest.reflect.method.StaticMethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link org.fest.reflect.method.StaticMethodReturnType#in(Class) in}(Jedi.class)
+ * .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.getCommonPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Retrieves the value of the property "name"
+ * 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}();
+ *
+ * // Sets the value of the property "name" to "Yoda"
+ * {@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");
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ * @author Ivan Hristov
+ */
+public final class Reflection {
+
+ /**
+ * Starting point of the fluent interface for loading a class dynamically.
+ * @param name the name of the class to load.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ * @since 1.1
+ */
+ public static Type type(String name) {
+ return newType(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for accessing static inner class via reflection.
+ * @param name the name of the static inner class to access.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ * @since 1.1
+ */
+ public static StaticInnerClassName staticInnerClass(String name) {
+ return startStaticInnerClassAccess(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for accessing fields via reflection.<br>
+ * Nested field are supported with dot notation, e.g. <code>"person.address.street"</code>.
+ * <p>
+ * Let's look how it works on an example :
+ *
+ * <pre>
+ * Let's say we have the following simple service:
+ *
+ * public class BusinessService {
+ * private NotificationService notificationService = new NotificationService();
+ * //... logic goes here
+ * }
+ *
+ * Where NotificationService is defined as follows:
+ *
+ * public class NotificationService {
+ * private Logger logger = new Logger();
+ * private IClientStatusDao clientStatusDao = new ClientStatusDao();
+ * //... logic goes here
+ * }
+ *
+ * And our ClientStatusDao looks like:
+ *
+ * public class ClientStatusDao implements IClientStatusDao {
+ * private final Session session = new SessionImpl();
+ * //... logic goes here
+ * }
+ *
+ * Let's say we want to change the {@code logger} field of {@code NotificationService} within our instance of {@code BusinessService}, we can do this:
+ *
+ * field("notificationService.logger").ofType(Logger.class).in(businessService).set(loggerMock);
+ *
+ * You can also set the deeply nested {@code session} field within {@code ClientStatusDao} like this:
+ *
+ * field("notificationService.clientStatusDao.session").ofType(Session.class).in(businessService).set(sessionMock);
+ * </pre>
+ *
+ * @param name the name of the field to access.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static FieldName field(String name) {
+ return beginFieldAccess(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for accessing static fields via reflection.
+ * @param name the name of the static field to access.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static StaticFieldName staticField(String name) {
+ return beginStaticFieldAccess(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for invoking methods via reflection.
+ * @param name the name of the method to invoke.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static MethodName method(String name) {
+ return startMethodAccess(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for invoking static methods via reflection.
+ * @param name the name of the static method to invoke.
+ * @return the starting point of the static method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static StaticMethodName staticMethod(String name) {
+ return startStaticMethodAccess(name);
+ }
+
+ /**
+ * Starting point of the fluent interface for invoking constructors via reflection.
+ * @return the starting point of the method chain.
+ */
+ public static TargetType constructor() {
+ return startConstructorAccess();
+ }
+
+ /**
+ * Starting point of the fluent interface for accessing properties via Bean Introspection.
+ * @param name the name of the property to access.
+ * @return the starting point of the method chain.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ * @since 1.2
+ */
+ public static PropertyName property(String name) {
+ return startPropertyAccess(name);
+ }
+
+ private Reflection() {}
+}
diff --git a/src/main/java/org/fest/reflect/core/package.html b/src/main/java/org/fest/reflect/core/package.html
new file mode 100644
index 0000000..bedf38e
--- /dev/null
+++ b/src/main/java/org/fest/reflect/core/package.html
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API that
+makes usage of the Java Reflection API easier and improves code readability.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Loads the class 'org.republic.Jedi'
+ Class<?> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link org.fest.reflect.type.Type#load() load}();
+
+ // Loads the class 'org.republic.Jedi' as 'org.republic.Person' (Jedi extends Person)
+ Class<Person> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link org.fest.reflect.type.Type#loadAs(Class) loadAs}(Person.class);
+
+ // Loads the class 'org.republic.Jedi' using a custom class loader
+ Class<?> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link org.fest.reflect.type.Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link org.fest.reflect.type.TypeLoader#load() load}();
+
+ // Gets the inner class 'Master' in the declaring class 'Jedi':
+ Class<?> 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}();
+
+ // Equivalent to call 'new Person()'
+ Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link org.fest.reflect.constructor.TargetType#in in}(Person.class).{@link org.fest.reflect.constructor.Invoker#newInstance(Object...) newInstance}();
+
+ // Equivalent to call 'new Person("Yoda")'
+ Person p = {@link org.fest.reflect.core.Reflection#constructor() constructor}().{@link org.fest.reflect.constructor.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");
+
+ // Retrieves the value of the field "name"
+ 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}();
+
+ // Sets the value of the field 'name' to "Yoda"
+ {@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");
+
+ // Equivalent to call 'jedi.getPowers()'
+ List<String> powers = {@link org.fest.reflect.core.Reflection#method(String) method}("getPowers").{@link org.fest.reflect.method.MethodName#withReturnType(org.fest.reflect.reference.TypeRef) withReturnType}(new {@link org.fest.reflect.reference.TypeRef TypeRef}<List<String>>() {})
+ .{@link org.fest.reflect.method.MethodReturnTypeRef#in(Object) in}(person)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+
+ // Equivalent to call 'person.setName("Luke")'
+ {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link org.fest.reflect.method.MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ .{@link org.fest.reflect.method.MethodParameterTypes#in(Object) in}(person)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Luke");
+
+ // Equivalent to call 'person.concentrate()'
+ {@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}();
+
+ // Equivalent to call 'person.getName()'
+ String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link org.fest.reflect.method.MethodName#withReturnType(Class) withReturnType}(String.class)
+ .{@link org.fest.reflect.method.MethodReturnType#in(Object) in}(person)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+
+ // Equivalent to call 'Jedi.getCommonPowers()'
+ List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link org.fest.reflect.method.StaticMethodName#withReturnType(org.fest.reflect.reference.TypeRef) withReturnType}(new {@link org.fest.reflect.reference.TypeRef TypeRef}<List<String>>() {})
+ .{@link org.fest.reflect.method.StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/exception/ReflectionError.java b/src/main/java/org/fest/reflect/exception/ReflectionError.java
new file mode 100644
index 0000000..a2c2447
--- /dev/null
+++ b/src/main/java/org/fest/reflect/exception/ReflectionError.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Nov 16, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.exception;
+
+/**
+ * Understands an error raised when using reflection.
+ *
+ * @author Alex Ruiz
+ */
+public final class ReflectionError extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new <code>{@link ReflectionError}</code>.
+ * @param message the detail message.
+ */
+ public ReflectionError(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new <code>{@link ReflectionError}</code>.
+ * @param message the detail message.
+ * @param cause the cause of the exception.
+ */
+ public ReflectionError(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/exception/package.html b/src/main/java/org/fest/reflect/exception/package.html
new file mode 100644
index 0000000..d7f9308
--- /dev/null
+++ b/src/main/java/org/fest/reflect/exception/package.html
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Exceptions used in the FEST-Reflect module.
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/DecoratedInvoker.java b/src/main/java/org/fest/reflect/field/DecoratedInvoker.java
new file mode 100644
index 0000000..41b8d36
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/DecoratedInvoker.java
@@ -0,0 +1,146 @@
+/*
+ * Created on Mar 18, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import java.lang.reflect.Proxy;
+
+import org.fest.reflect.field.decorator.DecoratorInvocationHandler;
+import org.fest.reflect.field.decorator.RuntimeExceptionShield;
+
+/**
+ * A decorated invoker allowing to ignore some exceptions or returning decorator result instead of field result.
+ * @author Ivan Hristov
+ */
+public final class DecoratedInvoker<T> {
+
+ private final T target;
+ private final T decorator;
+ private final Invoker<T> invoker;
+ private final Class<?> expectedType;
+ private final DecoratorInvocationHandler<T> decoratorInvocationHandler;
+
+ static <T> DecoratedInvoker<T> newInvoker(T target, T decorator, Class<?> expectedType, Invoker<T> invoker,
+ DecoratorInvocationHandler<T> decoratorInvocationHandler) {
+ return new DecoratedInvoker<T>(target, decorator, expectedType, invoker, decoratorInvocationHandler);
+ }
+
+ private DecoratedInvoker(T target, T decorator, Class<?> expectedType, Invoker<T> invoker,
+ DecoratorInvocationHandler<T> decoratorInvocationHandler) {
+ this.target = target;
+ this.decorator = decorator;
+ this.invoker = invoker;
+ this.expectedType = expectedType;
+ this.decoratorInvocationHandler = decoratorInvocationHandler;
+ }
+
+ /**
+ * Ignores any {@link RuntimeException} which comes from the preceding decorator.
+ * @return the DecoratedResultInvoker ignoring exceptions.
+ */
+ public DecoratedInvoker<T> ignoringDecoratorExceptions() {
+ return ignoringDecoratorExceptionsOfType(RuntimeException.class);
+ }
+
+ /**
+ * Ignores any exception of the {@code exceptionClass} type which comes from the preceding decorator.
+ * @param exceptionClass the exception to ignore - usually a checked exception of decorator method
+ * @return the DecoratedResultInvoker ignoring given exception type.
+ */
+ public DecoratedInvoker<T> ignoringDecoratorExceptionsOfType(Class<?> exceptionClass) {
+ RuntimeExceptionShield runtimeExceptionShield = new RuntimeExceptionShield(decorator, exceptionClass);
+ @SuppressWarnings("unchecked")
+ T exceptionSafeDecorator = (T) Proxy.newProxyInstance(decorator.getClass().getClassLoader(),//
+ new Class[] { expectedType }, runtimeExceptionShield);
+
+ decoratorInvocationHandler.setDecorator(exceptionSafeDecorator);
+
+ return newInvoker(target, exceptionSafeDecorator, expectedType, invoker, decoratorInvocationHandler);
+ }
+
+ /**
+ * Specifies that the result from the decorator should be returned.
+ * <p>
+ * If {@link DecoratedInvoker#ignoringDecoratorExceptions() ignoringDecoratorExceptions()} is used in combination with this
+ * method and an exception is thrown, the default value will be returned (as defined by JLS) for all primitives or null for all
+ * non-primitive.
+ * <p>
+ * Example :<br>
+ * If a {@link RuntimeException} is thrown while executing one of the decorated <code>IExampleService</code> field methods which
+ * returns primitive boolean value, the default value <i>false</i> will be returned.
+ *
+ * <pre>
+ * field("fieldName").ofType(IExampleService.class).in(target)
+ * .postDecorateWith(postDecoratorService)
+ * .returningDecoratorResult()
+ * .ignoringDecoratorExceptions();
+ * </pre>
+ * In case of several decorators attached to a field, the result from the latest will be returned.
+ * <p>
+ * Example 1:<br>
+ * The result from the <b>pre</b>DecoratorService will be returned
+ *
+ * <pre>
+ * field("fieldName").ofType(IExampleService.class).in(target)
+ * .preDecorateWith(preDecoratorService)
+ * .returningDecoratorResult();
+ * </pre>
+ * Example 2:<br>
+ * The result from the <b>post</b>DecoratorService will be returned
+ *
+ * <pre>
+ * field("fieldName").ofType(IExampleService.class).in(target)
+ * .postDecorateWith(postDecoratorService)
+ * .returningDecoratorResult();
+ * </pre>
+ * Example 3:<br>
+ * The result from the <b>pre</b>DecoratorService will be returned, since it's the <b>latest</b> attached decorator.
+ *
+ * <pre>
+ * field("fieldName").ofType(IExampleService.class).in(target)
+ * .postDecorateWith(postDecoratorService)
+ * .returningDecoratorResult()
+ * .<b>pre</b>DecorateWith(preDecoratorService)
+ * .returningDecoratorResult();
+ * </pre>
+ */
+ public DecoratedInvoker<T> returningDecoratorResult() {
+ decoratorInvocationHandler.setReturnDecoratorResult(true);
+ return newInvoker(target, decorator, expectedType, invoker, decoratorInvocationHandler);
+ }
+
+ /**
+ * Adds a pre-decorator to an already decorated field.
+ * <p>
+ * Note that if there are more than one pre-decorators assigned to a field they will be executed starting from the last attached
+ * decorator.
+ * @param decorator which methods be called before the same targeted object methods
+ * @return the {@link DecoratedInvoker} pre decorating the target field interface with given decorator.
+ */
+ public DecoratedInvoker<T> preDecorateWith(T decorator) {
+ return invoker.preDecorateWith(decorator);
+ }
+
+ /**
+ * Adds a post-decorator to an already decorated field
+ * <p>
+ * Note that if there are more than one post-decorators assigned to a field they will be executed starting from the first
+ * attached decorator.
+ * @param decorator which methods be called after the same targeted object methods
+ * @return the {@link DecoratedInvoker} post decorating the target field interface with given decorator.
+ */
+ public DecoratedInvoker<T> postDecorateWith(T decorator) {
+ return invoker.postDecorateWith(decorator);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/field/FieldName.java b/src/main/java/org/fest/reflect/field/FieldName.java
new file mode 100644
index 0000000..46e8b01
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/FieldName.java
@@ -0,0 +1,111 @@
+/*
+ * Created on Aug 17, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.FieldType.newFieldType;
+import static org.fest.reflect.field.FieldTypeRef.newFieldTypeRef;
+import static org.fest.util.Strings.isEmpty;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the name of a field to access using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the field "name"
+ * String name = {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the field "name" to "Yoda"
+ * {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#set(Object) set}("Yoda");
+ *
+ * // Retrieves the value of the field "powers"
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link FieldTypeRef#in(Object) in}(jedi).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the field "powers"
+ * List<String> powers = new ArrayList<String>();
+ * powers.add("heal");
+ * {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link FieldTypeRef#in(Object) in}(jedi).{@link Invoker#set(Object) set}(powers);
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ * @author Ivan Hristov
+ */
+public final class FieldName {
+
+ private final String name;
+ private final List<String> path;
+
+ /**
+ * Creates a new <code>{@link FieldName}</code>: the starting point of the fluent interface for accessing fields using Java
+ * Reflection.
+ * @param name the name of the field to access using Java Reflection.
+ * @return the created <code>FieldName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static FieldName beginFieldAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new FieldName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the field to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the field to access should not be empty");
+ }
+
+ private FieldName(String name) {
+ this.path = new ArrayList<String>(Arrays.asList(name.split("\\.")));
+ path.remove(path.size() - 1);
+ this.name = name.substring(name.lastIndexOf('.') + 1, name.length());
+ }
+
+ /**
+ * Sets the type of the field to access.
+ * @param <T> the generic type of the field type.
+ * @param type the type of the field to access.
+ * @return a recipient for the field type.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ */
+ public <T> FieldType<T> ofType(Class<T> type) {
+ return newFieldType(name, type, path);
+ }
+
+ /**
+ * Sets the type reference of the field to access. This method reduces casting when the type of the field to access uses
+ * generics.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link FieldTypeRef#in(Object) in}(jedi).{@link Invoker#get() get}();
+ * </pre>
+ * </p>
+ * @param <T> the generic type of the field type.
+ * @param type the type of the field to access.
+ * @return a recipient for the field type.
+ * @throws NullPointerException if the given type reference is <code>null</code>.
+ * @since 1.1
+ */
+ public <T> FieldTypeRef<T> ofType(TypeRef<T> type) {
+ return newFieldTypeRef(name, type, path);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/FieldType.java b/src/main/java/org/fest/reflect/field/FieldType.java
new file mode 100644
index 0000000..76e1708
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/FieldType.java
@@ -0,0 +1,77 @@
+/*
+ * Created on Aug 17, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.Invoker.newInvoker;
+
+import java.util.List;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands the type of a field to access using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the field "name"
+ * String name = {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the field "name" to "Yoda"
+ * {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#set(Object) set}("Yoda");
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the field.
+ *
+ * @author Alex Ruiz
+ * @author Ivan Hristov
+ */
+public class FieldType<T> {
+
+ private final List<String> path;
+
+ static <T> FieldType<T> newFieldType(String name, Class<T> type, List<String> path) {
+ if (type == null) throw new NullPointerException("The type of the field to access should not be null");
+ return new FieldType<T>(name, type, path);
+ }
+
+ private final String name;
+ private final Class<T> type;
+
+ private FieldType(String name, Class<T> type, List<String> path) {
+ this.name = name;
+ this.type = type;
+ this.path = path;
+ }
+
+ /**
+ * Returns a new field access invoker, capable of accessing (read/write) the underlying field.
+ * @param target the object containing the field of interest.
+ * @return the created field access invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a field with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Object target) {
+ Object nestedTarget = null;
+
+ for (String fieldName : path) {
+ nestedTarget = Invoker.getNestedField(fieldName, nestedTarget == null ? target : nestedTarget);
+ }
+
+ return newInvoker(name, type, nestedTarget == null ? target : nestedTarget);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/FieldTypeRef.java b/src/main/java/org/fest/reflect/field/FieldTypeRef.java
new file mode 100644
index 0000000..8701502
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/FieldTypeRef.java
@@ -0,0 +1,80 @@
+/*
+ * Created on Jan 24, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.Invoker.newInvoker;
+
+import java.util.List;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the type of a field to access using Java Reflection. This implementation supports Java generics.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the field "powers"
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link FieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link #in(Object) in}(jedi).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the field "powers"
+ * List<String> powers = new ArrayList<String>();
+ * powers.add("heal");
+ * {@link org.fest.reflect.core.Reflection#field(String) field}("powers").{@link FieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link #in(Object) in}(jedi).{@link Invoker#set(Object) set}(powers);
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the field.
+ *
+ * @author Alex Ruiz
+ * @author Ivan Hristov
+ *
+ * @since 1.1
+ */
+public class FieldTypeRef<T> {
+
+ static <T> FieldTypeRef<T> newFieldTypeRef(String name, TypeRef<T> type, List<String> path) {
+ if (type == null) throw new NullPointerException("The type reference of the field to access should not be null");
+ return new FieldTypeRef<T>(name, type, path);
+ }
+
+ private final String name;
+ private final TypeRef<T> type;
+ private final List<String> path;
+
+ private FieldTypeRef(String name, TypeRef<T> type, List<String> path) {
+ this.name = name;
+ this.type = type;
+ this.path = path;
+ }
+
+ /**
+ * Returns a new field invoker. A field invoker is capable of accessing (read/write) the underlying field.
+ * @param target the object containing the field of interest.
+ * @return the created field invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a field with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Object target) {
+ Object nestedTarget = null;
+
+ for (String fieldName : path) {
+ nestedTarget = Invoker.getNestedField(fieldName, nestedTarget == null ? target : nestedTarget);
+ }
+
+ return newInvoker(name, type, nestedTarget == null ? target : nestedTarget);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/Invoker.java b/src/main/java/org/fest/reflect/field/Invoker.java
new file mode 100644
index 0000000..e7347b5
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/Invoker.java
@@ -0,0 +1,302 @@
+/*
+ * Created on Oct 31, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.util.Accessibles.*;
+import static org.fest.util.Arrays.array;
+import static org.fest.util.Strings.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Proxy;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.field.decorator.DecoratorInvocationHandler;
+import org.fest.reflect.field.decorator.PostDecorator;
+import org.fest.reflect.field.decorator.PreDecorator;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the use of reflection to access a field from an object.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the field "name"
+ * String name = {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the field "name" to "Yoda"
+ * {@link org.fest.reflect.core.Reflection#field(String) field}("name").{@link FieldName#ofType(Class) ofType}(String.class).{@link FieldType#in(Object) in}(person).{@link Invoker#set(Object) set}("Yoda");
+ *
+ * // Retrieves the value of the static field "count"
+ * 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 Invoker#get() get}();
+ *
+ * // Sets the value of the static field "count" to 3
+ * {@link org.fest.reflect.core.Reflection#staticField(String) field}("count").{@link StaticFieldName#ofType(Class) ofType}(int.class).{@link StaticFieldType#in(Class) in}(Person.class).{@link Invoker#set(Object) set}(3);
+ * </pre>
+ *
+ * </p>
+ *
+ * @param <T> the declared type for the field to access.
+ *
+ * @author Alex Ruiz
+ * @author Ivan Hristov
+ */
+public final class Invoker<T> {
+
+ private final Object target;
+ private final Field field;
+ private final boolean accessible;
+ private final Class<?> expectedType;
+
+ static <T> Invoker<T> newInvoker(String fieldName, TypeRef<T> expectedType, Object target) {
+ return createInvoker(fieldName, expectedType.rawType(), target);
+ }
+
+ static <T> Invoker<T> newInvoker(String fieldName, Class<T> expectedType, Object target) {
+ return createInvoker(fieldName, expectedType, target);
+ }
+
+ private static <T> Invoker<T> createInvoker(String fieldName, Class<?> expectedType, Object target) {
+ if (target == null) { throw new NullPointerException("Target should not be null"); }
+ Field field = lookupInClassHierarchy(fieldName, typeOf(target));
+ verifyCorrectType(field, expectedType);
+ return new Invoker<T>(target, field, expectedType);
+ }
+
+ private static Class<?> typeOf(Object target) {
+ if (target instanceof Class<?>) return (Class<?>) target;
+ return target.getClass();
+ }
+
+ private static Field lookupInClassHierarchy(String fieldName, Class<?> declaringType) {
+ Field field = null;
+ Class<?> target = declaringType;
+ while (target != null) {
+ field = field(fieldName, target);
+ if (field != null) break;
+ target = target.getSuperclass();
+ }
+ if (field != null) return field;
+ throw new ReflectionError(concat("Unable to find field ", quote(fieldName), " in ", declaringType.getName()));
+ }
+
+ private static void verifyCorrectType(Field field, Class<?> expectedType) {
+ boolean isAccessible = field.isAccessible();
+ try {
+ makeAccessible(field);
+ Class<?> actualType = field.getType();
+ if (!expectedType.isAssignableFrom(actualType)) throw incorrectFieldType(field, actualType, expectedType);
+ } finally {
+ setAccessibleIgnoringExceptions(field, isAccessible);
+ }
+ }
+
+ private Invoker(Object target, Field field, Class<?> expectedType) {
+ this.target = target;
+ this.field = field;
+ this.expectedType = expectedType;
+ accessible = field.isAccessible();
+ }
+
+ private static Field field(String fieldName, Class<?> declaringType) {
+ try {
+ return declaringType.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+
+ private static ReflectionError incorrectFieldType(Field field, Class<?> actual, Class<?> expected) {
+ String fieldTypeName = field.getDeclaringClass().getName();
+ String message = concat("The type of the field ", quote(field.getName()), " in ", fieldTypeName, " should be <",
+ expected.getName(), "> but was <", actual.getName(), ">");
+ throw new ReflectionError(message);
+ }
+
+ /**
+ * Sets a value in the field managed by this class.
+ *
+ * @param value the value to set.
+ * @throws ReflectionError if the given value cannot be set.
+ */
+ public void set(T value) {
+ try {
+ setAccessible(field, true);
+ field.set(target, value);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to update the value in field ", quote(field.getName())), e);
+ } finally {
+ setAccessibleIgnoringExceptions(field, accessible);
+ }
+ }
+
+ /**
+ * <b>Pre</b>-decorates a targeted object's methods.
+ * <p>
+ * Each execution of a targeted object's method will be first performed on the same method of the {@code decorator} object. The
+ * result (if any) from the invocation of the targeted object's method will be returned but you can choose to return the
+ * decorator result if you want to.
+ * <p>
+ * Be aware:
+ * <li>The type of a targeted object should be an interface for this functionality to work</li>
+ * <li>Any exception caused by an invocation of a {@code decorator} object's method will result in disrupting the default
+ * program's flow</li>
+ * <p>
+ * Example: Assuming we have the following code:
+ *
+ * <pre>
+ * interface IUploadFileService {
+ * boolean upload(String file, String destination);
+ * }
+ *
+ * public class FileManager {
+ *
+ * private IUploadFileService uploadFileService;
+ * private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+ *
+ * public void manage(String fileName) {
+ * if( uploadFileService.upload(fileName, DEFAULT_DESTINATION) ) {
+ * System.out.println("File "+fileName+" sent to "+DEFAULT_DESTINATION);
+ * } else {
+ * System.out.println("Unable to sent "+fileName+" to "+DEFAULT_DESTINATION);
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * Let's say we want to decorate the uploadFileService.upload(...) part, so that additional functionality is executed
+ * <b>before</b> the actual uploadFileService.upload(...) logic, the following code will do the job:
+ *
+ * <pre>
+ * IUploadFileService uploadFileServiceDecorator = ...;
+ * FileManager fileManager = new FileManager();
+ *
+ * field("uploadFileService").ofType(IUploadFileService.class)
+ * .in(fileManager)
+ * .preDecorateWith(uploadFileServiceDecorator);
+ * </pre>
+ * However, if there is an exception when calling <code>uploadFileServiceDecorator.upload(fileName, DEFAULT_DESTINATION)</code>
+ * the default program's flow will be interrupted and the <code>uploadFileService.upload(fileName, DEFAULT_DESTINATION)</code>
+ * will not be executed.
+ * <p>
+ * @param decorator which methods be called before the same targeted object methods
+ * @return the {@link DecoratedInvoker} pre decorating the target field interface with given decorator.
+ */
+ public DecoratedInvoker<T> preDecorateWith(T decorator) {
+ T target = get();
+ DecoratorInvocationHandler<T> handler = new PreDecorator<T>(target, decorator);
+ @SuppressWarnings("unchecked")
+ T field = (T) Proxy.newProxyInstance(decorator.getClass().getClassLoader(), array(expectedType), handler);
+ set(field);
+ return DecoratedInvoker.newInvoker(target, decorator, expectedType, this, handler);
+ }
+
+ /**
+ * <b>Post</b>-decorates a targeted object's methods.
+ * <p>
+ * After each execution of a targeted object's method, the same method of the {@code decorator} object will be called. The
+ * result (if any) from the invocation of the targeted object's method will be returned but you can choose to return the
+ * decorator result if you want to.
+ * <p>
+ * Be aware:
+ * <li>The type of a targeted object should be an interface for this functionality to work</li>
+ * <li>Any exception caused by an invocation of a {@code decorator} object's method will result in disrupting the default
+ * program's flow</li>
+ * <p>
+ * Example: Assuming we have the following code:
+ *
+ * <pre>
+ * interface IUploadFileService {
+ * boolean upload(String file, String destination);
+ * }
+ *
+ * public class FileManager {
+ *
+ * private IUploadFileService uploadFileService;
+ * private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+ *
+ * public void manage(String fileName) {
+ * if( uploadFileService.upload(fileName, DEFAULT_DESTINATION) ) {
+ * System.out.println("File "+fileName+" sent to "+DEFAULT_DESTINATION);
+ * } else {
+ * System.out.println("Unable to sent "+fileName+" to "+DEFAULT_DESTINATION);
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * Let's say we want to decorate the uploadFileService.upload(...) part, so that additional functionality is executed
+ * <b>before</b> the actual uploadFileService.upload(...) logic, the following code will do the job:
+ *
+ * <pre>
+ * IUploadFileService uploadFileServiceDecorator = ...;
+ * FileManager fileManager = new FileManager();
+ *
+ * field("uploadFileService").ofType(IUploadFileService.class)
+ * .in(fileManager)
+ * .postDecorateWith(uploadFileServiceDecorator);
+ * </pre>
+ * However, if there is an exception when calling <code>uploadFileServiceDecorator.upload(fileName, DEFAULT_DESTINATION)</code>
+ * the default program's flow will be interrupted and the <code>uploadFileService.upload(fileName, DEFAULT_DESTINATION)</code>
+ * will not be executed.
+ * <p>
+ * @param decorator which methods be called after the same targeted object methods
+ * @return the {@link DecoratedInvoker} post decorating the target field interface with given decorator.
+ */
+ public DecoratedInvoker<T> postDecorateWith(T decorator) {
+ T target = get();
+ DecoratorInvocationHandler<T> handler = new PostDecorator<T>(target, decorator);
+ @SuppressWarnings("unchecked")
+ T field = (T) Proxy.newProxyInstance(decorator.getClass().getClassLoader(), array(expectedType), handler);
+ set(field);
+ return DecoratedInvoker.newInvoker(target, decorator, expectedType, this, handler);
+ }
+
+ /**
+ * Returns the value of the field managed by this class.
+ *
+ * @return the value of the field managed by this class.
+ * @throws ReflectionError if the value of the field cannot be retrieved.
+ */
+ public T get() {
+ return Invoker.<T> get(field, accessible, target);
+ }
+
+ static Object getNestedField(String fieldName, Object target) {
+ Field field = lookupInClassHierarchy(fieldName, typeOf(target));
+ return get(field, field.isAccessible(), target);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T get(Field field, boolean accessible, Object target) {
+ try {
+ setAccessible(field, true);
+ return (T) field.get(target);
+ } catch (Exception e) {
+ throw new ReflectionError(concat("Unable to obtain the value in field " + quote(field.getName())), e);
+ } finally {
+ setAccessibleIgnoringExceptions(field, accessible);
+ }
+ }
+
+ /**
+ * Returns the "real" field managed by this class.
+ *
+ * @return the "real" field managed by this class.
+ */
+ public Field info() {
+ return field;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/field/StaticFieldName.java b/src/main/java/org/fest/reflect/field/StaticFieldName.java
new file mode 100644
index 0000000..601fc15
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/StaticFieldName.java
@@ -0,0 +1,102 @@
+/*
+ * Created on Feb 5, 2008
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.StaticFieldType.newFieldType;
+import static org.fest.reflect.field.StaticFieldTypeRef.newFieldTypeRef;
+import static org.fest.util.Strings.isEmpty;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the name of a static field to access using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the static field "count"
+ * 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 Invoker#get() get}();
+ *
+ * // Sets the value of the static field "count" to 3
+ * {@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 Invoker#set(Object) set}(3);
+ *
+ * // Retrieves the value of the static field "commonPowers"
+ * List<String> commmonPowers = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the static field "commonPowers"
+ * List<String> commonPowers = new ArrayList<String>();
+ * commonPowers.add("jump");
+ * {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link Invoker#set(Object) set}(commonPowers);
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ */
+public final class StaticFieldName {
+
+ /**
+ * Creates a new <code>{@link StaticFieldName}</code>: the starting point of the fluent interface for accessing static fields
+ * using Java Reflection.
+ * @param name the name of the field to access using Java Reflection.
+ * @return the created <code>StaticFieldName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static StaticFieldName beginStaticFieldAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new StaticFieldName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the static field to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the static field to access should not be empty");
+ }
+
+ private final String name;
+
+ private StaticFieldName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the type of the field to access.
+ * @param <T> the generic type of the field type.
+ * @param type the type of the field to access.
+ * @return a recipient for the field type.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ */
+ public <T> StaticFieldType<T> ofType(Class<T> type) {
+ return newFieldType(name, type);
+ }
+
+ /**
+ * Sets the type reference of the field to access. This method reduces casting when the type of the field to access uses
+ * generics.
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * List<String> commmonPowers = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link #ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link Invoker#get() get}();
+ * </pre>
+ * </p>
+ * @param <T> the generic type of the field type.
+ * @param type the type of the field to access.
+ * @return a recipient for the field type.
+ * @throws NullPointerException if the given type reference is <code>null</code>.
+ */
+ public <T> StaticFieldTypeRef<T> ofType(TypeRef<T> type) {
+ return newFieldTypeRef(name, type);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/StaticFieldType.java b/src/main/java/org/fest/reflect/field/StaticFieldType.java
new file mode 100644
index 0000000..a6cc042
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/StaticFieldType.java
@@ -0,0 +1,64 @@
+/*
+ * Created on Feb 5, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.Invoker.newInvoker;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands the type of a static field to access using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the static field "count"
+ * 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 Invoker#get() get}();
+ *
+ * // Sets the value of the static field "count" to 3
+ * {@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 Invoker#set(Object) set}(3);
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the field.
+ *
+ * @author Alex Ruiz
+ */
+public class StaticFieldType<T> {
+
+ static <T> StaticFieldType<T> newFieldType(String name, Class<T> type) {
+ if (type == null) throw new NullPointerException("The type of the static field to access should not be null");
+ return new StaticFieldType<T>(name, type);
+ }
+
+ private final String name;
+ private final Class<T> type;
+
+ StaticFieldType(String name, Class<T> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Returns a new field invoker. A field invoker is capable of accessing (read/write) the underlying field.
+ * @param target the type containing the static field of interest.
+ * @return the created field invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a static field with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Class<?> target) {
+ return newInvoker(name, type, target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/StaticFieldTypeRef.java b/src/main/java/org/fest/reflect/field/StaticFieldTypeRef.java
new file mode 100644
index 0000000..93162a1
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/StaticFieldTypeRef.java
@@ -0,0 +1,69 @@
+/*
+ * Created on Feb 5, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.field.Invoker.newInvoker;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the type of a static field to access using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Retrieves the value of the static field "commonPowers"
+ * List<String> commmonPowers = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link StaticFieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link Invoker#get() get}();
+ *
+ * // Sets the value of the static field "commonPowers"
+ * List<String> commonPowers = new ArrayList<String>();
+ * commonPowers.add("jump");
+ * {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("commonPowers").{@link StaticFieldName#ofType(TypeRef) ofType}(new {@link TypeRef TypeRef}<List<String>>() {}).{@link StaticFieldTypeRef#in(Class) in}(Jedi.class).{@link Invoker#set(Object) set}(commonPowers);
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the field.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public class StaticFieldTypeRef<T> {
+
+ static <T> StaticFieldTypeRef<T> newFieldTypeRef(String name, TypeRef<T> type) {
+ if (type == null) throw new NullPointerException("The type reference of the static field to access should not be null");
+ return new StaticFieldTypeRef<T>(name, type);
+ }
+
+ private final String name;
+ private final TypeRef<T> type;
+
+ private StaticFieldTypeRef(String name, TypeRef<T> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ /**
+ * Returns a new field invoker. A field invoker is capable of accessing (read/write) the underlying field.
+ * @param target the type containing the static field of interest.
+ * @return the created field invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ * @throws ReflectionError if a static field with a matching name and type cannot be found.
+ */
+ public Invoker<T> in(Class<?> target) {
+ return newInvoker(name, type, target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/field/decorator/DecoratorInvocationHandler.java b/src/main/java/org/fest/reflect/field/decorator/DecoratorInvocationHandler.java
new file mode 100644
index 0000000..56c8d9a
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/decorator/DecoratorInvocationHandler.java
@@ -0,0 +1,82 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field.decorator;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * @author Ivan Hristov
+ *
+ */
+public abstract class DecoratorInvocationHandler<T> implements InvocationHandler {
+
+ private final T target;
+ private T decorator;
+ private boolean returnDecoratorResult = false;
+
+ public DecoratorInvocationHandler(T target, T decorator) {
+ this.target = target;
+ this.decorator = decorator;
+ }
+
+ public void setDecorator(T decorator) {
+ this.decorator = decorator;
+ }
+
+ public T getTarget() {
+ return target;
+ }
+
+ public T getDecorator() {
+ return decorator;
+ }
+
+ public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+
+ Object firstResult = null;
+ try {
+ firstResult = invokeFirst(method, args);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+
+ Object secondResult = null;
+ try {
+ secondResult = invokeSecond(method, args);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+
+ return getResult(firstResult, secondResult);
+ }
+
+ protected abstract Object invokeFirst(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException;
+
+ protected abstract Object invokeSecond(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException;
+
+ protected abstract Object getResult(Object firstResult, Object secondResult);
+
+ public void setReturnDecoratorResult(boolean returnDecoratorResult) {
+ this.returnDecoratorResult = returnDecoratorResult;
+ }
+
+ protected boolean shouldReturnDecoratorResult() {
+ return returnDecoratorResult;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/field/decorator/PostDecorator.java b/src/main/java/org/fest/reflect/field/decorator/PostDecorator.java
new file mode 100644
index 0000000..2efb336
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/decorator/PostDecorator.java
@@ -0,0 +1,48 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field.decorator;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A proxy for post-decorating a field
+ * @author Ivan Hristov
+ *
+ */
+public class PostDecorator<T> extends DecoratorInvocationHandler<T> {
+
+ public PostDecorator(T target, T decorator) {
+ super(target, decorator);
+ }
+
+ @Override
+ protected Object invokeFirst(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ return method.invoke(getTarget(), args);
+ }
+
+ @Override
+ protected Object invokeSecond(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ return method.invoke(getDecorator(), args);
+ }
+
+ @Override
+ protected Object getResult(Object firstResult, Object secondResult) {
+ return shouldReturnDecoratorResult() ? secondResult : firstResult;
+ }
+
+}
diff --git a/src/main/java/org/fest/reflect/field/decorator/PreDecorator.java b/src/main/java/org/fest/reflect/field/decorator/PreDecorator.java
new file mode 100644
index 0000000..447aa61
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/decorator/PreDecorator.java
@@ -0,0 +1,47 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field.decorator;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A proxy for pre-decorating a field
+ * @author Ivan Hristov
+ *
+ */
+public class PreDecorator<T> extends DecoratorInvocationHandler<T> {
+
+ public PreDecorator(T target, T decorator) {
+ super(target, decorator);
+ }
+
+ @Override
+ protected Object invokeFirst(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ return method.invoke(getDecorator(), args);
+ }
+
+ @Override
+ protected Object invokeSecond(Method method, Object[] args) throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ return method.invoke(getTarget(), args);
+ }
+
+ @Override
+ protected Object getResult(Object firstResult, Object secondResult) {
+ return shouldReturnDecoratorResult() ? firstResult : secondResult;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/field/decorator/RuntimeExceptionShield.java b/src/main/java/org/fest/reflect/field/decorator/RuntimeExceptionShield.java
new file mode 100644
index 0000000..84aa12d
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/decorator/RuntimeExceptionShield.java
@@ -0,0 +1,61 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field.decorator;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A proxy for shielding from exception
+ * @author Ivan Hristov
+ *
+ */
+public class RuntimeExceptionShield implements InvocationHandler {
+
+ private static final Map<Class<?>, Object> DEFAULT_RETURN_VALUES = new HashMap<Class<?>, Object>();
+ private final Object target;
+ private final Class<?> exceptionClass;
+
+ // static init - reference JLS
+ {
+ DEFAULT_RETURN_VALUES.put(byte.class, 0);
+ DEFAULT_RETURN_VALUES.put(short.class, 0);
+ DEFAULT_RETURN_VALUES.put(int.class, 0);
+ DEFAULT_RETURN_VALUES.put(long.class, 0L);
+ DEFAULT_RETURN_VALUES.put(float.class, 0f);
+ DEFAULT_RETURN_VALUES.put(double.class, 0d);
+ DEFAULT_RETURN_VALUES.put(char.class, '\u0000');
+ DEFAULT_RETURN_VALUES.put(boolean.class, false);
+ }
+
+ public RuntimeExceptionShield(Object target, Class<?> exceptionClass) {
+ this.target = target;
+ this.exceptionClass = exceptionClass;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ try {
+ return method.invoke(target, args);
+ } catch (InvocationTargetException e) {
+ if (!(e.getCause().getClass() == exceptionClass)) throw e.getCause();
+ // shield from specified exceptions
+ }
+ return DEFAULT_RETURN_VALUES.get(method.getReturnType());
+ }
+
+}
diff --git a/src/main/java/org/fest/reflect/field/package.html b/src/main/java/org/fest/reflect/field/package.html
new file mode 100644
index 0000000..a70cf7a
--- /dev/null
+++ b/src/main/java/org/fest/reflect/field/package.html
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API
+for field access via the Java Reflection API.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Retrieves the value of the field "name"
+ 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}();
+
+ // Sets the value of the field "name" to "Yoda"
+ {@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");
+
+ // Retrieves the value of the static field "count"
+ int count = {@link org.fest.reflect.core.Reflection#staticField(String) staticField}("count").{@link org.fest.reflect.field.StaticFieldName#ofType(Class) ofType}(int.class).{@link org.fest.reflect.field.StaticFieldType#in(Class) in}(Person.class).{@link org.fest.reflect.field.Invoker#get() get}();
+
+ // Sets the value of the static field "count" to 3
+ {@link org.fest.reflect.core.Reflection#staticField(String) field}("count").{@link org.fest.reflect.field.StaticFieldName#ofType(Class) ofType}(int.class).{@link org.fest.reflect.field.StaticFieldType#in(Class) in}(Person.class).{@link org.fest.reflect.field.Invoker#set(Object) set}(3);
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/innerclass/Invoker.java b/src/main/java/org/fest/reflect/innerclass/Invoker.java
new file mode 100644
index 0000000..7cbbeae
--- /dev/null
+++ b/src/main/java/org/fest/reflect/innerclass/Invoker.java
@@ -0,0 +1,59 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.innerclass;
+
+import static org.fest.util.Strings.concat;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands how to obtain a reference to a static inner class.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public class Invoker {
+
+ static Invoker newInvoker(Class<?> declaringClass, String innerClassName) {
+ if (declaringClass == null) throw new NullPointerException("The declaring class should not be null");
+ return new Invoker(declaringClass, innerClassName);
+ }
+
+ private final Class<?> declaringClass;
+ private final String innerClassName;
+
+ private Invoker(Class<?> declaringClass, String innerClassName) {
+ this.declaringClass = declaringClass;
+ this.innerClassName = innerClassName;
+ }
+
+ /**
+ * Returns a reference to the static inner class with the specified name in the specified declaring class.
+ * @return a reference to the static inner class with the specified name in the specified declaring class.
+ * @throws ReflectionError if the static inner class does not exist (since 1.2).
+ */
+ public Class<?> get() {
+ String namespace = declaringClass.getName();
+ for (Class<?> innerClass : declaringClass.getDeclaredClasses())
+ if (innerClass.getName().equals(expectedInnerClassName(namespace))) return innerClass;
+ throw new ReflectionError(concat("The static inner class <", innerClassName, "> cannot be found in ",
+ declaringClass.getName()));
+ }
+
+ private String expectedInnerClassName(String namespace) {
+ return concat(namespace, "$", innerClassName);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/innerclass/StaticInnerClassName.java b/src/main/java/org/fest/reflect/innerclass/StaticInnerClassName.java
new file mode 100644
index 0000000..39670e9
--- /dev/null
+++ b/src/main/java/org/fest/reflect/innerclass/StaticInnerClassName.java
@@ -0,0 +1,81 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.innerclass;
+
+import static org.fest.reflect.innerclass.Invoker.newInvoker;
+import static org.fest.util.Strings.isEmpty;
+
+/**
+ * Understands the name of a static inner class.
+ * <p>
+ * Let's assume we have the class <code>Jedi</code>, which contains two static inner classes: <code>Master</code> and
+ * <code>Padawan</code>.
+ *
+ * <pre>
+ * public class Jedi {
+ *
+ * public static class Master {}
+ *
+ * public static class Padawan {}
+ * }
+ * </pre>
+ * </p>
+ * <p>
+ * The following example shows how to get a reference to the inner class <code>Master</code>:
+ *
+ * <pre>
+ * Class<?> 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}();
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public final class StaticInnerClassName {
+
+ /**
+ * Creates a new </code>{@link StaticInnerClassName}</code>.
+ * @param name the name of the static inner class to obtain.
+ * @return the created <code>StaticInnerClassName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static StaticInnerClassName startStaticInnerClassAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new StaticInnerClassName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the static inner class to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the static inner class to access should not be empty");
+ }
+
+ private final String name;
+
+ private StaticInnerClassName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Specifies the declaring class of the static inner class to obtain.
+ * @param declaringClass the declaring class.
+ * @return an object responsible for obtaining a reference to a static inner class.
+ * @throws NullPointerException if the given declaring class is <code>null</code>.
+ */
+ public Invoker in(Class<?> declaringClass) {
+ return newInvoker(declaringClass, name);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/innerclass/package.html b/src/main/java/org/fest/reflect/innerclass/package.html
new file mode 100644
index 0000000..1cb62f1
--- /dev/null
+++ b/src/main/java/org/fest/reflect/innerclass/package.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API for accessing static inner classes via the Java Reflection API.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Gets the inner class 'Master' in the declaring class 'Jedi':
+ Class<?> 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}();
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/Invoker.java b/src/main/java/org/fest/reflect/method/Invoker.java
new file mode 100644
index 0000000..0518a3a
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/Invoker.java
@@ -0,0 +1,134 @@
+/*
+ * Created on Oct 31, 2006
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.util.Accessibles.makeAccessible;
+import static org.fest.reflect.util.Accessibles.setAccessibleIgnoringExceptions;
+import static org.fest.reflect.util.Throwables.targetOf;
+import static org.fest.util.Arrays.format;
+import static org.fest.util.Strings.concat;
+import static org.fest.util.Strings.quote;
+
+import java.lang.reflect.Method;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands the use of reflection to access a method from an object.
+ * <p>
+ *
+ * <pre>
+ * // Equivalent to call 'person.setName("Luke")'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link MethodParameterTypes#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}("Luke");
+ *
+ * // Equivalent to call 'person.concentrate()'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("concentrate").{@link MethodName#in(Object) in}(person).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'person.getName()'
+ * String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link MethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link MethodReturnType#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the return type of the method invocation.
+ *
+ * @author Yvonne Wang
+ */
+public final class Invoker<T> {
+
+ static <T> Invoker<T> newInvoker(String methodName, Object target, Class<?>... parameterTypes) {
+ return createInvoker(methodName, target, parameterTypes);
+ }
+
+ private static <T> Invoker<T> createInvoker(String methodName, Object target, Class<?>... parameterTypes) {
+ if (target == null) throw new NullPointerException("Target should not be null");
+ Method method = lookupInClassHierarchy(methodName, typeOf(target), parameterTypes);
+ return new Invoker<T>(target, method);
+ }
+
+ private static Class<?> typeOf(Object target) {
+ if (target instanceof Class<?>) return (Class<?>) target;
+ return target.getClass();
+ }
+
+ private static Method lookupInClassHierarchy(String methodName, Class<?> targetType, Class<?>[] parameterTypes) {
+ Method method = null;
+ Class<?> type = targetType;
+ while (type != null) {
+ method = method(methodName, type, parameterTypes);
+ if (method != null) break;
+ type = type.getSuperclass();
+ }
+ if (method == null)
+ throw new ReflectionError(concat("Unable to find method ", quote(methodName), " in ", targetType.getName(),
+ " with parameter type(s) ", format(parameterTypes)));
+ return method;
+ }
+
+ private static Method method(String methodName, Class<?> type, Class<?>[] parameterTypes) {
+ try {
+ return type.getDeclaredMethod(methodName, parameterTypes);
+ } catch (SecurityException e) {
+ return null;
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ private final Object target;
+ private final Method method;
+
+ private Invoker(Object target, Method method) {
+ this.target = target;
+ this.method = method;
+ }
+
+ /**
+ * Invokes the method managed by this class using the given arguments.
+ * @param args the arguments to use to call the method managed by this class.
+ * @return the result of the method call.
+ * @throws ReflectionError if the method cannot be invoked.
+ */
+ @SuppressWarnings("unchecked")
+ public T invoke(Object... args) {
+ boolean accessible = method.isAccessible();
+ try {
+ makeAccessible(method);
+ return (T) method.invoke(target, args);
+ } catch (Throwable t) {
+ Throwable cause = targetOf(t);
+ if (cause instanceof RuntimeException) throw (RuntimeException) cause;
+ throw cannotInvokeMethod(cause, args);
+ } finally {
+ setAccessibleIgnoringExceptions(method, accessible);
+ }
+ }
+
+ private ReflectionError cannotInvokeMethod(Throwable cause, Object... args) {
+ String message = concat("Unable to invoke method ", quote(method.getName()), " with arguments ", format(args));
+ throw new ReflectionError(message, cause);
+ }
+
+ /**
+ * Returns the "real" method managed by this class.
+ * @return the "real" method managed by this class.
+ */
+ public java.lang.reflect.Method info() {
+ return method;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/method/MethodName.java b/src/main/java/org/fest/reflect/method/MethodName.java
new file mode 100644
index 0000000..97c9054
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/MethodName.java
@@ -0,0 +1,125 @@
+/*
+ * Created on Aug 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.MethodParameterTypes.newParameterTypes;
+import static org.fest.reflect.method.MethodReturnType.newReturnType;
+import static org.fest.reflect.method.MethodReturnTypeRef.newReturnTypeRef;
+import static org.fest.util.Strings.isEmpty;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the name of a method to invoke using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'person.setName("Luke")'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link MethodParameterTypes#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}("Luke");
+ *
+ * // Equivalent to call 'person.concentrate()'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("concentrate").{@link MethodName#in(Object) in}(person).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'person.getName()'
+ * String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link MethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link MethodReturnType#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'jedi.getPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#method(String) method}("getPowers").{@link MethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link MethodReturnTypeRef#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @author Yvonne Wang
+ * @author Alex Ruiz
+ */
+public final class MethodName {
+
+ /**
+ * Creates a new <code>{@link MethodName}</code>: the starting point of the fluent interface for accessing methods using Java
+ * Reflection.
+ * @param name the name of the method to invoke using Java Reflection.
+ * @return the created <code>MethodName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static MethodName startMethodAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new MethodName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the method to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the method to access should not be empty");
+ }
+
+ private final String name;
+
+ private MethodName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Specifies the return type of the method to invoke. This method call is optional if the return type of the method to invoke is
+ * <code>void</code>.
+ * @param <T> the generic type of the method's return type.
+ * @param type the return type of the method to invoke.
+ * @return the created return type holder.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ */
+ public <T> MethodReturnType<T> withReturnType(Class<T> type) {
+ return newReturnType(name, type);
+ }
+
+ /**
+ * Specifies the return type reference of the method to invoke. This method call is optional if the return type of the method to
+ * invoke is <code>void</code>.
+ * @param <T> the generic type of the method's return type.
+ * @param type the return type reference of the method to invoke.
+ * @return the created return type holder.
+ * @throws NullPointerException if the given type reference is <code>null</code>.
+ * @since 1.1
+ */
+ public <T> MethodReturnTypeRef<T> withReturnType(TypeRef<T> type) {
+ return newReturnTypeRef(name, type);
+ }
+
+ /**
+ * Specifies the parameter types of the method to invoke. This method call is optional if the method to invoke does not take
+ * arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public MethodParameterTypes<Void> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+
+ /**
+ * Creates a new invoker for a method that takes no parameters and return value <code>void</code>.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<Void> in(Object target) {
+ return newInvoker(name, target);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/MethodParameterTypes.java b/src/main/java/org/fest/reflect/method/MethodParameterTypes.java
new file mode 100644
index 0000000..bf08ed9
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/MethodParameterTypes.java
@@ -0,0 +1,70 @@
+/*
+ * Created on Aug 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+
+/**
+ * Understands the parameter types of the method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'person.setName("Luke")'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link MethodParameterTypes#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}("Luke");
+ *
+ * // Equivalent to call 'person.concentrate()'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("concentrate").{@link MethodName#in(Object) in}(person).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'person.getName()'
+ * String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link MethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link MethodReturnType#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the method's return type.
+ *
+ * @author Yvonne Wang
+ * @author Alex Ruiz
+ */
+public final class MethodParameterTypes<T> {
+
+ private final String name;
+ private final Class<?>[] parameterTypes;
+
+ static <T> MethodParameterTypes<T> newParameterTypes(String name, Class<?>[] parameterTypes) {
+ if (parameterTypes == null)
+ throw new NullPointerException("The array of parameter types for the method to access should not be null");
+ return new MethodParameterTypes<T>(parameterTypes, name);
+ }
+
+ private MethodParameterTypes(Class<?>[] parameterTypes, String name) {
+ this.name = name;
+ this.parameterTypes = parameterTypes;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Object target) {
+ return newInvoker(name, target, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/MethodReturnType.java b/src/main/java/org/fest/reflect/method/MethodReturnType.java
new file mode 100644
index 0000000..a114ebf
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/MethodReturnType.java
@@ -0,0 +1,79 @@
+/*
+ * Created on Aug 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.MethodParameterTypes.newParameterTypes;
+
+/**
+ * Understands the return type of the method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'person.setName("Luke")'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link MethodParameterTypes#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}("Luke");
+ *
+ * // Equivalent to call 'person.concentrate()'
+ * {@link org.fest.reflect.core.Reflection#method(String) method}("concentrate").{@link MethodName#in(Object) in}(person).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'person.getName()'
+ * String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link MethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link MethodReturnType#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the method's return type.
+ *
+ * @author Yvonne Wang
+ * @author Alex Ruiz
+ */
+public class MethodReturnType<T> {
+
+ static <T> MethodReturnType<T> newReturnType(String name, Class<T> type) {
+ if (type == null) throw new NullPointerException("The return type of the method to access should not be null");
+ return new MethodReturnType<T>(name);
+ }
+
+ private final String name;
+
+ private MethodReturnType(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Object target) {
+ return newInvoker(name, target);
+ }
+
+ /**
+ * Specifies the parameter types of the method to invoke. This method call is optional if the method to invoke does not take
+ * arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public MethodParameterTypes<T> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/MethodReturnTypeRef.java b/src/main/java/org/fest/reflect/method/MethodReturnTypeRef.java
new file mode 100644
index 0000000..c68d012
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/MethodReturnTypeRef.java
@@ -0,0 +1,74 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.MethodParameterTypes.newParameterTypes;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the return type reference of the method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'jedi.getPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#method(String) method}("getPowers").{@link MethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link MethodReturnTypeRef#in(Object) in}(person)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the method's return type reference.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public class MethodReturnTypeRef<T> {
+
+ static <T> MethodReturnTypeRef<T> newReturnTypeRef(String name, TypeRef<T> type) {
+ if (type == null) throw new NullPointerException("The return type reference of the method to access should not be null");
+ return new MethodReturnTypeRef<T>(name);
+ }
+
+ private final String name;
+
+ private MethodReturnTypeRef(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Object target) {
+ return newInvoker(name, target);
+ }
+
+ /**
+ * Specifies the parameter types of the method to invoke. This method call is optional if the method to invoke does not take
+ * arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public MethodParameterTypes<T> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/StaticMethodName.java b/src/main/java/org/fest/reflect/method/StaticMethodName.java
new file mode 100644
index 0000000..3e07b0b
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/StaticMethodName.java
@@ -0,0 +1,123 @@
+/*
+ * Created on Feb 20, 2008
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2008-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.StaticMethodParameterTypes.newParameterTypes;
+import static org.fest.reflect.method.StaticMethodReturnType.newReturnType;
+import static org.fest.reflect.method.StaticMethodReturnTypeRef.newReturnTypeRef;
+import static org.fest.util.Strings.isEmpty;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the name of a static method to invoke using Java Reflection.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'Jedi.setCommonPower("Jump")'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link StaticMethodParameterTypes#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}("Jump");
+ *
+ * // Equivalent to call 'Jedi.addPadawan()'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("addPadawan").{@link StaticMethodName#in(Class) in}(Jedi.class).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.commonPowerCount()'
+ * String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link StaticMethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link StaticMethodReturnType#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.getCommonPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ */
+public final class StaticMethodName {
+
+ /**
+ * Creates a new </code>{@link StaticMethodName}</code>: the starting point of the fluent interface for accessing static methods
+ * using Java Reflection.
+ * @param name the name of the method to access using Java Reflection.
+ * @return the created <code>StaticMethodName</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static StaticMethodName startStaticMethodAccess(String name) {
+ validateIsNotNullOrEmpty(name);
+ return new StaticMethodName(name);
+ }
+
+ private static void validateIsNotNullOrEmpty(String name) {
+ if (name == null) throw new NullPointerException("The name of the static method to access should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the static method to access should not be empty");
+ }
+
+ private final String name;
+
+ private StaticMethodName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Specifies the return type of the static method to invoke. This method call is optional if the return type of the method to
+ * invoke is <code>void</code>.
+ * @param <T> the generic type of the method's return type.
+ * @param type the return type of the method to invoke.
+ * @return the created return type holder.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ */
+ public <T> StaticMethodReturnType<T> withReturnType(Class<T> type) {
+ return newReturnType(name, type);
+ }
+
+ /**
+ * Specifies the return type reference of the static method to invoke. This method call is optional if the return type of the
+ * method to invoke is <code>void</code>.
+ * @param <T> the generic type of the method's return type.
+ * @param type the return type reference of the method to invoke.
+ * @return the created return type holder.
+ * @throws NullPointerException if the given type reference is <code>null</code>.
+ */
+ public <T> StaticMethodReturnTypeRef<T> withReturnType(TypeRef<T> type) {
+ return newReturnTypeRef(name, type);
+ }
+
+ /**
+ * Specifies the parameter types of the static method to invoke. This method call is optional if the method to invoke does not
+ * take arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public StaticMethodParameterTypes<Void> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+
+ /**
+ * Creates a new invoker for a static method that takes no parameters and return value <code>void</code>.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<Void> in(Class<?> target) {
+ return newInvoker(name, target);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/method/StaticMethodParameterTypes.java b/src/main/java/org/fest/reflect/method/StaticMethodParameterTypes.java
new file mode 100644
index 0000000..0354701
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/StaticMethodParameterTypes.java
@@ -0,0 +1,76 @@
+/*
+ * Created on Aug 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the parameter types of the static method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'Jedi.setCommonPower("Jump")'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link StaticMethodParameterTypes#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}("Jump");
+ *
+ * // Equivalent to call 'Jedi.addPadawan()'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("addPadawan").{@link StaticMethodName#in(Class) in}(Jedi.class).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.commonPowerCount()'
+ * String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link StaticMethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link StaticMethodReturnType#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.getCommonPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the static method's return type.
+ *
+ * @author Alex Ruiz
+ */
+public final class StaticMethodParameterTypes<T> {
+
+ static <T> StaticMethodParameterTypes<T> newParameterTypes(String name, Class<?>[] parameterTypes) {
+ if (parameterTypes == null)
+ throw new NullPointerException("The array of parameter types for the static method to access should not be null");
+ return new StaticMethodParameterTypes<T>(name, parameterTypes);
+ }
+
+ private final String name;
+ private final Class<?>[] parameterTypes;
+
+ private StaticMethodParameterTypes(String name, Class<?>[] parameterTypes) {
+ this.name = name;
+ this.parameterTypes = parameterTypes;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the class containing the static method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Class<?> target) {
+ return newInvoker(name, target, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/StaticMethodReturnType.java b/src/main/java/org/fest/reflect/method/StaticMethodReturnType.java
new file mode 100644
index 0000000..366843c
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/StaticMethodReturnType.java
@@ -0,0 +1,85 @@
+/*
+ * Created on Aug 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.StaticMethodParameterTypes.newParameterTypes;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the return type of the static method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'Jedi.setCommonPower("Jump")'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ * .{@link StaticMethodParameterTypes#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}("Jump");
+ *
+ * // Equivalent to call 'Jedi.addPadawan()'
+ * {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("addPadawan").{@link StaticMethodName#in(Class) in}(Jedi.class).{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.commonPowerCount()'
+ * String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link StaticMethodName#withReturnType(Class) withReturnType}(String.class)
+ * .{@link StaticMethodReturnType#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ *
+ * // Equivalent to call 'Jedi.getCommonPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the static method's return type.
+ *
+ * @author Alex Ruiz
+ */
+public class StaticMethodReturnType<T> {
+
+ static <T> StaticMethodReturnType<T> newReturnType(String name, Class<T> type) {
+ if (type == null) throw new NullPointerException("The return type of the static method to access should not be null");
+ return new StaticMethodReturnType<T>(name);
+ }
+
+ private final String name;
+
+ private StaticMethodReturnType(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Class<?> target) {
+ return newInvoker(name, target);
+ }
+
+ /**
+ * Specifies the parameter types of the static method to invoke. This method call is optional if the method to invoke does not
+ * take arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public StaticMethodParameterTypes<T> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/StaticMethodReturnTypeRef.java b/src/main/java/org/fest/reflect/method/StaticMethodReturnTypeRef.java
new file mode 100644
index 0000000..6664667
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/StaticMethodReturnTypeRef.java
@@ -0,0 +1,75 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.method.Invoker.newInvoker;
+import static org.fest.reflect.method.StaticMethodParameterTypes.newParameterTypes;
+
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * Understands the return type of the static method to invoke.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Equivalent to call 'Jedi.getCommonPowers()'
+ * List<String> powers = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("getCommonPowers").{@link StaticMethodName#withReturnType(TypeRef) withReturnType}(new {@link TypeRef TypeRef}<List<String>>() {})
+ * .{@link StaticMethodReturnTypeRef#in(Class) in}(Jedi.class)
+ * .{@link Invoker#invoke(Object...) invoke}();
+ * </pre>
+ * </p>
+ *
+ * @param <T> the generic type of the static method's return type.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public class StaticMethodReturnTypeRef<T> {
+
+ static <T> StaticMethodReturnTypeRef<T> newReturnTypeRef(String name, TypeRef<T> type) {
+ if (type == null)
+ throw new NullPointerException("The return type reference of the static method to access should not be null");
+ return new StaticMethodReturnTypeRef<T>(name);
+ }
+
+ private final String name;
+
+ private StaticMethodReturnTypeRef(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a new method invoker.
+ * @param target the object containing the method to invoke.
+ * @return the created method invoker.
+ * @throws NullPointerException if the given target is <code>null</code>.
+ */
+ public Invoker<T> in(Class<?> target) {
+ return newInvoker(name, target);
+ }
+
+ /**
+ * Specifies the parameter types of the static method to invoke. This method call is optional if the method to invoke does not
+ * take arguments.
+ * @param parameterTypes the parameter types of the method to invoke.
+ * @return the created parameter types holder.
+ * @throws NullPointerException if the array of parameter types is <code>null</code>.
+ */
+ public StaticMethodParameterTypes<T> withParameterTypes(Class<?>... parameterTypes) {
+ return newParameterTypes(name, parameterTypes);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/method/package.html b/src/main/java/org/fest/reflect/method/package.html
new file mode 100644
index 0000000..dc451ea
--- /dev/null
+++ b/src/main/java/org/fest/reflect/method/package.html
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API for
+method invocation via the Java Reflection API.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Equivalent to call 'person.setName("Luke")'
+ {@link org.fest.reflect.core.Reflection#method(String) method}("setName").{@link org.fest.reflect.method.MethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ .{@link org.fest.reflect.method.MethodParameterTypes#in(Object) in}(person)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Luke");
+
+ // Equivalent to call 'person.concentrate()'
+ {@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}();
+
+ // Equivalent to call 'person.getName()'
+ String name = {@link org.fest.reflect.core.Reflection#method(String) method}("getName").{@link org.fest.reflect.method.MethodName#withReturnType(Class) withReturnType}(String.class)
+ .{@link org.fest.reflect.method.MethodReturnType#in(Object) in}(person)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+
+ // Equivalent to call 'Jedi.class.setCommonPower("Jump")'
+ {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("setCommonPower").{@link org.fest.reflect.method.StaticMethodName#withParameterTypes(Class...) withParameterTypes}(String.class)
+ .{@link org.fest.reflect.method.StaticMethodParameterTypes#in(Class) in}(Jedi.class)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}("Jump");
+
+ // Equivalent to call 'Jedi.class.addPadawan()'
+ {@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}();
+
+ // Equivalent to call 'Jedi.class.commonPowerCount()'
+ String name = {@link org.fest.reflect.core.Reflection#staticMethod(String) staticMethod}("commonPowerCount").{@link org.fest.reflect.method.StaticMethodName#withReturnType(Class) withReturnType}(String.class)
+ .{@link org.fest.reflect.method.StaticMethodReturnType#in(Class) in}(Jedi.class)
+ .{@link org.fest.reflect.method.Invoker#invoke(Object...) invoke}();
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/reference/TypeRef.java b/src/main/java/org/fest/reflect/reference/TypeRef.java
new file mode 100644
index 0000000..f1c75a9
--- /dev/null
+++ b/src/main/java/org/fest/reflect/reference/TypeRef.java
@@ -0,0 +1,54 @@
+/*
+ * Created on Jan 24, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.reference;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import org.fest.reflect.exception.ReflectionError;
+
+/**
+ * Understands a references a generic type. Based on Neal Gafter's
+ * <code><a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html" target="_blank">TypeReference</a></code>.
+ * @param <T> the generic type in this reference.
+ *
+ * @author crazybob at google.com (Bob Lee)
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public abstract class TypeRef<T> {
+
+ private final Class<?> rawType;
+
+ /**
+ * Creates a new </code>{@link TypeRef}</code>.
+ * @throws ReflectionError if the generic type of this reference is missing type parameter.
+ */
+ public TypeRef() {
+ Type superclass = getClass().getGenericSuperclass();
+ if (superclass instanceof Class<?>) throw new ReflectionError("Missing type parameter.");
+ Type type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
+ rawType = type instanceof Class<?> ? (Class<?>) type : (Class<?>) ((ParameterizedType) type).getRawType();
+ }
+
+ /**
+ * Returns the raw type of the generic type in this reference.
+ * @return the raw type of the generic type in this reference.
+ */
+ public final Class<?> rawType() {
+ return rawType;
+ }
+}
diff --git a/src/main/java/org/fest/reflect/reference/package.html b/src/main/java/org/fest/reflect/reference/package.html
new file mode 100644
index 0000000..905a1b2
--- /dev/null
+++ b/src/main/java/org/fest/reflect/reference/package.html
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides support to use Java Generics overcoming the limitations of erasure. Based on Neal Gafter's
+<a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html" target="_blank">Super Type Tokens</a>.
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/type/Type.java b/src/main/java/org/fest/reflect/type/Type.java
new file mode 100644
index 0000000..c7db279
--- /dev/null
+++ b/src/main/java/org/fest/reflect/type/Type.java
@@ -0,0 +1,113 @@
+/*
+ * Created on Jan 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.type;
+
+import org.fest.reflect.exception.ReflectionError;
+
+import static org.fest.reflect.type.TypeLoader.newLoader;
+import static org.fest.util.Strings.isEmpty;
+
+/**
+ * Understands loading a class dynamically.
+ * <p>
+ * The following is an example of proper usage of this class:
+ *
+ * <pre>
+ * // Loads the class 'org.republic.Jedi'
+ * Class<?> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#load() load}();
+ *
+ * // Loads the class 'org.republic.Jedi' as 'org.republic.Person' (Jedi extends Person)
+ * Class<Person> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#loadAs(Class) loadAs}(Person.class);
+ *
+ * // Loads the class 'org.republic.Jedi' using a custom class loader
+ * Class<?> 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}();
+ * </pre>
+ * </p>
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public final class Type {
+
+ /**
+ * Creates a new <code>{@link Type}</code>: the starting point of the fluent interface for loading classes dynamically.
+ * @param name the name of the class to load.
+ * @return the created <code>Type</code>.
+ * @throws NullPointerException if the given name is <code>null</code>.
+ * @throws IllegalArgumentException if the given name is empty.
+ */
+ public static Type newType(String name) {
+ if (name == null) throw new NullPointerException("The name of the class to load should not be null");
+ if (isEmpty(name)) throw new IllegalArgumentException("The name of the class to load should not be empty");
+ return new Type(name);
+ }
+
+ private final String name;
+
+ private Type(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Loads the class with the name specified in this type, using this class' <code>ClassLoader</code>.
+ * @return the loaded class.
+ * @throws ReflectionError wrapping any error that occurred during class loading.
+ */
+ public Class<?> load() {
+ return newLoader(name, thisClassLoader()).load();
+ }
+
+ /**
+ * Loads the class with the name specified in this type, as the given type, using this class' <code>ClassLoader</code>.
+ * <p>
+ * The following example shows how to use this method. Let's assume that we have the class <code>Jedi</code> that extends the
+ * class <code>Person</code>:
+ *
+ * <pre>
+ * Class<Person> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#loadAs(Class) loadAs}(Person.class);
+ * </pre>
+ * </p>
+ * @param type the given type.
+ * @param <T> the generic type of the type.
+ * @return the loaded class.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ * @throws ReflectionError wrapping any error that occurred during class loading.
+ */
+ public <T> Class<? extends T> loadAs(Class<T> type) {
+ return newLoader(name, thisClassLoader()).loadAs(type);
+ }
+
+ private ClassLoader thisClassLoader() {
+ return getClass().getClassLoader();
+ }
+
+ /**
+ * Specifies the <code>{@link ClassLoader}</code> to use to load the class.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * Class<?> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link TypeLoader#load() load}();
+ * </pre>
+ * </p>
+ * @param classLoader the given <code>ClassLoader</code>.
+ * @return an object responsible of loading a class with the given <code>ClassLoader</code>.
+ * @throws NullPointerException if the given <code>ClassLoader</code> is <code>null</code>.
+ */
+ public TypeLoader withClassLoader(ClassLoader classLoader) {
+ return newLoader(name, classLoader);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/type/TypeLoader.java b/src/main/java/org/fest/reflect/type/TypeLoader.java
new file mode 100644
index 0000000..c520446
--- /dev/null
+++ b/src/main/java/org/fest/reflect/type/TypeLoader.java
@@ -0,0 +1,99 @@
+/*
+ * Created on Jan 28, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.type;
+
+import org.fest.reflect.exception.ReflectionError;
+
+import static org.fest.util.Strings.quote;
+
+/**
+ * Understands loading a class dynamically using a specific <code>{@link ClassLoader}</code>.
+ *
+ * @author Alex Ruiz
+ *
+ * @since 1.1
+ */
+public final class TypeLoader {
+
+ static TypeLoader newLoader(String name, ClassLoader classLoader) {
+ if (classLoader == null) throw new NullPointerException("The given class loader should not be null");
+ return new TypeLoader(name, classLoader);
+ }
+
+ private final String name;
+ private final ClassLoader classLoader;
+
+ private TypeLoader(String name, ClassLoader classLoader) {
+ this.name = name;
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Loads the class with the name specified in this type, using this class' <code>ClassLoader</code>.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * Class<?> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link TypeLoader#load() load}();
+ * </pre>
+ * </p>
+ * @return the loaded class.
+ * @throws ReflectionError wrapping any error that occurred during class loading.
+ */
+ public Class<?> load() {
+ try {
+ return loadType();
+ } catch (Exception e) {
+ throw new ReflectionError(unableToLoadClassMessage(null), e);
+ }
+ }
+
+ /**
+ * Loads the class with the name specified in this type, as the given type, using this class' <code>ClassLoader</code>.
+ * <p>
+ * The following example shows how to use this method. Let's assume that we have the class <code>Jedi</code> that extends the
+ * class <code>Person</code>:
+ *
+ * <pre>
+ * Class<Person> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link TypeLoader#loadAs(Class) loadAs}(Person.class);
+ * </pre>
+ * </p>
+ * @param type the given type.
+ * @param <T> the generic type of the type.
+ * @return the loaded class.
+ * @throws NullPointerException if the given type is <code>null</code>.
+ * @throws ReflectionError wrapping any error that occurred during class loading.
+ */
+ public <T> Class<? extends T> loadAs(Class<T> type) {
+ if (type == null) throw new NullPointerException("The given type should not be null");
+ try {
+ return loadType().asSubclass(type);
+ } catch (Exception e) {
+ throw new ReflectionError(unableToLoadClassMessage(type), e);
+ }
+ }
+
+ private String unableToLoadClassMessage(Class<?> asType) {
+ StringBuilder msg = new StringBuilder();
+ msg.append("Unable to load class ").append(quote(name));
+ if (asType != null) msg.append(" as ").append(asType.getName());
+ msg.append(" using class loader ").append(classLoader);
+ return msg.toString();
+ }
+
+ private Class<?> loadType() throws ClassNotFoundException {
+ return classLoader.loadClass(name);
+ }
+}
diff --git a/src/main/java/org/fest/reflect/type/package.html b/src/main/java/org/fest/reflect/type/package.html
new file mode 100644
index 0000000..6db260e
--- /dev/null
+++ b/src/main/java/org/fest/reflect/type/package.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Provides a "fluent" API for loading classes dynamically.
+</p>
+<p>
+<strong>Note:</strong> Classes in this package are not intended to be used directly. To use them, you need to use the
+class <code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+<p>
+Here are some examples:
+<pre>
+ // import static {@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}.*;
+
+ // Loads the class 'org.republic.Jedi"
+ Class<?> jediType = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link org.fest.reflect.type.Type#load() load}();
+</pre>
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/java/org/fest/reflect/util/Accessibles.java b/src/main/java/org/fest/reflect/util/Accessibles.java
new file mode 100644
index 0000000..1935999
--- /dev/null
+++ b/src/main/java/org/fest/reflect/util/Accessibles.java
@@ -0,0 +1,76 @@
+/*
+ * Created on Jan 1, 2008
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2008-2009 the original author or authors.
+ */
+package org.fest.reflect.util;
+
+import java.lang.reflect.AccessibleObject;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Understands utility methods related to <code>{@link AccessibleObject}</code>s.
+ *
+ * @author Alex Ruiz
+ */
+public final class Accessibles {
+
+ /**
+ * Sets the <code>accessible</code> flag of the given <code>{@link AccessibleObject}</code> to the given <code>boolean</code>
+ * value, ignoring any thrown exception.
+ * @param o the given <code>AccessibleObject</code>.
+ * @param accessible the value to set the <code>accessible</code> flag to.
+ */
+ public static void setAccessibleIgnoringExceptions(AccessibleObject o, boolean accessible) {
+ try {
+ setAccessible(o, accessible);
+ } catch (RuntimeException ignored) {}
+ }
+
+ /**
+ * Sets the <code>accessible</code> flag of the given <code>{@link AccessibleObject}</code> to <code>true</code>.
+ * @param o the given <code>AccessibleObject</code>.
+ * @throws SecurityException if the request is denied.
+ */
+ public static void makeAccessible(AccessibleObject o) {
+ setAccessible(o, true);
+ }
+
+ /**
+ * Sets the <code>accessible</code> flag of the given <code>{@link AccessibleObject}</code> to the given <code>boolean</code>
+ * value.
+ * @param o the given <code>AccessibleObject</code>.
+ * @param accessible the value to set the <code>accessible</code> flag to.
+ * @throws SecurityException if the request is denied.
+ */
+ public static void setAccessible(AccessibleObject o, boolean accessible) {
+ AccessController.doPrivileged(new SetAccessibleAction(o, accessible));
+ }
+
+ private static class SetAccessibleAction implements PrivilegedAction<Void> {
+ private final AccessibleObject o;
+ private final boolean accessible;
+
+ SetAccessibleAction(AccessibleObject o, boolean accessible) {
+ this.o = o;
+ this.accessible = accessible;
+ }
+
+ public Void run() {
+ o.setAccessible(accessible);
+ return null;
+ }
+ }
+
+ private Accessibles() {}
+}
diff --git a/src/main/java/org/fest/reflect/util/Throwables.java b/src/main/java/org/fest/reflect/util/Throwables.java
new file mode 100644
index 0000000..83e5132
--- /dev/null
+++ b/src/main/java/org/fest/reflect/util/Throwables.java
@@ -0,0 +1,41 @@
+/*
+ * Created on Mar 19, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.util;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Understands utility methods related to <code>{@link Throwable}</code>s.
+ *
+ * @author Alex Ruiz
+ * @since 1.2
+ */
+public final class Throwables {
+
+ /**
+ * Obtains the target of the given <code>{@link Throwable}</code>. If the <code>Throwable</code> is a
+ * <code>{@link InvocationTargetException}</code>, this method will return the "target exception" (not the cause.) For other
+ * <code>Throwable</code>s, the same instance is returned unmodified.
+ * @param t the given <code>Throwable</code>.
+ * @return the target exception, if applicable. Otherwise, this method returns the same <code>Throwable</code> passed as
+ * argument.
+ */
+ public static Throwable targetOf(Throwable t) {
+ if (t instanceof InvocationTargetException) return ((InvocationTargetException) t).getTargetException();
+ return t;
+ }
+
+ private Throwables() {}
+}
diff --git a/src/main/java/org/fest/reflect/util/package.html b/src/main/java/org/fest/reflect/util/package.html
new file mode 100644
index 0000000..2e3d332
--- /dev/null
+++ b/src/main/java/org/fest/reflect/util/package.html
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!--
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+
+Copyright @2007-2009 the original author or authors.
+ -->
+</head>
+<body bgcolor="white">
+<p>
+Utility methods.
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
new file mode 100644
index 0000000..5e63e4a
--- /dev/null
+++ b/src/main/javadoc/overview.html
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+</head>
+<body>
+<p>
+This document is the API specification for the <a href="http://code.google.com/p/fest/" target="_blank">FEST</a> Reflection
+Module.
+</p>
+<p>
+In order to use the fluent interface, you need to start with the class
+<code>{@link org.fest.reflect.core.Reflection org.fest.reflect.core.Reflection}</code>.
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/site/changes.xml b/src/site/changes.xml
new file mode 100644
index 0000000..f950cf5
--- /dev/null
+++ b/src/site/changes.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document>
+ <properties>
+ <title>Changelog</title>
+ <author email="alex.ruiz.05 at gmail.com">Alex Ruiz</author>
+ </properties>
+ <body>
+ <release version="1.2" date="2009-11-30" description="Subsequent release">
+ <action dev="alexruiz" type="fix" issue="FEST-68" due-to="Francis ANDRE">
+ Method invocation now rethrow the original exception thrown by the method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="FEST-68" due-to="Francis ANDRE">
+ Constructor invocation now rethrow the original exception thrown by the constructor.
+ </action>
+ <action dev="alexruiz" type="add" issue="FEST-235" due-to="Jean-Francois Poilpret">
+ Added static method 'property(String)' to class Reflection. It returns the starting point of the fluent
+ interface for accessing properties using Bean Instrospection under the hood.
+ </action>
+ <action dev="alexruiz" type="fix" issue="FEST-256">
+ Replaced constructor access in fluent interfaces with static factory methods, resulting in code duplication
+ removal and improved encapsulation.
+ </action>
+ <action dev="alexruiz" type="fix" issue="FEST-257">
+ FEST-Reflect now throws ReflectionError if a static inner class is not found.
+ </action>
+ </release>
+ <release version="1.1" date="2009-02-10" description="Subsequent release">
+ <action dev="alexruiz" type="add" issue="117" due-to="Xavier Dury">
+ Added class org.fest.reflect.type.TypeRef based on Neal Gafter's TypeReference.
+ </action>
+ <action dev="alexruiz" type="add" issue="117" due-to="Xavier Dury">
+ Added support for TypeRef as field type in the fluent interface of the package org.fest.reflect.field.
+ </action>
+ <action dev="alexruiz" type="add" issue="117" due-to="Xavier Dury">
+ Added support for TypeRef as method return type in the fluent interface of the package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="add" issue="194" due-to="Leo Jay">
+ Added support for accessing static inner classes (code in package org.fest.reflect.innerclass.)
+ </action>
+ <action dev="alexruiz" type="add" issue="278" due-to="Stephen Colebourne">
+ Added support for loading class objects via the method 'type(String)' in org.fest.reflect.core.Reflection and
+ the class(es) in the package org.fest.reflect.type.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class Name to FieldName in package org.fest.reflect.field.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class StaticName to StaticFieldName in package org.fest.reflect.field.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class Type to FieldType in package org.fest.reflect.field.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class StaticType to StaticFieldType in package org.fest.reflect.field.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class Name to MethodName in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class StaticName to StaticMethodName in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class ParameterTypes to MethodParameterTypes in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class StaticParameterTypes to StaticMethodParameterTypes in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class ReturnType to MethodReturnType in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="287">
+ Renamed class StaticReturnType to StaticMethodReturnType in package org.fest.reflect.method.
+ </action>
+ <action dev="alexruiz" type="fix" issue="288">
+ All public methods throw NullPointerException if any of their arguments is null.
+ </action>
+ </release>
+ <release version="1.0" date="2009-01-07" description="Subsequent release">
+ <action dev="alexruiz" type="fix">
+ Updated documentation.
+ </action>
+ </release>
+ <release version="0.4" date="2008-02-27" description="Subsequent release">
+ <action dev="alexruiz" type="add" issue="111">
+ Added support for calling static fields and static methods.
+ </action>
+ <action dev="alexruiz" type="fix">
+ Fixed bug in method setAccessible(AccessibleObject, boolean) in org.fest.reflect.util.Accessibles where 'true'
+ was used instead of the specified boolean value.
+ </action>
+ </release>
+ <release version="0.3" date="2008-01-31" description="Subsequent release">
+ <action dev="alexruiz" type="fix" issue="106">
+ Reflection.method now find methods of supertypes.
+ </action>
+ </release>
+ <release version="0.2" date="2008-01-02" description="First public release">
+ <action dev="alexruiz" type="fix">
+ Created class Accessibles to call method 'setAccessible' in an AccessibleObject inside a Privileged Block.
+ </action>
+ <action dev="wanghy" type="fix">
+ Moved class Reflection from package org.fest.reflect to org.fest.reflect.core to remove cyclic dependencies.
+ </action>
+ <action dev="wanghy" type="fix">
+ Moved class ReflectionError from package org.fest.reflect to org.fest.reflect.exception to remove cyclic dependencies.
+ </action>
+ </release>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/site/resources/images/fest-reflect.png b/src/site/resources/images/fest-reflect.png
new file mode 100644
index 0000000..f37eb8b
Binary files /dev/null and b/src/site/resources/images/fest-reflect.png differ
diff --git a/src/site/site.vm b/src/site/site.vm
new file mode 100644
index 0000000..791d34e
--- /dev/null
+++ b/src/site/site.vm
@@ -0,0 +1,369 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+#macro ( link $href $name )
+ #if ( ( $href.toLowerCase().startsWith("http") || $href.toLowerCase().startsWith("https") ) )
+ <a href="$href" class="externalLink">$name</a>
+ #else
+ <a href="$href">$name</a>
+ #end
+#end
+
+#macro ( banner $banner $id )
+ #if ( $banner )
+ #if( $banner.href )
+ <a href="$banner.href" id="$id">
+ #else
+ <span id="$id">
+ #end
+
+ #if( $banner.src )
+ #set ( $src = $banner.src )
+ #if ( ! ( $src.toLowerCase().startsWith("http") || $src.toLowerCase().startsWith("https") ) )
+ #set ( $src = $PathTool.calculateLink( $src, $relativePath ) )
+ #set ( $src = $src.replaceAll( "\\", "/" ) )
+ #end
+ #if ( $banner.alt )
+ #set ( $alt = $banner.alt )
+ #else
+ #set ( $alt = "" )
+ #end
+ <img src="$src" alt="$alt" />
+ #else
+ $banner.name
+ #end
+
+ #if( $banner.href )
+ </a>
+ #else
+ </span>
+ #end
+ #end
+#end
+
+#macro ( links $links )
+ #set ( $counter = 0 )
+ #foreach( $item in $links )
+ #set ( $counter = $counter + 1 )
+ #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+ #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+ #link( $currentItemHref $item.name )
+ #if ( $links.size() > $counter )
+ |
+ #end
+ #end
+#end
+
+#macro ( breadcrumbs $breadcrumbs )
+ #set ( $counter = 0 )
+ #foreach( $item in $breadcrumbs )
+ #set ( $counter = $counter + 1 )
+ #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+ #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+
+ #if ( $currentItemHref == $alignedFileName || $currentItemHref == "" )
+ $item.name
+ #else
+ #link( $currentItemHref $item.name )
+ #end
+ #if ( $breadcrumbs.size() > $counter )
+ >
+ #end
+ #end
+#end
+
+#macro ( displayTree $display $item )
+ #if ( $item && $item.items && $item.items.size() > 0 )
+ #foreach( $subitem in $item.items )
+ #set ( $subitemHref = $PathTool.calculateLink( $subitem.href, $relativePath ) )
+ #set ( $subitemHref = $subitemHref.replaceAll( "\\", "/" ) )
+
+ #if ( $alignedFileName == $subitemHref )
+ #set ( $display = true )
+ #end
+
+ #displayTree( $display $subitem )
+ #end
+ #end
+#end
+
+#macro ( menuItem $item )
+ #set ( $collapse = "none" )
+ #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) )
+ #set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
+
+ #if ( $item && $item.items && $item.items.size() > 0 )
+ #if ( $item.collapse == false )
+ #set ( $collapse = "expanded" )
+ #else
+ ## By default collapsed
+ #set ( $collapse = "collapsed" )
+ #end
+
+ #set ( $display = false )
+ #displayTree( $display $item )
+
+ #if ( $alignedFileName == $currentItemHref || $display )
+ #set ( $collapse = "expanded" )
+ #end
+ #end
+ <li class="$collapse">
+ #if ( $item.img )
+ #if ( ! ( $item.img.toLowerCase().startsWith("http") || $item.img.toLowerCase().startsWith("https") ) )
+ #set ( $src = $PathTool.calculateLink( $item.img, $relativePath ) )
+ #set ( $src = $src.replaceAll( "\\", "/" ) )
+ <img src="$src"/>
+ #else
+ <img src="$item.img" align="absbottom" style="border-width: 0"/>
+ #end
+ #end
+ #if ( $alignedFileName == $currentItemHref )
+ <strong>$item.name</strong>
+ #else
+ #link( $currentItemHref $item.name )
+ #end
+ #if ( $item && $item.items && $item.items.size() > 0 )
+ #if ( $collapse == "expanded" )
+ <ul>
+ #foreach( $subitem in $item.items )
+ #menuItem( $subitem )
+ #end
+ </ul>
+ #end
+ #end
+ </li>
+#end
+
+#macro ( mainMenu $menus )
+ #foreach( $menu in $menus )
+ #if ( $menu.name )
+ <h5>$menu.name</h5>
+ #end
+ #if ( $menu.items && $menu.items.size() > 0 )
+ <ul>
+ #foreach( $item in $menu.items )
+ #menuItem( $item )
+ #end
+ </ul>
+ #end
+ #end
+#end
+
+#macro ( copyright )
+ #if ( $project )
+ #set ( $currentYear = ${currentDate.year} + 1900 )
+
+ #if ( ${project.inceptionYear} && ( ${project.inceptionYear} != ${currentYear.toString()} ) )
+ ${project.inceptionYear}-${currentYear}
+ #else
+ ${currentYear}
+ #end
+
+ #if ( ${project.organization} && ${project.organization.name} )
+ ${project.organization.name}
+ #end
+ #end
+#end
+
+#macro ( publishDate $position $publishDate $version )
+ #if ( $publishDate && $publishDate.format )
+ #set ( $format = $publishDate.format )
+ #else
+ #set ( $format = "yyyy-MM-dd" )
+ #end
+
+ $dateFormat.applyPattern( $format )
+
+ #set ( $dateToday = $dateFormat.format( $currentDate ) )
+
+ #if ( $publishDate && $publishDate.position )
+ #set ( $datePosition = $publishDate.position )
+ #else
+ #set ( $datePosition = "left" )
+ #end
+
+ #if ( $version )
+ #if ( $version.position )
+ #set ( $versionPosition = $version.position )
+ #else
+ #set ( $versionPosition = "left" )
+ #end
+ #end
+
+ #set ( $breadcrumbs = $decoration.body.breadcrumbs )
+ #set ( $links = $decoration.body.links )
+
+ #if ( $datePosition.equalsIgnoreCase( "right" ) && $links && $links.size() > 0 )
+ #set ( $prefix = " |" )
+ #else
+ #set ( $prefix = "" )
+ #end
+
+ #if ( $datePosition.equalsIgnoreCase( $position ) )
+ #if ( ( $datePosition.equalsIgnoreCase( "right" ) ) || ( $datePosition.equalsIgnoreCase( "bottom" ) ) )
+ $prefix $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+ #if ( $versionPosition.equalsIgnoreCase( $position ) )
+ | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ #end
+ #elseif ( ( $datePosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $datePosition.equalsIgnoreCase( "navigation-top" ) ) )
+ <div id="lastPublished">
+ $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+ #if ( $versionPosition.equalsIgnoreCase( $position ) )
+ | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ #end
+ </div>
+ #elseif ( $datePosition.equalsIgnoreCase("left") )
+ <div class="xleft">
+ $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday
+ #if ( $versionPosition.equalsIgnoreCase( $position ) )
+ | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ #end
+ #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+ | #breadcrumbs( $breadcrumbs )
+ #end
+ </div>
+ #end
+ #elseif ( $versionPosition.equalsIgnoreCase( $position ) )
+ #if ( ( $versionPosition.equalsIgnoreCase( "right" ) ) || ( $versionPosition.equalsIgnoreCase( "bottom" ) ) )
+ $prefix $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ #elseif ( ( $versionPosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $versionPosition.equalsIgnoreCase( "navigation-top" ) ) )
+ <div id="lastPublished">
+ $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ </div>
+ #elseif ( $versionPosition.equalsIgnoreCase("left") )
+ <div class="xleft">
+ $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version}
+ #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+ | #breadcrumbs( $breadcrumbs )
+ #end
+ </div>
+ #end
+ #elseif ( $position.equalsIgnoreCase( "left" ) )
+ #if ( $breadcrumbs && $breadcrumbs.size() > 0 )
+ <div class="xleft">
+ #breadcrumbs( $breadcrumbs )
+ </div>
+ #end
+ #end
+#end
+
+#macro ( poweredByLogo $poweredBy )
+ #if( $poweredBy )
+ #foreach ($item in $poweredBy)
+ #if( $item.href )
+ #set ( $href = $PathTool.calculateLink( $item.href, $relativePath ) )
+ #set ( $href = $href.replaceAll( "\\", "/" ) )
+ #else
+ #set ( $href="http://maven.apache.org/" )
+ #end
+
+ #if( $item.name )
+ #set ( $name = $item.name )
+ #else
+ #set ( $name = $i18n.getString( "site-renderer", $locale, "template.builtby" ) )
+ #set ( $name = "${name} Maven" )
+ #end
+
+ #if( $item.img )
+ #set ( $img = $item.img )
+ #else
+ #set ( $img = "images/logos/maven-feather.png" )
+ #end
+
+ <a href="$href" title="$name" class="poweredBy">
+ #set ( $img = $PathTool.calculateLink( $img, $relativePath ) )
+ #set ( $img = $img.replaceAll( "\\", "/" ) )
+ <img alt="$name" src="$img" />
+ </a>
+ #end
+ #if( $poweredBy.isEmpty() )
+ <a href="http://maven.apache.org/" title="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" class="poweredBy">
+ <img alt="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" src="$relativePath/images/logos/maven-feather.png"></img>
+ </a>
+ #end
+ #else
+ <a href="http://maven.apache.org/" title="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" class="poweredBy">
+ <img alt="$i18n.getString( "site-renderer", $locale, "template.builtby" ) Maven" src="$relativePath/images/logos/maven-feather.png"></img>
+ </a>
+ #end
+#end
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>$title</title>
+ <style type="text/css" media="all">
+ @import url("$relativePath/css/maven-base.css");
+ @import url("$relativePath/css/maven-theme.css");
+ @import url("$relativePath/css/site.css");
+ </style>
+ <link rel="stylesheet" href="$relativePath/css/print.css" type="text/css" media="print" />
+ #foreach( $author in $authors )
+ <meta name="author" content="$author" />
+ #end
+ <meta http-equiv="Content-Type" content="text/html; charset=${outputEncoding}" />
+ #if ( $decoration.body.head )
+ #foreach( $item in $decoration.body.head.getChildren() )
+ ## Workaround for DOXIA-150 due to a non-desired behaviour in p-u
+ ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toString()
+ ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toUnescapedString()
+ #set ( $documentHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" )
+ #set ( $documentHeader = $documentHeader.replaceAll( "\\", "" ) )
+ #if ( $item.name == "script" )
+ $StringUtils.replace( $item.toUnescapedString(), $documentHeader, "" )
+ #else
+ $StringUtils.replace( $item.toString(), $documentHeader, "" )
+ #end
+ #end
+ #end
+ </head>
+ <body class="composite">
+ <div id="banner">
+ #banner( $decoration.bannerLeft "bannerLeft" )
+ #banner( $decoration.bannerRight "bannerRight" )
+ <span id="bannerRight">
+ </span>
+ <div class="clear">
+ <hr/>
+ </div>
+ </div>
+ <div id="breadcrumbs">
+ #publishDate( "left" $decoration.publishDate $decoration.version )
+ <div class="xright">
+ <a href="http://code.google.com/p/fest" target="_blank">FEST @ Google Code</a>
+ </div>
+ <div class="clear">
+ <hr/>
+ </div>
+ </div>
+ <div id="leftColumn">
+ <div id="navcolumn">
+ #publishDate( "navigation-top" $decoration.publishDate $decoration.version )
+ #mainMenu( $decoration.body.menus )
+ <a href="http://maven.apache.org" target="_blank" title="Build with Maven 2" class="poweredBy">
+ <img alt="Build with Maven 2" src="./images/maven.png">
+ </a>
+ <p></p>
+ #publishDate( "navigation-bottom" $decoration.publishDate $decoration.version )
+ </div>
+ </div>
+ <div id="bodyColumn">
+ <div id="contentBox">
+ $bodyContent
+ </div>
+ </div>
+ <div class="clear">
+ <hr/>
+ </div>
+ <div id="footer">
+ <div class="xright">©#copyright()#publishDate( "bottom" $decoration.publishDate $decoration.version )</div>
+ <div class="clear">
+ <hr/>
+ </div>
+ </div>
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-847284-6";
+urchinTracker();
+</script>
+ </body>
+</html>
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..89e12d2
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="FEST-Reflect">
+ <skin>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-site-skin</artifactId>
+ <version>1.0</version>
+ </skin>
+ <bannerLeft>
+ <name>FEST-Reflect</name>
+ <src>/images/fest-reflect.png</src>
+ <href>index.php</href>
+ </bannerLeft>
+ <poweredBy>
+ <logo name="Built with Maven 2" href="http://maven.apache.org"
+ img="images/logos/maven-feather.png" />
+ </poweredBy>
+
+ <body>
+ <breadcrumbs>
+ <item name="FEST" href="../index.php" />
+ <item name="Reflection" href="index.php"/>
+ </breadcrumbs>
+ <menu ref="reports"/>
+ </body>
+</project>
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
new file mode 100644
index 0000000..00ef862
--- /dev/null
+++ b/src/site/xdoc/index.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document>
+
+ <properties>
+ <title>Welcome</title>
+ <!--meta HTTP-EQUIV="REFRESH" content="0; url=http://fest.easytesting.org/reflect/index.php" /-->
+ </properties>
+
+ <body>
+ <p>
+ You are being redirected to the <a href="index.php">wiki page</a>.
+ </p>
+ </body>
+</document>
\ No newline at end of file
diff --git a/src/test/java/org/fest/reflect/Jedi.java b/src/test/java/org/fest/reflect/Jedi.java
new file mode 100644
index 0000000..4ca14e2
--- /dev/null
+++ b/src/test/java/org/fest/reflect/Jedi.java
@@ -0,0 +1,114 @@
+/*
+ * Created on May 18, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Understands a Jedi.
+ *
+ * @author Alex Ruiz
+ */
+public class Jedi extends Person {
+
+ private static List<String> commonPowers = new ArrayList<String>();
+
+ private final List<String> powers = new ArrayList<String>();
+ private boolean master;
+
+ public Jedi(String name) {
+ super(name);
+ }
+
+ public void addPower(String power) {
+ powers.add(power);
+ }
+
+ public String powerAt(int index) {
+ return powers.get(index);
+ }
+
+ public int powerCount() {
+ return powers.size();
+ }
+
+ public void clearPowers() {
+ powers.clear();
+ }
+
+ public void makeMaster() {
+ master = true;
+ }
+
+ public List<String> powers() {
+ return getPowers();
+ }
+
+ public List<String> getPowers() {
+ return new ArrayList<String>(powers);
+ }
+
+ public void setPowers(List<String> newPowers) {
+ powers.clear();
+ powers.addAll(newPowers);
+ }
+
+ public List<String> powersThatStartWith(String prefix) {
+ List<String> sub = new ArrayList<String>();
+ for (String power : powers)
+ if (power != null && power.startsWith(prefix)) sub.add(power);
+ return sub;
+ }
+
+ public boolean isMaster() {
+ return master;
+ }
+
+ public void throwRuntimeException() {
+ throw new IllegalStateException("Somehow I got in an illegal state");
+ }
+
+ public void throwCheckedException() throws Exception {
+ throw new Exception("I don't know what's wrong");
+ }
+
+ public static void addCommonPower(String power) {
+ commonPowers.add(power);
+ }
+
+ public static String commonPowerAt(int index) {
+ return commonPowers.get(index);
+ }
+
+ public static int commonPowerCount() {
+ return commonPowers.size();
+ }
+
+ public static void clearCommonPowers() {
+ commonPowers.clear();
+ }
+
+ public static List<String> commonPowers() {
+ return new ArrayList<String>(commonPowers);
+ }
+
+ public static List<String> commonPowersThatStartWith(String prefix) {
+ List<String> sub = new ArrayList<String>();
+ for (String power : commonPowers)
+ if (power != null && power.startsWith(prefix)) sub.add(power);
+ return sub;
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/fest/reflect/Person.java b/src/test/java/org/fest/reflect/Person.java
new file mode 100644
index 0000000..58bdcc2
--- /dev/null
+++ b/src/test/java/org/fest/reflect/Person.java
@@ -0,0 +1,57 @@
+/*
+ * Created on May 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect;
+
+/**
+ * Understands a person.
+ *
+ * @author Yvonne Wang
+ */
+public class Person {
+
+ private static int count;
+
+ private String name;
+
+ public Person() {}
+
+ public Person(String name) {
+ setName(name);
+ }
+
+ public Person(int name) {
+ throw new IllegalArgumentException("The name of a person cannot be a number");
+ }
+
+ public Person(Person person) throws Exception {
+ throw new Exception("A person cannot be created from another person");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public static int getCount() {
+ return count;
+ }
+
+ public static void setCount(int count) {
+ Person.count = count;
+ }
+}
diff --git a/src/test/java/org/fest/reflect/beanproperty/Property_Test.java b/src/test/java/org/fest/reflect/beanproperty/Property_Test.java
new file mode 100644
index 0000000..cf8214a
--- /dev/null
+++ b/src/test/java/org/fest/reflect/beanproperty/Property_Test.java
@@ -0,0 +1,165 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.beanproperty;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+import static org.fest.util.Lists.newArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.beans.PropertyDescriptor;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.Person;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for accessing properties.
+ *
+ * @author Alex Ruiz
+ */
+public class Property_Test {
+
+ private Person person;
+
+ @Before
+ public void setUp() {
+ person = new Person("Luke");
+ }
+
+ @Test
+ public void should_throw_error_if_property_name_is_null() {
+ expectNullPointerException("The name of the property to access should not be null").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_property_name_is_empty() {
+ expectIllegalArgumentException("The name of the property to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_property_type_is_null() {
+ expectNullPointerException("The type of the property to access should not be null").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("name").ofType((Class<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_target_is_null() {
+ expectNullPointerException("Target should not be null").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("name").ofType(String.class).in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_property_value() {
+ String personName = PropertyName.startPropertyAccess("name").ofType(String.class).in(person).get();
+ assertEquals("Luke", personName);
+ }
+
+ @Test
+ public void should_get_property_value_defined_in_object_class() {
+ Class<?> personClass = PropertyName.startPropertyAccess("class").ofType(Class.class).in(person).get();
+ assertEquals(Person.class, personClass);
+ }
+
+ @Test
+ public void should_set_property_value() {
+ PropertyName.startPropertyAccess("name").ofType(String.class).in(person).set("Leia");
+ assertEquals("Leia", person.getName());
+ }
+
+ @Test
+ public void should_return_real_property() {
+ PropertyDescriptor property = PropertyName.startPropertyAccess("name").ofType(String.class).in(person).info();
+ assertNotNull(property);
+ assertEquals("name", property.getName());
+ assertEquals(String.class, property.getPropertyType());
+ }
+
+ @Test
+ public void should_throw_error_if_wrong_property_type_was_specified() {
+ String message = "The type of the property 'name' in org.fest.reflect.Person should be <java.lang.Integer> but was <java.lang.String>";
+ expectReflectionError(message).on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("name").ofType(Integer.class).in(person).get();
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_property_name_is_invalid() {
+ expectReflectionError("Unable to find property 'age' in org.fest.reflect.Person").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("age").ofType(Integer.class).in(person);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_property_in_super_type() {
+ Jedi jedi = new Jedi("Yoda");
+ String jediName = PropertyName.startPropertyAccess("name").ofType(String.class).in(jedi).get();
+ assertEquals("Yoda", jediName);
+ }
+
+ @Test
+ public void should_throw_error_if_TypeRef_is_null() {
+ expectNullPointerException("The type reference of the property to access should not be null").on(new CodeToTest() {
+ public void run() {
+ PropertyName.startPropertyAccess("name").ofType((TypeRef<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_use_TypeRef_to_read_property() {
+ Jedi jedi = new Jedi("Yoda");
+ jedi.addPower("heal");
+ List<String> powers = PropertyName.startPropertyAccess("powers").ofType(new TypeRef<List<String>>() {}).in(jedi).get();
+ assertEquals(1, powers.size());
+ assertEquals("heal", powers.get(0));
+
+ }
+
+ @Test
+ public void should_use_TypeRef_to_write_property() {
+ Jedi jedi = new Jedi("Yoda");
+ List<String> powers = newArrayList("heal");
+ PropertyName.startPropertyAccess("powers").ofType(new TypeRef<List<String>>() {}).in(jedi).set(powers);
+ assertEquals(1, jedi.powers().size());
+ assertEquals("heal", jedi.powers().get(0));
+ }
+}
diff --git a/src/test/java/org/fest/reflect/constructor/Constructor_Test.java b/src/test/java/org/fest/reflect/constructor/Constructor_Test.java
new file mode 100644
index 0000000..b909e74
--- /dev/null
+++ b/src/test/java/org/fest/reflect/constructor/Constructor_Test.java
@@ -0,0 +1,107 @@
+/*
+ * Created on May 17, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.constructor;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Constructor;
+
+import org.junit.Test;
+
+import org.fest.reflect.Person;
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for constructors.
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ */
+public class Constructor_Test {
+
+ @Test
+ public void should_create_new_instance_with_default_constructor() {
+ Person person = TargetType.startConstructorAccess().in(Person.class).newInstance();
+ assertNotNull(person);
+ assertNull(person.getName());
+ }
+
+ @Test
+ public void should_create_new_instance_using_given_constructor_parameters() {
+ Person person = TargetType.startConstructorAccess().withParameterTypes(String.class).in(Person.class).newInstance("Yoda");
+ assertNotNull(person);
+ assertEquals("Yoda", person.getName());
+ }
+
+ @Test
+ public void should_return_real_constructor() {
+ Constructor<Person> constructor = TargetType.startConstructorAccess().withParameterTypes(String.class).in(Person.class)
+ .info();
+ assertNotNull(constructor);
+ Class<?>[] parameterTypes = constructor.getParameterTypes();
+ assertEquals(1, parameterTypes.length);
+ assertEquals(String.class, parameterTypes[0]);
+ }
+
+ @Test
+ public void should_throw_error_if_parameter_type_array_is_null() {
+ expectNullPointerException("The array of parameter types should not be null").on(new CodeToTest() {
+ public void run() {
+ TargetType.startConstructorAccess().withParameterTypes((Class<?>[]) null).in(Person.class).info();
+ }
+ });
+ }
+
+ @Test(expected = ReflectionError.class)
+ public void should_throw_error_if_constructor_was_not_found() {
+ Class<Integer> illegalType = Integer.class;
+ TargetType.startConstructorAccess().withParameterTypes(illegalType).in(Person.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void should_throw_error_if_instance_was_not_created() {
+ int illegalArg = 8;
+ TargetType.startConstructorAccess().withParameterTypes(String.class).in(Person.class).newInstance(illegalArg);
+ }
+
+ @Test
+ public void should_rethrow_RuntimeException_thrown_by_constructor() {
+ expectIllegalArgumentException("The name of a person cannot be a number").on(new CodeToTest() {
+ public void run() {
+ TargetType.startConstructorAccess().withParameterTypes(int.class).in(Person.class).newInstance(8);
+ }
+ });
+ }
+
+ @Test
+ public void should_wrap_with_a_ReflectionError_the_checked_Exception_thrown_by_constructor() {
+ try {
+ TargetType.startConstructorAccess().withParameterTypes(Person.class).in(Person.class).newInstance(new Person());
+ fail("Expecting an ReflectionError");
+ } catch (ReflectionError e) {
+ Throwable cause = e.getCause();
+ assertTrue(cause instanceof Exception);
+ assertEquals("A person cannot be created from another person", cause.getMessage());
+ }
+ }
+}
diff --git a/src/test/java/org/fest/reflect/core/FEST68_CatchingWrongExceptions_Test.java b/src/test/java/org/fest/reflect/core/FEST68_CatchingWrongExceptions_Test.java
new file mode 100644
index 0000000..010f8fb
--- /dev/null
+++ b/src/test/java/org/fest/reflect/core/FEST68_CatchingWrongExceptions_Test.java
@@ -0,0 +1,60 @@
+/*
+ * Created on Mar 19, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.core;
+
+import static org.fest.reflect.core.Reflection.constructor;
+import static org.fest.reflect.core.Reflection.method;
+
+import org.junit.Test;
+
+/**
+ * Tests for <a href="http://jira.codehaus.org/browse/FEST-68" target="_blank">FEST-68</a>.
+ *
+ * @author Francis ANDRE
+ * @author Alex Ruiz
+ */
+public class FEST68_CatchingWrongExceptions_Test {
+
+ @Test(expected = MyRuntimeException.class)
+ public void should_not_catch_RuntimeException_when_calling_method() {
+ Main main = new Main();
+ method("set").in(main).invoke();
+ }
+
+ @Test(expected = MyRuntimeException.class)
+ public void should_not_catch_RuntimeException_when_calling_constructor() {
+ constructor().withParameterTypes(String.class).in(Main.class).newInstance("Hello");
+ }
+
+ static class MyRuntimeException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public MyRuntimeException(String text) {
+ super(text);
+ }
+ }
+
+ public static class Main {
+ public Main() {}
+
+ public Main(String hello) {
+ throw new MyRuntimeException("set");
+ }
+
+ public void set() {
+ throw new MyRuntimeException("set");
+ }
+ }
+}
diff --git a/src/test/java/org/fest/reflect/core/Reflection_Test.java b/src/test/java/org/fest/reflect/core/Reflection_Test.java
new file mode 100644
index 0000000..e842599
--- /dev/null
+++ b/src/test/java/org/fest/reflect/core/Reflection_Test.java
@@ -0,0 +1,81 @@
+/*
+ * Created on May 18, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.core;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import org.fest.reflect.beanproperty.PropertyName;
+import org.fest.reflect.constructor.TargetType;
+import org.fest.reflect.field.FieldName;
+import org.fest.reflect.field.StaticFieldName;
+import org.fest.reflect.innerclass.StaticInnerClassName;
+import org.fest.reflect.method.MethodName;
+import org.fest.reflect.method.StaticMethodName;
+import org.fest.reflect.type.Type;
+
+/**
+ * Tests for <code>{@link Reflection}</code>.
+ *
+ * @author Alex Ruiz
+ * @author Yvonne Wang
+ */
+public class Reflection_Test {
+
+ @Test
+ public void should_return_fluent_interface_for_constructor() {
+ verifyTypesAreEqual(TargetType.class, Reflection.constructor());
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_field() {
+ verifyTypesAreEqual(FieldName.class, Reflection.field("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_static_field() {
+ verifyTypesAreEqual(StaticFieldName.class, Reflection.staticField("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_method() {
+ verifyTypesAreEqual(MethodName.class, Reflection.method("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_static_method() {
+ verifyTypesAreEqual(StaticMethodName.class, Reflection.staticMethod("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_type() {
+ verifyTypesAreEqual(Type.class, Reflection.type("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_static_inner_class() {
+ verifyTypesAreEqual(StaticInnerClassName.class, Reflection.staticInnerClass("foo"));
+ }
+
+ @Test
+ public void should_return_fluent_interface_for_property() {
+ verifyTypesAreEqual(PropertyName.class, Reflection.property("foo"));
+ }
+
+ private void verifyTypesAreEqual(Class<?> expected, Object o) {
+ assertEquals(expected, o.getClass());
+ }
+}
diff --git a/src/test/java/org/fest/reflect/field/FieldDecoratorCombinedTest.java b/src/test/java/org/fest/reflect/field/FieldDecoratorCombinedTest.java
new file mode 100644
index 0000000..049e360
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/FieldDecoratorCombinedTest.java
@@ -0,0 +1,145 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.core.Reflection.field;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.Test;
+
+/**
+ * Tests returning decorator result in case of a decorator exceptions
+ * @author Ivan Hristov
+ *
+ */
+public class FieldDecoratorCombinedTest {
+
+ public interface IUploadFileService {
+ Boolean upload(String file, String destination) throws CustomeException;
+ }
+
+ public interface INotificationService {
+ void notify(String msg);
+ }
+
+ @SuppressWarnings("serial")
+ public class CustomeException extends RuntimeException {
+ public CustomeException() {
+ super("This is a test exception");
+ }
+ }
+
+ private class FileManager {
+
+ private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+
+ private final IUploadFileService uploadFileService;
+ private INotificationService notificationService;
+
+ public FileManager() {
+ this.uploadFileService = new IUploadFileService() {
+
+ public Boolean upload(String file, String destination) {
+ return false;
+ }
+ };
+ }
+
+ public void manage(String fileName) {
+ notificationService.notify("Upload successful? : " + uploadFileService.upload(fileName, DEFAULT_DESTINATION));
+ }
+ }
+
+ @Test
+ public void should_pre_decorate_field_returning_decorator_result_ignoring_custom_exception_in_decorator() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenThrow(new CustomeException());
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).preDecorateWith(uploadFileServiceMock)//
+ .returningDecoratorResult().ignoringDecoratorExceptionsOfType(CustomeException.class);
+
+ field("notificationService").ofType(INotificationService.class)//
+ .in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq("Upload successful? : null"));
+ }
+
+ @Test
+ public void should_post_decorate_field_returning_decorator_result_ignoring_decorator_exceptions() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenThrow(new RuntimeException());
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).postDecorateWith(uploadFileServiceMock)//
+ .returningDecoratorResult().ignoringDecoratorExceptions();
+
+ field("notificationService").ofType(INotificationService.class)//
+ .in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq("Upload successful? : null"));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_returning_decorator_result_ignoring_decorator_exceptions() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenThrow(new RuntimeException()).thenThrow(
+ new CustomeException());
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager).preDecorateWith(uploadFileServiceMock)
+ .ignoringDecoratorExceptions().returningDecoratorResult().postDecorateWith(uploadFileServiceMock)
+ .ignoringDecoratorExceptionsOfType(CustomeException.class).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(2)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq("Upload successful? : null"));
+ }
+
+}
diff --git a/src/test/java/org/fest/reflect/field/FieldDecoratorIgnoreExceptionTest.java b/src/test/java/org/fest/reflect/field/FieldDecoratorIgnoreExceptionTest.java
new file mode 100644
index 0000000..6d8d0c6
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/FieldDecoratorIgnoreExceptionTest.java
@@ -0,0 +1,204 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.core.Reflection.field;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.net.SocketTimeoutException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.junit.rules.ExpectedException;
+
+/**
+ *
+ * @author Ivan Hristov
+ *
+ */
+public class FieldDecoratorIgnoreExceptionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ public interface IUploadFileService {
+ Boolean upload(String file, String destination) throws SocketTimeoutException;
+ }
+
+ public interface INotifierService {
+ void notify(String msg);
+ }
+
+ private class FileManager {
+
+ private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+
+ private final IUploadFileService uploadFileService;
+ private INotifierService notifierService;
+
+ public FileManager() {
+ this.uploadFileService = new IUploadFileService() {
+
+ public Boolean upload(String file, String destination) {
+ return false;
+ }
+ };
+ }
+
+ public void manage(String fileName) throws SocketTimeoutException {
+ if (uploadFileService.upload(fileName, DEFAULT_DESTINATION)) {
+ System.out.println("File " + fileName + " sent to " + DEFAULT_DESTINATION);
+ } else {
+ notifierService.notify("Unable to send msg!");
+ }
+ }
+ }
+
+ @Test
+ public void should_not_ignore_pre_decorator_exceptions() throws SocketTimeoutException {
+ // GIVEN
+ expectedException.expect(SocketTimeoutException.class);
+ String expectedExceptionMsg = "Expected test exception";
+ expectedException.expectMessage(JUnitMatchers.containsString(expectedExceptionMsg));
+
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotifierService notifierServiceMock = mock(INotifierService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenThrow(new SocketTimeoutException(expectedExceptionMsg));
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).preDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions();
+
+ field("notifierService").ofType(INotifierService.class).in(fileManager).set(notifierServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN there should be an exception
+ }
+
+ @Test
+ public void should_not_ignore_post_decorator_exceptions() throws SocketTimeoutException {
+ // GIVEN
+ expectedException.expect(SocketTimeoutException.class);
+ String expectedExceptionMsg = "Expected test exception";
+ expectedException.expectMessage(JUnitMatchers.containsString(expectedExceptionMsg));
+
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotifierService notifierServiceMock = mock(INotifierService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenThrow(new SocketTimeoutException(expectedExceptionMsg));
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).postDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions();
+
+ field("notifierService").ofType(INotifierService.class).in(fileManager).set(notifierServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN there should be an exception
+ }
+
+ @Test
+ public void should_pre_decorate_field_ignoring_decorator_exceptions() throws SocketTimeoutException {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotifierService notifierServiceMock = mock(INotifierService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenThrow(new RuntimeException("Expected test exception"));
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).preDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions();
+
+ field("notifierService").ofType(INotifierService.class).in(fileManager).set(notifierServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(notifierServiceMock, times(1)).notify(eq("Unable to send msg!"));
+ }
+
+ @Test
+ public void should_post_decorate_field_ignoring_decorator_exceptions() throws SocketTimeoutException {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotifierService notifierServiceMock = mock(INotifierService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenThrow(new RuntimeException("Expected test exception"));
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).postDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions();
+
+ field("notifierService").ofType(INotifierService.class).in(fileManager).set(notifierServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ verify(notifierServiceMock, times(1)).notify(eq("Unable to send msg!"));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_ignoring_decorator_exceptions() throws SocketTimeoutException {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotifierService notifierServiceMock = mock(INotifierService.class);
+
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenThrow(new SocketTimeoutException("Expected test exception"))//
+ .thenThrow(new RuntimeException("Expected test exception"))//
+ .thenThrow(new RuntimeException("Expected test exception"));
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)//
+ .preDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions()//
+ .postDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptions()//
+ .preDecorateWith(uploadFileServiceMock).ignoringDecoratorExceptionsOfType(SocketTimeoutException.class);
+
+ field("notifierService").ofType(INotifierService.class).in(fileManager).set(notifierServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(3)).upload(eq("testFileName"), anyString());
+ verify(notifierServiceMock, times(1)).notify(eq("Unable to send msg!"));
+ }
+
+}
diff --git a/src/test/java/org/fest/reflect/field/FieldDecoratorReturningDecoratorResultTest.java b/src/test/java/org/fest/reflect/field/FieldDecoratorReturningDecoratorResultTest.java
new file mode 100644
index 0000000..fc5dece
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/FieldDecoratorReturningDecoratorResultTest.java
@@ -0,0 +1,214 @@
+/*
+ * Created on Mar 20, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.core.Reflection.field;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.Test;
+
+/**
+ *
+ * @author Ivan Hristov
+ *
+ */
+public class FieldDecoratorReturningDecoratorResultTest {
+
+ public interface IUploadFileService {
+ String upload(String file, String destination);
+ }
+
+ public interface INotificationService {
+ void notify(String msg);
+ }
+
+ private class FileManager {
+
+ private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+
+ private final IUploadFileService uploadFileService;
+ private INotificationService notificationService;
+
+ public FileManager() {
+ this.uploadFileService = new IUploadFileService() {
+
+ public String upload(String file, String destination) {
+ return "Default result";
+ }
+ };
+ }
+
+ public void manage(String fileName) {
+ notificationService.notify(uploadFileService.upload(fileName, DEFAULT_DESTINATION));
+ }
+ }
+
+ @Test
+ public void should_pre_decorate_field_and_return_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "pre-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenReturn(expectedResult);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).preDecorateWith(uploadFileServiceMock).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+
+ @Test
+ public void should_post_decorate_field_and_return_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "post-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenReturn(expectedResult);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).postDecorateWith(uploadFileServiceMock).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_and_return_pre_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "pre-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenReturn(expectedResult).thenReturn("post-decorator result");
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)//
+ .preDecorateWith(uploadFileServiceMock).returningDecoratorResult().postDecorateWith(uploadFileServiceMock);
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(2)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_and_return_post_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "post-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString())).thenReturn("pre-decorator result").thenReturn(expectedResult);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)//
+ .preDecorateWith(uploadFileServiceMock).postDecorateWith(uploadFileServiceMock).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(2)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_both_returning_results_but_return_post_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "post-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenReturn("pre-decorator result").thenReturn(expectedResult);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)//
+ .preDecorateWith(uploadFileServiceMock).returningDecoratorResult()//
+ .postDecorateWith(uploadFileServiceMock).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(2)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field_both_returning_results_but_return_pre_decorator_result() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+ INotificationService notificationServiceMock = mock(INotificationService.class);
+
+ String expectedResult = "pre-decorator result";
+ when(uploadFileServiceMock.upload(anyString(), anyString()))//
+ .thenReturn(expectedResult).thenReturn("post-decorator result");
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)//
+ .postDecorateWith(uploadFileServiceMock).returningDecoratorResult()//
+ .preDecorateWith(uploadFileServiceMock).returningDecoratorResult();
+
+ field("notificationService").ofType(INotificationService.class).in(fileManager).set(notificationServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(2)).upload(eq("testFileName"), anyString());
+ verify(notificationServiceMock, times(1)).notify(eq(expectedResult));
+ }
+}
diff --git a/src/test/java/org/fest/reflect/field/FieldDecoratorTest.java b/src/test/java/org/fest/reflect/field/FieldDecoratorTest.java
new file mode 100644
index 0000000..23ef773
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/FieldDecoratorTest.java
@@ -0,0 +1,184 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.core.Reflection.field;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+
+/**
+ *
+ * @author Ivan Hristov
+ *
+ */
+public class FieldDecoratorTest {
+
+ private static class LogMyName {
+
+ private final ILogger logger = new MySmartLogger(this.getClass());
+ private final String name;
+
+ public LogMyName(String name) {
+ this.name = name;
+ }
+
+ public void logMyName() {
+ logger.info(name);
+ }
+ }
+
+ private static class MySmartLogger implements ILogger {
+ private final Class<?> _clazz;
+
+ public MySmartLogger(Class<?> _clazz) {
+ this._clazz = _clazz;
+ }
+
+ public void info(String infoStr) {
+ System.out.println(_clazz.getSimpleName() + " : " + infoStr);
+ }
+ }
+
+ public interface ILogger {
+ public void info(String infoStr);
+ }
+
+ @Test
+ public void should_pre_decorate_field() {
+ // GIVEN
+ ILogger mySmartLoggerMock = mock(ILogger.class);
+
+ LogMyName logMyName = new LogMyName("FEST");
+
+ field("logger").ofType(ILogger.class).in(logMyName).preDecorateWith(mySmartLoggerMock);
+
+ // WHEN
+ logMyName.logMyName();
+
+ // THEN
+ verify(mySmartLoggerMock, times(1)).info(eq("FEST"));
+ }
+
+ public interface IUploadFileService {
+ boolean upload(String file, String destination);
+ }
+
+ private class FileManager {
+
+ private static final String DEFAULT_DESTINATION = "http://example.org/default/destination/";
+
+ private final IUploadFileService uploadFileService;
+
+ public FileManager() {
+ this.uploadFileService = new IUploadFileService() {
+
+ public boolean upload(String file, String destination) {
+ return false;
+ }
+ };
+ }
+
+ public void manage(String fileName) {
+ if (uploadFileService.upload(fileName, DEFAULT_DESTINATION)) {
+ System.out.println("File " + fileName + " sent to " + DEFAULT_DESTINATION);
+ } else {
+ System.out.println("Unable to sent " + fileName + " to " + DEFAULT_DESTINATION);
+ }
+ }
+ }
+
+ @Test
+ public void should_attach_two_pre_decorators() {
+ // GIVEN
+ IUploadFileService firstUploadFileServiceMock = mock(IUploadFileService.class);
+ IUploadFileService secondUploadFileServiceMock = mock(IUploadFileService.class);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).preDecorateWith(firstUploadFileServiceMock).preDecorateWith(secondUploadFileServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ InOrder inOrder = inOrder(firstUploadFileServiceMock, secondUploadFileServiceMock);
+ inOrder.verify(secondUploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ inOrder.verify(firstUploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ }
+
+ @Test
+ public void should_post_decorate_field() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager).postDecorateWith(uploadFileServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ }
+
+ @Test
+ public void should_attach_two_post_decorators() {
+ // GIVEN
+ IUploadFileService firstUploadFileServiceMock = mock(IUploadFileService.class);
+ IUploadFileService secondUploadFileServiceMock = mock(IUploadFileService.class);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class)//
+ .in(fileManager).postDecorateWith(firstUploadFileServiceMock).postDecorateWith(secondUploadFileServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ InOrder inOrder = inOrder(firstUploadFileServiceMock, secondUploadFileServiceMock);
+ inOrder.verify(firstUploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ inOrder.verify(secondUploadFileServiceMock, times(1)).upload(eq("testFileName"), anyString());
+ }
+
+ @Test
+ public void should_pre_and_post_decorate_field() {
+ // GIVEN
+ IUploadFileService uploadFileServiceMock = mock(IUploadFileService.class);
+
+ FileManager fileManager = new FileManager();
+
+ field("uploadFileService").ofType(IUploadFileService.class).in(fileManager)
+ //
+ .preDecorateWith(uploadFileServiceMock).postDecorateWith(uploadFileServiceMock).preDecorateWith(uploadFileServiceMock);
+
+ // WHEN
+ String fileName = "testFileName";
+ fileManager.manage(fileName);
+
+ // THEN
+ verify(uploadFileServiceMock, times(3)).upload(eq("testFileName"), anyString());
+ }
+
+}
diff --git a/src/test/java/org/fest/reflect/field/Field_field_Test.java b/src/test/java/org/fest/reflect/field/Field_field_Test.java
new file mode 100644
index 0000000..19405c2
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/Field_field_Test.java
@@ -0,0 +1,157 @@
+/*
+ * Created on May 18, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+import static org.fest.util.Lists.newArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.Person;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for accessing fields.
+ *
+ * @author Alex Ruiz
+ */
+public class Field_field_Test {
+
+ private Person person;
+
+ @Before
+ public void setUp() {
+ person = new Person("Luke");
+ }
+
+ @Test
+ public void should_throw_error_if_field_name_is_null() {
+ expectNullPointerException("The name of the field to access should not be null").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_field_name_is_empty() {
+ expectIllegalArgumentException("The name of the field to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_field_type_is_null() {
+ expectNullPointerException("The type of the field to access should not be null").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("name").ofType((Class<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_target_is_null() {
+ expectNullPointerException("Target should not be null").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("name").ofType(String.class).in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_field_value() {
+ String personName = FieldName.beginFieldAccess("name").ofType(String.class).in(person).get();
+ assertEquals("Luke", personName);
+ }
+
+ @Test
+ public void should_set_field_value() {
+ FieldName.beginFieldAccess("name").ofType(String.class).in(person).set("Leia");
+ assertEquals("Leia", person.getName());
+ }
+
+ @Test
+ public void should_return_real_field() {
+ java.lang.reflect.Field field = FieldName.beginFieldAccess("name").ofType(String.class).in(person).info();
+ assertNotNull(field);
+ assertEquals("name", field.getName());
+ assertEquals(String.class, field.getType());
+ }
+
+ @Test
+ public void should_throw_error_if_wrong_field_type_was_specified() {
+ String msg = "The type of the field 'name' in org.fest.reflect.Person should be <java.lang.Integer> but was <java.lang.String>";
+ expectReflectionError(msg).on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("name").ofType(Integer.class).in(person).get();
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_field_name_is_invalid() {
+ expectReflectionError("Unable to find field 'age' in org.fest.reflect.Person").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("age").ofType(Integer.class).in(person);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_field_in_super_type() {
+ Jedi jedi = new Jedi("Yoda");
+ String jediName = FieldName.beginFieldAccess("name").ofType(String.class).in(jedi).get();
+ assertEquals("Yoda", jediName);
+ }
+
+ @Test
+ public void should_throw_error_if_TypeRef_is_null() {
+ expectNullPointerException("The type reference of the field to access should not be null").on(new CodeToTest() {
+ public void run() {
+ FieldName.beginFieldAccess("name").ofType((TypeRef<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_use_TypeRef_to_read_field() {
+ Jedi jedi = new Jedi("Yoda");
+ jedi.addPower("heal");
+ List<String> powers = FieldName.beginFieldAccess("powers").ofType(new TypeRef<List<String>>() {}).in(jedi).get();
+ assertEquals(1, powers.size());
+ assertEquals("heal", powers.get(0));
+ }
+
+ @Test
+ public void should_use_TypeRef_to_write_field() {
+ Jedi jedi = new Jedi("Yoda");
+ List<String> powers = newArrayList("heal");
+ FieldName.beginFieldAccess("powers").ofType(new TypeRef<List<String>>() {}).in(jedi).set(powers);
+ assertEquals(1, jedi.powers().size());
+ assertEquals("heal", jedi.powers().get(0));
+ }
+}
diff --git a/src/test/java/org/fest/reflect/field/Field_staticField_Test.java b/src/test/java/org/fest/reflect/field/Field_staticField_Test.java
new file mode 100644
index 0000000..97e15a2
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/Field_staticField_Test.java
@@ -0,0 +1,151 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+import static org.fest.util.Lists.newArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.Person;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for accessing static fields.
+ *
+ * @author Alex Ruiz
+ */
+public class Field_staticField_Test {
+
+ @Test
+ public void should_throw_error_if_static_field_name_is_null() {
+ expectNullPointerException("The name of the static field to access should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_field_name_is_empty() {
+ expectIllegalArgumentException("The name of the static field to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_field_type_is_null() {
+ expectNullPointerException("The type of the static field to access should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("name").ofType((Class<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_target_is_null() {
+ expectNullPointerException("Target should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("age").ofType(int.class).in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_static_field_value() {
+ Person.setCount(6);
+ int count = StaticFieldName.beginStaticFieldAccess("count").ofType(int.class).in(Person.class).get();
+ assertEquals(6, count);
+ }
+
+ @Test
+ public void should_set_static_field_value() {
+ StaticFieldName.beginStaticFieldAccess("count").ofType(int.class).in(Person.class).set(8);
+ assertEquals(8, Person.getCount());
+ }
+
+ @Test
+ public void should_return_real_static_field() {
+ java.lang.reflect.Field field = StaticFieldName.beginStaticFieldAccess("count").ofType(int.class).in(Person.class).info();
+ assertNotNull(field);
+ assertEquals("count", field.getName());
+ assertEquals(int.class, field.getType());
+
+ }
+
+ @Test
+ public void should_throw_error_if_wrong_static_field_type_was_specified() {
+ String msg = "The type of the field 'count' in org.fest.reflect.Person should be <java.lang.Float> but was <int>";
+ expectReflectionError(msg).on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("count").ofType(Float.class).in(Person.class).get();
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_field_name_is_invalid() {
+ expectReflectionError("Unable to find field 'age' in org.fest.reflect.Person").on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("age").ofType(int.class).in(Person.class);
+ }
+ });
+ }
+
+ @Test
+ public void should_get_static_field_in_super_type() {
+ Person.setCount(8);
+ int count = StaticFieldName.beginStaticFieldAccess("count").ofType(int.class).in(Person.class).get();
+ assertEquals(8, count);
+ }
+
+ @Test
+ public void should_throw_error_if_TypeRef_is_null() {
+ String msg = "The type reference of the static field to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ StaticFieldName.beginStaticFieldAccess("name").ofType((TypeRef<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_use_TypeRef_to_read_static_field() {
+ Jedi.addCommonPower("jump");
+ List<String> powers = StaticFieldName.beginStaticFieldAccess("commonPowers").ofType(new TypeRef<List<String>>() {})
+ .in(Jedi.class).get();
+ assertEquals(1, powers.size());
+ assertEquals("jump", powers.get(0));
+ }
+
+ @Test
+ public void should_use_TypeRef_to_write_static_field() {
+ List<String> powers = newArrayList("jump");
+ StaticFieldName.beginStaticFieldAccess("commonPowers").ofType(new TypeRef<List<String>>() {}).in(Jedi.class).set(powers);
+ assertEquals(1, Jedi.commonPowers().size());
+ assertEquals("jump", Jedi.commonPowers().get(0));
+ }
+}
diff --git a/src/test/java/org/fest/reflect/field/NestedFieldTest.java b/src/test/java/org/fest/reflect/field/NestedFieldTest.java
new file mode 100644
index 0000000..b3a5a30
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/NestedFieldTest.java
@@ -0,0 +1,197 @@
+/*
+ * Created on Apr 8, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field;
+
+import static org.fest.reflect.core.Reflection.field;
+import static org.fest.util.Lists.newArrayList;
+
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.junit.rules.ExpectedException;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.reference.TypeRef;
+
+/**
+ * @author Ivan Hristov
+ *
+ */
+public class NestedFieldTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private static final class BusinessService {
+ private final NotificationService notificationService;
+
+ public BusinessService() {
+ this.notificationService = new NotificationService();
+ }
+
+ public void doLogic() {
+ notificationService.save();
+ }
+
+ public NotificationService getNotificationService() {
+ return notificationService;
+ }
+ // ...
+ }
+
+ private static final class NotificationService {
+ private final Logger logger = new Logger();
+ private final IClientStatusDao clientStatusDao;
+
+ public NotificationService() {
+ this.clientStatusDao = new ClientStatusDao();
+ }
+
+ // ...
+
+ public void save() {
+ clientStatusDao.update();
+ }
+
+ public Logger getLogger() {
+ return logger;
+ }
+ }
+
+ private static class Logger {
+ // ...
+ }
+
+ private static interface IClientStatusDao {
+ void update();
+ }
+
+ private static class ClientStatusDao implements IClientStatusDao {
+ private final Session session;
+ @SuppressWarnings("unused")
+ private final List<String> listOfNames = newArrayList("Ivan", "Joel", "Alex");
+
+ public ClientStatusDao() {
+ this.session = new SessionImpl();
+ }
+
+ public void update() {
+ session.manageSession();
+ }
+ }
+
+ private static class SessionImpl implements Session {
+ private final SessionMonitor sessionMonitor = new SessionMonitor();
+
+ public void manageSession() {
+ sessionMonitor.monitor();
+ // logic goes here
+ }
+
+ }
+
+ private static interface Session {
+ void manageSession();
+ }
+
+ private static class SessionMonitor {
+ public void monitor() {
+ // monitoring logic here
+ }
+ }
+
+ @Test
+ public void shouldSetOneLevelNestedLoggerField() {
+ // GIVEN
+ BusinessService businessService = new BusinessService();
+ Logger loggerMock = mock(Logger.class);
+
+ // WHEN
+ field("notificationService.logger").ofType(Logger.class).in(businessService).set(loggerMock);
+
+ // THEN
+ assertSame(businessService.getNotificationService().getLogger(), loggerMock);
+ }
+
+ @Test
+ public void shouldThrowExceptionBecauseOfWrongOrder() {
+
+ expectedException.expect(ReflectionError.class);
+ expectedException.expectMessage(JUnitMatchers.containsString(//
+ "Unable to find field 'clientStatusDao' in org.fest.reflect.field.NestedFieldTest$BusinessService"));
+
+ // GIVEN
+ BusinessService businessService = new BusinessService();
+ Session sessionMock = mock(Session.class);
+
+ field("clientStatusDao.notificationService.session").ofType(Session.class).in(businessService).set(sessionMock);
+
+ // WHEN
+ businessService.doLogic();
+
+ // THEN
+ verify(sessionMock, times(1)).manageSession();
+ }
+
+ @Test
+ public void shouldSetSecondLevelNestedSessionField() {
+ // GIVEN
+ BusinessService businessService = new BusinessService();
+ Session sessionMock = mock(Session.class);
+
+ field("notificationService.clientStatusDao.session").ofType(Session.class).in(businessService).set(sessionMock);
+
+ // WHEN
+ businessService.doLogic();
+
+ // THEN
+ verify(sessionMock, times(1)).manageSession();
+ }
+
+ @Test
+ public void shouldGetSecondLevelNestedListOfNamesField() {
+ // GIVEN
+ BusinessService businessService = new BusinessService();
+
+ // WHEN
+ List<String> listOfNames = field("notificationService.clientStatusDao.listOfNames").ofType(new TypeRef<List<String>>() {})
+ .in(businessService).get();
+
+ // THEN
+ Assert.assertThat(listOfNames, JUnitMatchers.hasItems("Ivan", "Joel", "Alex"));
+ }
+
+ @Test
+ public void shouldSetThirdLevelNestedSessionFactoryField() {
+ // GIVEN
+ BusinessService businessService = new BusinessService();
+ SessionMonitor sessionMonitorMock = mock(SessionMonitor.class);
+
+ field("notificationService.clientStatusDao.session.sessionMonitor").ofType(SessionMonitor.class)//
+ .in(businessService).set(sessionMonitorMock);
+
+ // WHEN
+ businessService.doLogic();
+
+ // THEN
+ verify(sessionMonitorMock, times(1)).monitor();
+ }
+}
diff --git a/src/test/java/org/fest/reflect/field/decorator/TestRuntimeExceptionShield.java b/src/test/java/org/fest/reflect/field/decorator/TestRuntimeExceptionShield.java
new file mode 100644
index 0000000..9f7dcc8
--- /dev/null
+++ b/src/test/java/org/fest/reflect/field/decorator/TestRuntimeExceptionShield.java
@@ -0,0 +1,79 @@
+/*
+ * Created on Mar 19, 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2006-2009 the original author or authors.
+ */
+package org.fest.reflect.field.decorator;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.lang.reflect.Proxy;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.junit.rules.ExpectedException;
+
+/**
+ * @author Ivan Hristov
+ *
+ */
+public class TestRuntimeExceptionShield {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ interface ITestService {
+ boolean test() throws IllegalAccessError;
+ }
+
+ @Test
+ public void shouldShieldFromRuntimeException() {
+ // GIVEN
+ ITestService testServiceMock = mock(ITestService.class);
+ when(testServiceMock.test()).thenThrow(new RuntimeException("Expected test exception"));
+
+ RuntimeExceptionShield runtimeExceptionShield = new RuntimeExceptionShield(testServiceMock, RuntimeException.class);
+
+ ITestService proxyObject = (ITestService) Proxy.newProxyInstance(testServiceMock.getClass().getClassLoader(),//
+ new Class[] { ITestService.class }, runtimeExceptionShield);
+
+ // WHEN
+ proxyObject.test();
+
+ // THEN no exception should happen
+ verify(testServiceMock, times(1)).test();
+ }
+
+ @Test
+ public void shouldNotShieldFromNonRuntimeException() {
+ // GIVEN
+ expectedException.expect(IllegalAccessError.class);
+ expectedException.expectMessage(JUnitMatchers.containsString("Expected test error"));
+
+ ITestService testServiceMock = mock(ITestService.class);
+ when(testServiceMock.test()).thenThrow(new IllegalAccessError("Expected test error"));
+
+ RuntimeExceptionShield runtimeExceptionShield = new RuntimeExceptionShield(testServiceMock, RuntimeException.class);
+
+ ITestService proxyObject = (ITestService) Proxy.newProxyInstance(testServiceMock.getClass().getClassLoader(),//
+ new Class[] { ITestService.class }, runtimeExceptionShield);
+
+ // WHEN
+ proxyObject.test();
+
+ // THEN there should be an error
+ }
+}
diff --git a/src/test/java/org/fest/reflect/innerclass/OuterClass.java b/src/test/java/org/fest/reflect/innerclass/OuterClass.java
new file mode 100644
index 0000000..9e7e75d
--- /dev/null
+++ b/src/test/java/org/fest/reflect/innerclass/OuterClass.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.innerclass;
+
+/**
+ * Understands SOMETHING DUMMY.
+ *
+ * @author Alex Ruiz
+ */
+public class OuterClass {
+
+ public static class PublicInnerClass {}
+
+ protected static class ProtectedInnerClass {}
+
+ static class PackageInnerClass {}
+
+ @SuppressWarnings("unused")
+ private static class PrivateInnerClass {
+ private final String name;
+
+ PrivateInnerClass(String name) {
+ this.name = name;
+ }
+
+ String name() {
+ return name;
+ }
+ }
+}
diff --git a/src/test/java/org/fest/reflect/innerclass/StaticInnerClass_Test.java b/src/test/java/org/fest/reflect/innerclass/StaticInnerClass_Test.java
new file mode 100644
index 0000000..98a4014
--- /dev/null
+++ b/src/test/java/org/fest/reflect/innerclass/StaticInnerClass_Test.java
@@ -0,0 +1,84 @@
+/*
+ * Created on Jan 25, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.innerclass;
+
+import static org.fest.reflect.core.Reflection.constructor;
+import static org.fest.reflect.core.Reflection.field;
+import static org.fest.reflect.core.Reflection.method;
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for inner classes.
+ *
+ * @author Alex Ruiz
+ */
+public class StaticInnerClass_Test {
+
+ @Test
+ public void should_throw_error_if_static_inner_class_name_is_null() {
+ expectNullPointerException("The name of the static inner class to access should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticInnerClassName.startStaticInnerClassAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_inner_class_name_is_empty() {
+ expectIllegalArgumentException("The name of the static inner class to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ StaticInnerClassName.startStaticInnerClassAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_declaring_class_is_null() {
+ expectNullPointerException("The declaring class should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticInnerClassName.startStaticInnerClassAccess("Hello").in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_see_static_inner_class() {
+ Class<?> innerClass = StaticInnerClassName.startStaticInnerClassAccess("PrivateInnerClass").in(OuterClass.class).get();
+ assertTrue(innerClass.getName().contains("PrivateInnerClass"));
+ // make sure we really got the inner classes by creating a new instance and accessing its fields and methods.
+ Object leia = constructor().withParameterTypes(String.class).in(innerClass).newInstance("Leia");
+ assertEquals("Leia", field("name").ofType(String.class).in(leia).get());
+ assertEquals("Leia", method("name").withReturnType(String.class).in(leia).invoke());
+ }
+
+ @Test
+ public void should_return_null_if_static_inner_class_does_not_exist() {
+ String msg = "The static inner class <SomeInnerClass> cannot be found in org.fest.reflect.innerclass.OuterClass";
+ expectReflectionError(msg).on(new CodeToTest() {
+ public void run() {
+ StaticInnerClassName.startStaticInnerClassAccess("SomeInnerClass").in(OuterClass.class).get();
+ }
+ });
+ }
+}
diff --git a/src/test/java/org/fest/reflect/method/Method_method_Test.java b/src/test/java/org/fest/reflect/method/Method_method_Test.java
new file mode 100644
index 0000000..0f8fe39
--- /dev/null
+++ b/src/test/java/org/fest/reflect/method/Method_method_Test.java
@@ -0,0 +1,208 @@
+/*
+ * Created on May 18, 2007
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2007-2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for accessing methods.
+ *
+ * @author Yvonne Wang
+ * @author Alex Ruiz
+ */
+public class Method_method_Test {
+
+ private Jedi jedi;
+
+ @Before
+ public void setUp() {
+ jedi = new Jedi("Luke");
+ }
+
+ @Test
+ public void should_throw_error_if_method_name_is_null() {
+ expectNullPointerException("The name of the method to access should not be null").on(new CodeToTest() {
+ public void run() {
+ MethodName.startMethodAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_method_name_is_empty() {
+ expectIllegalArgumentException("The name of the method to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ MethodName.startMethodAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_method_return_type_is_null() {
+ String msg = "The return type of the method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ MethodName.startMethodAccess("setName").withReturnType((Class<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_method_return_TypeRef_is_null() {
+ String msg = "The return type reference of the method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ MethodName.startMethodAccess("setName").withReturnType((TypeRef<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_method_parameter_array_is_null() {
+ String msg = "The array of parameter types for the method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ Class<?>[] parameterTypes = null;
+ MethodName.startMethodAccess("setName").withParameterTypes(parameterTypes);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_method_target_is_null() {
+ expectNullPointerException("Target should not be null").on(new CodeToTest() {
+ public void run() {
+ MethodName.startMethodAccess("setName").in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_call_method_with_args_and_no_return_value() {
+ MethodName.startMethodAccess("setName").withParameterTypes(String.class).in(jedi).invoke("Leia");
+ assertEquals("Leia", jedi.getName());
+ }
+
+ @Test
+ public void should_call_method_with_no_args_and_return_value() {
+ String personName = MethodName.startMethodAccess("getName").withReturnType(String.class).in(jedi).invoke();
+ assertEquals("Luke", personName);
+ }
+
+ @Test
+ public void should_call_method_with_args_and_return_value() {
+ jedi.addPower("healing");
+ String power = MethodName.startMethodAccess("powerAt").withReturnType(String.class).withParameterTypes(int.class).in(jedi)
+ .invoke(0);
+ assertEquals("healing", power);
+ }
+
+ @Test
+ public void should_call_method_with_no_args_and_return_TypeRef() {
+ jedi.addPower("jump");
+ List<String> powers = MethodName.startMethodAccess("powers").withReturnType(new TypeRef<List<String>>() {}).in(jedi).invoke();
+ assertEquals(1, powers.size());
+ assertEquals("jump", powers.get(0));
+ }
+
+ @Test
+ public void should_call_method_with_args_and_return_TypeRef() {
+ jedi.addPower("healing");
+ jedi.addPower("jump");
+ String method = "powersThatStartWith";
+ List<String> powers = MethodName.startMethodAccess(method).withReturnType(new TypeRef<List<String>>() {})
+ .withParameterTypes(String.class).in(jedi).invoke("ju");
+ assertEquals(1, powers.size());
+ assertEquals("jump", powers.get(0));
+ }
+
+ @Test
+ public void should_call_method_with_no_args_and_no_return_value() {
+ assertFalse(jedi.isMaster());
+ MethodName.startMethodAccess("makeMaster").in(jedi).invoke();
+ assertTrue(jedi.isMaster());
+ }
+
+ @Test
+ public void should_return_real_method() {
+ java.lang.reflect.Method method = MethodName.startMethodAccess("setName").withParameterTypes(String.class).in(jedi).info();
+ assertNotNull(method);
+ assertEquals("setName", method.getName());
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ assertEquals(1, parameterTypes.length);
+ assertEquals(String.class, parameterTypes[0]);
+ }
+
+ @Test
+ public void should_throw_error_if_method_name_is_invalid() {
+ String message = "Unable to find method 'getAge' in org.fest.reflect.Jedi with parameter type(s) []";
+ expectReflectionError(message).on(new CodeToTest() {
+ public void run() {
+ String invalidName = "getAge";
+ MethodName.startMethodAccess(invalidName).withReturnType(Integer.class).in(jedi);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_args_for_method_are_invalid() {
+ expectIllegalArgumentException("argument type mismatch").on(new CodeToTest() {
+ public void run() {
+ int invalidArg = 8;
+ MethodName.startMethodAccess("setName").withParameterTypes(String.class).in(jedi).invoke(invalidArg);
+ }
+ });
+ }
+
+ @Test
+ public void should_rethrow_RuntimeException_thrown_by_method() {
+ try {
+ MethodName.startMethodAccess("throwRuntimeException").in(jedi).invoke();
+ fail("Expecting an IllegalStateException");
+ } catch (IllegalStateException e) {
+ assertEquals("Somehow I got in an illegal state", e.getMessage());
+ }
+ }
+
+ @Test
+ public void should_wrap_with_a_ReflectionError_the_checked_Exception_thrown_by_method() {
+ try {
+ MethodName.startMethodAccess("throwCheckedException").in(jedi).invoke();
+ fail("Expecting an ReflectionError");
+ } catch (ReflectionError e) {
+ Throwable cause = e.getCause();
+ assertTrue(cause instanceof Exception);
+ assertEquals("I don't know what's wrong", cause.getMessage());
+ }
+ }
+}
diff --git a/src/test/java/org/fest/reflect/method/Method_staticMethod_Test.java b/src/test/java/org/fest/reflect/method/Method_staticMethod_Test.java
new file mode 100644
index 0000000..4840cff
--- /dev/null
+++ b/src/test/java/org/fest/reflect/method/Method_staticMethod_Test.java
@@ -0,0 +1,174 @@
+/*
+ * Created on Nov 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.method;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+import static org.fest.reflect.util.ExpectedFailures.expectReflectionError;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.reference.TypeRef;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for the fluent interface for accessing static methods.
+ *
+ * @author Yvonne Wang
+ * @author Alex Ruiz
+ */
+public class Method_staticMethod_Test {
+
+ @Before
+ public void setUp() {
+ Jedi.clearCommonPowers();
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_name_is_null() {
+ expectNullPointerException("The name of the static method to access should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticMethodName.startStaticMethodAccess(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_name_is_empty() {
+ expectIllegalArgumentException("The name of the static method to access should not be empty").on(new CodeToTest() {
+ public void run() {
+ StaticMethodName.startStaticMethodAccess("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_return_type_is_null() {
+ String msg = "The return type of the static method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ StaticMethodName.startStaticMethodAccess("commonPowerCount").withReturnType((Class<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_return_TypeRef_is_null() {
+ String msg = "The return type reference of the static method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ StaticMethodName.startStaticMethodAccess("commonPowerCount").withReturnType((TypeRef<?>) null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_parameter_array_is_null() {
+ String msg = "The array of parameter types for the static method to access should not be null";
+ expectNullPointerException(msg).on(new CodeToTest() {
+ public void run() {
+ Class<?>[] parameterTypes = null;
+ StaticMethodName.startStaticMethodAccess("commonPowerCount").withParameterTypes(parameterTypes);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_target_is_null() {
+ expectNullPointerException("Target should not be null").on(new CodeToTest() {
+ public void run() {
+ StaticMethodName.startStaticMethodAccess("commonPowerCount").in(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_call_static_method_with_no_args_and_return_value() {
+ Jedi.addCommonPower("Jump");
+ int count = StaticMethodName.startStaticMethodAccess("commonPowerCount").withReturnType(int.class).in(Jedi.class).invoke();
+ assertEquals(Jedi.commonPowerCount(), count);
+ }
+
+ @Test
+ public void should_call_static_method_with_args_and_return_value() {
+ Jedi.addCommonPower("Jump");
+ String power = StaticMethodName.startStaticMethodAccess("commonPowerAt").withReturnType(String.class)
+ .withParameterTypes(int.class).in(Jedi.class).invoke(0);
+ assertEquals("Jump", power);
+ }
+
+ @Test
+ public void should_call_static_method_with_no_args_and_return_TypeRef() {
+ Jedi.addCommonPower("jump");
+ String method = "commonPowers";
+ List<String> powers = StaticMethodName.startStaticMethodAccess(method).withReturnType(new TypeRef<List<String>>() {})
+ .in(Jedi.class).invoke();
+ assertEquals(1, powers.size());
+ assertEquals("jump", powers.get(0));
+ }
+
+ @Test
+ public void should_call_static_method_with_args_and_return_TypeRef() {
+ Jedi.addCommonPower("jump");
+ String method = "commonPowersThatStartWith";
+ List<String> powers = StaticMethodName.startStaticMethodAccess(method).withReturnType(new TypeRef<List<String>>() {})
+ .withParameterTypes(String.class).in(Jedi.class).invoke("ju");
+ assertEquals(1, powers.size());
+ assertEquals("jump", powers.get(0));
+ }
+
+ @Test
+ public void should_call_static_method_with_args_and_no_return_value() {
+ StaticMethodName.startStaticMethodAccess("addCommonPower").withParameterTypes(String.class).in(Jedi.class).invoke("Jump");
+ assertEquals("Jump", Jedi.commonPowerAt(0));
+ }
+
+ @Test
+ public void should_call_static_method_with_no_args_and_no_return_value() {
+ Jedi.addCommonPower("Jump");
+ assertEquals(1, Jedi.commonPowerCount());
+ assertEquals("Jump", Jedi.commonPowerAt(0));
+ StaticMethodName.startStaticMethodAccess("clearCommonPowers").in(Jedi.class).invoke();
+ assertEquals(0, Jedi.commonPowerCount());
+ }
+
+ @Test
+ public void should_throw_error_if_static_method_name_is_invalid() {
+ String message = "Unable to find method 'powerSize' in org.fest.reflect.Jedi with parameter type(s) []";
+ expectReflectionError(message).on(new CodeToTest() {
+ public void run() {
+ String invalidName = "powerSize";
+ StaticMethodName.startStaticMethodAccess(invalidName).in(Jedi.class);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_args_for_static_method_are_invalid() {
+ expectIllegalArgumentException("argument type mismatch").on(new CodeToTest() {
+ public void run() {
+ int invalidArg = 8;
+ StaticMethodName.startStaticMethodAccess("addCommonPower").withParameterTypes(String.class).in(Jedi.class)
+ .invoke(invalidArg);
+ }
+ });
+ }
+}
diff --git a/src/test/java/org/fest/reflect/type/Type_Test.java b/src/test/java/org/fest/reflect/type/Type_Test.java
new file mode 100644
index 0000000..05a20e2
--- /dev/null
+++ b/src/test/java/org/fest/reflect/type/Type_Test.java
@@ -0,0 +1,120 @@
+/*
+ * Created on Jan 23, 2009
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2009 the original author or authors.
+ */
+package org.fest.reflect.type;
+
+import static org.fest.reflect.util.ExpectedFailures.expectIllegalArgumentException;
+import static org.fest.reflect.util.ExpectedFailures.expectNullPointerException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import org.fest.reflect.Jedi;
+import org.fest.reflect.Person;
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.test.CodeToTest;
+
+/**
+ * Tests for <code>{@link Type}</code>.
+ *
+ * @author Alex Ruiz
+ */
+public class Type_Test {
+
+ @Test
+ public void should_throw_error_if__type_name_is_null() {
+ expectNullPointerException("The name of the class to load should not be null").on(new CodeToTest() {
+ public void run() {
+ Type.newType(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if__type_name_is_empty() {
+ expectIllegalArgumentException("The name of the class to load should not be empty").on(new CodeToTest() {
+ public void run() {
+ Type.newType("");
+ }
+ });
+ }
+
+ @Test
+ public void should_throw_error_if_subtype_is_mull() {
+ expectNullPointerException("The given type should not be null").on(new CodeToTest() {
+ public void run() {
+ Type.newType("hello").loadAs(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_load_class() {
+ Class<Jedi> expected = Jedi.class;
+ Class<?> type = Type.newType(expected.getName()).load();
+ assertEquals(expected, type);
+ }
+
+ @Test
+ public void should_load_class_with_given_ClassLoader() {
+ Class<Jedi> expected = Jedi.class;
+ Class<?> type = Type.newType(expected.getName()).withClassLoader(getClass().getClassLoader()).load();
+ assertEquals(expected, type);
+ }
+
+ @Test
+ public void should_throw_error_if_Classloader_is_null() {
+ expectNullPointerException("The given class loader should not be null").on(new CodeToTest() {
+ public void run() {
+ Type.newType("hello").withClassLoader(null);
+ }
+ });
+ }
+
+ @Test
+ public void should_wrap_any_Exception_thrown_when_loading_class() {
+ try {
+ Type.newType("org.fest.reflect.NonExistingType").load();
+ } catch (ReflectionError expected) {
+ assertTrue(expected.getMessage().contains("Unable to load class 'org.fest.reflect.NonExistingType' using class loader "));
+ assertTrue(expected.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ @Test
+ public void should_load_class_as_given_type() {
+ Class<? extends Person> type = Type.newType(Jedi.class.getName()).loadAs(Person.class);
+ assertEquals(Jedi.class, type);
+ }
+
+ @Test
+ public void should_load_class_as_given_type_with_given_ClassLoader() {
+ Class<? extends Person> type = Type.newType(Jedi.class.getName()).withClassLoader(getClass().getClassLoader())
+ .loadAs(Person.class);
+ assertEquals(Jedi.class, type);
+ }
+
+ @Test
+ public void should_wrap_any_Exception_thrown_when_loading_class_as_given_type() {
+ try {
+ Type.newType("org.fest.reflect.NonExistingType").loadAs(Jedi.class);
+ } catch (ReflectionError expected) {
+ assertTrue(expected.getMessage().contains(
+ "Unable to load class 'org.fest.reflect.NonExistingType' as org.fest.reflect.Jedi using class loader "));
+ assertTrue(expected.getCause() instanceof ClassNotFoundException);
+ }
+ }
+}
diff --git a/src/test/java/org/fest/reflect/util/ExpectedFailures.java b/src/test/java/org/fest/reflect/util/ExpectedFailures.java
new file mode 100644
index 0000000..2f34eeb
--- /dev/null
+++ b/src/test/java/org/fest/reflect/util/ExpectedFailures.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Feb 18, 2008
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * Copyright @2008-2009 the original author or authors.
+ */
+package org.fest.reflect.util;
+
+import org.fest.reflect.exception.ReflectionError;
+import org.fest.test.ExpectedFailure.Message;
+
+import static org.fest.test.ExpectedFailure.expect;
+
+/**
+ * Understands expected failures.
+ *
+ * @author Alex Ruiz
+ */
+public final class ExpectedFailures {
+
+ public static Message expectReflectionError(String message) {
+ return expect(ReflectionError.class).withMessage(message);
+ }
+
+ public static Message expectIllegalArgumentException(String message) {
+ return expect(IllegalArgumentException.class).withMessage(message);
+ }
+
+ public static Message expectNullPointerException(String message) {
+ return expect(NullPointerException.class).withMessage(message);
+ }
+
+ private ExpectedFailures() {}
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/fest-reflect.git
More information about the pkg-java-commits
mailing list