| /* |
| * Copyright (C) 2012 The Guava Authors |
| * |
| * 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. |
| */ |
| |
| package com.google.common.reflect; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.Iterables; |
| import com.google.common.testing.EqualsTester; |
| import com.google.common.testing.NullPointerTester; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.TypeVariable; |
| import java.util.Collections; |
| import junit.framework.TestCase; |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| |
| /** |
| * Unit tests for {@link Invokable}. |
| * |
| * @author Ben Yu |
| */ |
| @AndroidIncompatible // lots of failures, possibly some related to bad equals() implementations? |
| public class InvokableTest extends TestCase { |
| |
| public void testConstructor_returnType() throws Exception { |
| assertEquals(Prepender.class, Prepender.constructor().getReturnType().getType()); |
| } |
| |
| private static class WithConstructorAndTypeParameter<T> { |
| @SuppressWarnings("unused") // by reflection |
| <X> WithConstructorAndTypeParameter() {} |
| } |
| |
| public void testConstructor_returnType_hasTypeParameter() throws Exception { |
| @SuppressWarnings("rawtypes") // Foo.class for Foo<T> is always raw type |
| Class<WithConstructorAndTypeParameter> type = WithConstructorAndTypeParameter.class; |
| @SuppressWarnings("rawtypes") // Foo.class |
| Constructor<WithConstructorAndTypeParameter> constructor = type.getDeclaredConstructor(); |
| Invokable<?, ?> factory = Invokable.from(constructor); |
| assertThat(factory.getTypeParameters()).hasLength(2); |
| assertEquals(type.getTypeParameters()[0], factory.getTypeParameters()[0]); |
| assertEquals(constructor.getTypeParameters()[0], factory.getTypeParameters()[1]); |
| ParameterizedType returnType = (ParameterizedType) factory.getReturnType().getType(); |
| assertEquals(type, returnType.getRawType()); |
| assertEquals( |
| ImmutableList.copyOf(type.getTypeParameters()), |
| ImmutableList.copyOf(returnType.getActualTypeArguments())); |
| } |
| |
| public void testConstructor_exceptionTypes() throws Exception { |
| assertEquals( |
| ImmutableList.of(TypeToken.of(NullPointerException.class)), |
| Prepender.constructor(String.class, int.class).getExceptionTypes()); |
| } |
| |
| public void testConstructor_typeParameters() throws Exception { |
| TypeVariable<?>[] variables = Prepender.constructor().getTypeParameters(); |
| assertThat(variables).hasLength(1); |
| assertEquals("A", variables[0].getName()); |
| } |
| |
| public void testConstructor_parameters() throws Exception { |
| Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); |
| ImmutableList<Parameter> parameters = delegate.getParameters(); |
| assertEquals(2, parameters.size()); |
| assertEquals(String.class, parameters.get(0).getType().getType()); |
| assertTrue(parameters.get(0).isAnnotationPresent(NotBlank.class)); |
| assertEquals(int.class, parameters.get(1).getType().getType()); |
| assertFalse(parameters.get(1).isAnnotationPresent(NotBlank.class)); |
| new EqualsTester() |
| .addEqualityGroup(parameters.get(0)) |
| .addEqualityGroup(parameters.get(1)) |
| .testEquals(); |
| } |
| |
| public void testConstructor_call() throws Exception { |
| Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); |
| Prepender prepender = delegate.invoke(null, "a", 1); |
| assertEquals("a", prepender.prefix); |
| assertEquals(1, prepender.times); |
| } |
| |
| public void testConstructor_returning() throws Exception { |
| Invokable<?, Prepender> delegate = |
| Prepender.constructor(String.class, int.class).returning(Prepender.class); |
| Prepender prepender = delegate.invoke(null, "a", 1); |
| assertEquals("a", prepender.prefix); |
| assertEquals(1, prepender.times); |
| } |
| |
| public void testConstructor_invalidReturning() throws Exception { |
| Invokable<?, Prepender> delegate = Prepender.constructor(String.class, int.class); |
| try { |
| delegate.returning(SubPrepender.class); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| public void testStaticMethod_returnType() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| } |
| |
| public void testStaticMethod_exceptionTypes() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| assertEquals(ImmutableList.of(), delegate.getExceptionTypes()); |
| } |
| |
| public void testStaticMethod_typeParameters() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| TypeVariable<?>[] variables = delegate.getTypeParameters(); |
| assertThat(variables).hasLength(1); |
| assertEquals("T", variables[0].getName()); |
| } |
| |
| public void testStaticMethod_parameters() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| ImmutableList<Parameter> parameters = delegate.getParameters(); |
| assertEquals(2, parameters.size()); |
| assertEquals(String.class, parameters.get(0).getType().getType()); |
| assertTrue(parameters.get(0).isAnnotationPresent(NotBlank.class)); |
| assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(1).getType()); |
| assertFalse(parameters.get(1).isAnnotationPresent(NotBlank.class)); |
| new EqualsTester() |
| .addEqualityGroup(parameters.get(0)) |
| .addEqualityGroup(parameters.get(1)) |
| .testEquals(); |
| } |
| |
| public void testStaticMethod_call() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| @SuppressWarnings("unchecked") // prepend() returns Iterable<String> |
| Iterable<String> result = |
| (Iterable<String>) delegate.invoke(null, "a", ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testStaticMethod_returning() throws Exception { |
| Invokable<?, Iterable<String>> delegate = |
| Prepender.method("prepend", String.class, Iterable.class) |
| .returning(new TypeToken<Iterable<String>>() {}); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| Iterable<String> result = delegate.invoke(null, "a", ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testStaticMethod_returningRawType() throws Exception { |
| @SuppressWarnings("rawtypes") // the purpose is to test raw type |
| Invokable<?, Iterable> delegate = |
| Prepender.method("prepend", String.class, Iterable.class).returning(Iterable.class); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| @SuppressWarnings("unchecked") // prepend() returns Iterable<String> |
| Iterable<String> result = delegate.invoke(null, "a", ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testStaticMethod_invalidReturning() throws Exception { |
| Invokable<?, Object> delegate = Prepender.method("prepend", String.class, Iterable.class); |
| try { |
| delegate.returning(new TypeToken<Iterable<Integer>>() {}); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| public void testInstanceMethod_returnType() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| } |
| |
| public void testInstanceMethod_exceptionTypes() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); |
| assertEquals( |
| ImmutableList.of( |
| TypeToken.of(IllegalArgumentException.class), TypeToken.of(NullPointerException.class)), |
| delegate.getExceptionTypes()); |
| } |
| |
| public void testInstanceMethod_typeParameters() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); |
| assertThat(delegate.getTypeParameters()).isEmpty(); |
| } |
| |
| public void testInstanceMethod_parameters() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("prepend", Iterable.class); |
| ImmutableList<Parameter> parameters = delegate.getParameters(); |
| assertEquals(1, parameters.size()); |
| assertEquals(new TypeToken<Iterable<String>>() {}, parameters.get(0).getType()); |
| assertThat(parameters.get(0).getAnnotations()).isEmpty(); |
| new EqualsTester().addEqualityGroup(parameters.get(0)).testEquals(); |
| } |
| |
| public void testInstanceMethod_call() throws Exception { |
| Invokable<Prepender, ?> delegate = Prepender.method("prepend", Iterable.class); |
| @SuppressWarnings("unchecked") // prepend() returns Iterable<String> |
| Iterable<String> result = |
| (Iterable<String>) delegate.invoke(new Prepender("a", 2), ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testInstanceMethod_returning() throws Exception { |
| Invokable<Prepender, Iterable<String>> delegate = |
| Prepender.method("prepend", Iterable.class).returning(new TypeToken<Iterable<String>>() {}); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| Iterable<String> result = delegate.invoke(new Prepender("a", 2), ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testInstanceMethod_returningRawType() throws Exception { |
| @SuppressWarnings("rawtypes") // the purpose is to test raw type |
| Invokable<Prepender, Iterable> delegate = |
| Prepender.method("prepend", Iterable.class).returning(Iterable.class); |
| assertEquals(new TypeToken<Iterable<String>>() {}, delegate.getReturnType()); |
| @SuppressWarnings("unchecked") // prepend() returns Iterable<String> |
| Iterable<String> result = delegate.invoke(new Prepender("a", 2), ImmutableList.of("b", "c")); |
| assertEquals(ImmutableList.of("a", "a", "b", "c"), ImmutableList.copyOf(result)); |
| } |
| |
| public void testInstanceMethod_invalidReturning() throws Exception { |
| Invokable<?, Object> delegate = Prepender.method("prepend", Iterable.class); |
| try { |
| delegate.returning(new TypeToken<Iterable<Integer>>() {}); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| public void testPrivateInstanceMethod_isOverridable() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("privateMethod"); |
| assertTrue(delegate.isPrivate()); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| public void testPrivateFinalInstanceMethod_isOverridable() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("privateFinalMethod"); |
| assertTrue(delegate.isPrivate()); |
| assertTrue(delegate.isFinal()); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| public void testStaticMethod_isOverridable() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("staticMethod"); |
| assertTrue(delegate.isStatic()); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| public void testStaticFinalMethod_isFinal() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("staticFinalMethod"); |
| assertTrue(delegate.isStatic()); |
| assertTrue(delegate.isFinal()); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| static class Foo {} |
| |
| public void testConstructor_isOverridablel() throws Exception { |
| Invokable<?, ?> delegate = Invokable.from(Foo.class.getDeclaredConstructor()); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| public void testMethod_isVarArgs() throws Exception { |
| Invokable<?, ?> delegate = Prepender.method("privateVarArgsMethod", String[].class); |
| assertTrue(delegate.isVarArgs()); |
| } |
| |
| public void testConstructor_isVarArgs() throws Exception { |
| Invokable<?, ?> delegate = Prepender.constructor(String[].class); |
| assertTrue(delegate.isVarArgs()); |
| } |
| |
| public void testGetOwnerType_constructor() throws Exception { |
| Invokable<String, String> invokable = Invokable.from(String.class.getConstructor()); |
| assertEquals(TypeToken.of(String.class), invokable.getOwnerType()); |
| } |
| |
| public void testGetOwnerType_method() throws Exception { |
| Invokable<?, ?> invokable = Invokable.from(String.class.getMethod("length")); |
| assertEquals(TypeToken.of(String.class), invokable.getOwnerType()); |
| } |
| |
| private static final class FinalClass { |
| @SuppressWarnings("unused") // used by reflection |
| void notFinalMethod() {} |
| } |
| |
| public void testNonFinalMethodInFinalClass_isOverridable() throws Exception { |
| Invokable<?, ?> delegate = Invokable.from(FinalClass.class.getDeclaredMethod("notFinalMethod")); |
| assertFalse(delegate.isOverridable()); |
| assertFalse(delegate.isVarArgs()); |
| } |
| |
| private class InnerWithDefaultConstructor { |
| class NestedInner {} |
| } |
| |
| public void testInnerClassDefaultConstructor() { |
| Constructor<?> constructor = InnerWithDefaultConstructor.class.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| public void testNestedInnerClassDefaultConstructor() { |
| Constructor<?> constructor = |
| InnerWithDefaultConstructor.NestedInner.class.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| private class InnerWithOneParameterConstructor { |
| @SuppressWarnings("unused") // called by reflection |
| public InnerWithOneParameterConstructor(String s) {} |
| } |
| |
| public void testInnerClassWithOneParameterConstructor() { |
| Constructor<?> constructor = |
| InnerWithOneParameterConstructor.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(1, invokable.getParameters().size()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); |
| } |
| |
| private class InnerWithAnnotatedConstructorParameter { |
| @SuppressWarnings("unused") // called by reflection |
| InnerWithAnnotatedConstructorParameter(@Nullable String s) {} |
| } |
| |
| public void testInnerClassWithAnnotatedConstructorParameter() { |
| Constructor<?> constructor = |
| InnerWithAnnotatedConstructorParameter.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(1, invokable.getParameters().size()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); |
| } |
| |
| private class InnerWithGenericConstructorParameter { |
| @SuppressWarnings("unused") // called by reflection |
| InnerWithGenericConstructorParameter(Iterable<String> it, String s) {} |
| } |
| |
| public void testInnerClassWithGenericConstructorParameter() { |
| Constructor<?> constructor = |
| InnerWithGenericConstructorParameter.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(2, invokable.getParameters().size()); |
| assertEquals(new TypeToken<Iterable<String>>() {}, invokable.getParameters().get(0).getType()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(1).getType()); |
| } |
| |
| public void testAnonymousClassDefaultConstructor() { |
| final int i = 1; |
| final String s = "hello world"; |
| Class<?> anonymous = |
| new Runnable() { |
| @Override |
| public void run() { |
| System.out.println(s + i); |
| } |
| }.getClass(); |
| Constructor<?> constructor = anonymous.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| public void testAnonymousClassWithTwoParametersConstructor() { |
| abstract class Base { |
| @SuppressWarnings("unused") // called by reflection |
| Base(String s, int i) {} |
| } |
| Class<?> anonymous = new Base("test", 0) {}.getClass(); |
| Constructor<?> constructor = anonymous.getDeclaredConstructors()[0]; |
| assertEquals(2, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| public void testLocalClassDefaultConstructor() { |
| final int i = 1; |
| final String s = "hello world"; |
| class LocalWithDefaultConstructor implements Runnable { |
| @Override |
| public void run() { |
| System.out.println(s + i); |
| } |
| } |
| Constructor<?> constructor = LocalWithDefaultConstructor.class.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| public void testStaticAnonymousClassDefaultConstructor() throws Exception { |
| doTestStaticAnonymousClassDefaultConstructor(); |
| } |
| |
| private static void doTestStaticAnonymousClassDefaultConstructor() { |
| final int i = 1; |
| final String s = "hello world"; |
| Class<?> anonymous = |
| new Runnable() { |
| @Override |
| public void run() { |
| System.out.println(s + i); |
| } |
| }.getClass(); |
| Constructor<?> constructor = anonymous.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| |
| public void testAnonymousClassInConstructor() { |
| new AnonymousClassInConstructor(); |
| } |
| |
| private static class AnonymousClassInConstructor { |
| AnonymousClassInConstructor() { |
| final int i = 1; |
| final String s = "hello world"; |
| Class<?> anonymous = |
| new Runnable() { |
| @Override |
| public void run() { |
| System.out.println(s + i); |
| } |
| }.getClass(); |
| Constructor<?> constructor = anonymous.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| } |
| |
| public void testLocalClassInInstanceInitializer() { |
| new LocalClassInInstanceInitializer(); |
| } |
| |
| private static class LocalClassInInstanceInitializer { |
| { |
| class Local {} |
| Constructor<?> constructor = Local.class.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| } |
| |
| public void testLocalClassInStaticInitializer() { |
| new LocalClassInStaticInitializer(); |
| } |
| |
| private static class LocalClassInStaticInitializer { |
| static { |
| class Local {} |
| Constructor<?> constructor = Local.class.getDeclaredConstructors()[0]; |
| assertEquals(0, Invokable.from(constructor).getParameters().size()); |
| } |
| } |
| |
| public void testLocalClassWithSeeminglyHiddenThisInStaticInitializer_BUG() { |
| new LocalClassWithSeeminglyHiddenThisInStaticInitializer(); |
| } |
| |
| /** |
| * This class demonstrates a bug in getParameters() when the local class is inside static |
| * initializer. |
| */ |
| private static class LocalClassWithSeeminglyHiddenThisInStaticInitializer { |
| static { |
| class Local { |
| @SuppressWarnings("unused") // through reflection |
| Local(LocalClassWithSeeminglyHiddenThisInStaticInitializer outer) {} |
| } |
| Constructor<?> constructor = Local.class.getDeclaredConstructors()[0]; |
| int miscalculated = 0; |
| assertEquals(miscalculated, Invokable.from(constructor).getParameters().size()); |
| } |
| } |
| |
| public void testLocalClassWithOneParameterConstructor() throws Exception { |
| final int i = 1; |
| final String s = "hello world"; |
| class LocalWithOneParameterConstructor { |
| @SuppressWarnings("unused") // called by reflection |
| public LocalWithOneParameterConstructor(String x) { |
| System.out.println(s + i); |
| } |
| } |
| Constructor<?> constructor = |
| LocalWithOneParameterConstructor.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(1, invokable.getParameters().size()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); |
| } |
| |
| public void testLocalClassWithAnnotatedConstructorParameter() throws Exception { |
| class LocalWithAnnotatedConstructorParameter { |
| @SuppressWarnings("unused") // called by reflection |
| LocalWithAnnotatedConstructorParameter(@Nullable String s) {} |
| } |
| Constructor<?> constructor = |
| LocalWithAnnotatedConstructorParameter.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(1, invokable.getParameters().size()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(0).getType()); |
| } |
| |
| public void testLocalClassWithGenericConstructorParameter() throws Exception { |
| class LocalWithGenericConstructorParameter { |
| @SuppressWarnings("unused") // called by reflection |
| LocalWithGenericConstructorParameter(Iterable<String> it, String s) {} |
| } |
| Constructor<?> constructor = |
| LocalWithGenericConstructorParameter.class.getDeclaredConstructors()[0]; |
| Invokable<?, ?> invokable = Invokable.from(constructor); |
| assertEquals(2, invokable.getParameters().size()); |
| assertEquals(new TypeToken<Iterable<String>>() {}, invokable.getParameters().get(0).getType()); |
| assertEquals(TypeToken.of(String.class), invokable.getParameters().get(1).getType()); |
| } |
| |
| public void testEquals() throws Exception { |
| new EqualsTester() |
| .addEqualityGroup(Prepender.constructor(), Prepender.constructor()) |
| .addEqualityGroup(Prepender.constructor(String.class, int.class)) |
| .addEqualityGroup(Prepender.method("privateMethod"), Prepender.method("privateMethod")) |
| .addEqualityGroup(Prepender.method("privateFinalMethod")) |
| .testEquals(); |
| } |
| |
| public void testNulls() { |
| new NullPointerTester().testAllPublicStaticMethods(Invokable.class); |
| new NullPointerTester().testAllPublicInstanceMethods(Prepender.method("staticMethod")); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| private @interface NotBlank {} |
| |
| /** Class for testing constructor, static method and instance method. */ |
| @SuppressWarnings("unused") // most are called by reflection |
| private static class Prepender { |
| |
| private final String prefix; |
| private final int times; |
| |
| Prepender(@NotBlank String prefix, int times) throws NullPointerException { |
| this.prefix = prefix; |
| this.times = times; |
| } |
| |
| Prepender(String... varargs) { |
| this(null, 0); |
| } |
| |
| // just for testing |
| private <A> Prepender() { |
| this(null, 0); |
| } |
| |
| static <T> Iterable<String> prepend(@NotBlank String first, Iterable<String> tail) { |
| return Iterables.concat(ImmutableList.of(first), tail); |
| } |
| |
| Iterable<String> prepend(Iterable<String> tail) |
| throws IllegalArgumentException, NullPointerException { |
| return Iterables.concat(Collections.nCopies(times, prefix), tail); |
| } |
| |
| static Invokable<?, Prepender> constructor(Class<?>... parameterTypes) throws Exception { |
| Constructor<Prepender> constructor = Prepender.class.getDeclaredConstructor(parameterTypes); |
| return Invokable.from(constructor); |
| } |
| |
| static Invokable<Prepender, Object> method(String name, Class<?>... parameterTypes) { |
| try { |
| Method method = Prepender.class.getDeclaredMethod(name, parameterTypes); |
| @SuppressWarnings("unchecked") // The method is from Prepender. |
| Invokable<Prepender, Object> invokable = |
| (Invokable<Prepender, Object>) Invokable.from(method); |
| return invokable; |
| } catch (NoSuchMethodException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| |
| private void privateMethod() {} |
| |
| private final void privateFinalMethod() {} |
| |
| static void staticMethod() {} |
| |
| static final void staticFinalMethod() {} |
| |
| private void privateVarArgsMethod(String... varargs) {} |
| } |
| |
| private static class SubPrepender extends Prepender { |
| @SuppressWarnings("unused") // needed to satisfy compiler, never called |
| public SubPrepender() throws NullPointerException { |
| throw new AssertionError(); |
| } |
| } |
| } |