
com.google.gwt.inject.rebind.reflect.MethodLiteral Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gin Show documentation
Show all versions of gin Show documentation
GIN (GWT INjection) brings automatic dependency injection to Google Web Toolkit client-side code. GIN is built on top of Guice and uses (a subset of) Guice's binding language.
/*
* Copyright 2010 Google Inc.
*
* 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.gwt.inject.rebind.reflect;
import com.google.gwt.dev.util.Preconditions;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.user.client.rpc.core.java.util.Collections;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.MoreTypes;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.google.gwt.inject.rebind.util.SourceWriteUtil.join;
/**
* Generic method and constructor representation that preserves the member's
* parametrization and allows common operations on methods and constructors
* where appropriate.
*
* @see TypeLiteral
*/
public abstract class MethodLiteral
extends MemberLiteral {
/**
* Creates a new {@code MethodLiteral} based on the passed method and its
* declaring type.
*
* @param method method for which the literal is constructed
* @param declaringType type declaring the passed method
* @return new method literal
*/
public static MethodLiteral get(Method method, TypeLiteral declaringType) {
Preconditions.checkArgument(method.getDeclaringClass().equals(declaringType.getRawType()),
"declaringType (%s) must be the type literal where method was declared (%s)!",
declaringType, method.getDeclaringClass());
return new ConcreteMethodLiteral(method, declaringType);
}
/**
* Creates a new {@code MethodLiteral} based on the passed constructor and
* its declaring type.
*
* @param constructor constructor for which the literal is constructed
* @param declaringType type declaring the constructor
* @return new method literal
*/
public static MethodLiteral> get(Constructor> constructor,
TypeLiteral declaringType) {
Preconditions.checkArgument(
constructor.getDeclaringClass().equals(declaringType.getRawType()),
"declaringType (%s) must be the type literal where constructor was declared (%s)!",
declaringType, constructor.getDeclaringClass());
return new ConstructorLiteral(constructor, declaringType);
}
/**
* Cache of parameter keys.
*/
private List> parameterKeys;
/**
* Cache of parameter types.
*/
private List> parameterTypes;
protected MethodLiteral(M member, TypeLiteral declaringType) {
super(member, declaringType);
}
/**
* Returns this method's parameter keys, if appropriate parametrized with the
* declaring class's type parameters.
*
* @return parameter keys
*/
public List> getParameterKeys() {
if (parameterKeys == null) {
compileParameterKeys();
}
return parameterKeys;
}
/**
* Returns this method's parameter types, if appropriate parametrized with
* the declaring class's type parameters.
*
* @return parameter types
*/
public List> getParameterTypes() {
if (parameterTypes == null) {
parameterTypes = getDeclaringType().getParameterTypes(getMember());
}
return parameterTypes;
}
/**
* Returns this method's parameter types without any type parametrization
* applied.
*
* For example, {@code <T> void foo(T t)} will return a list with a single
* entry, a {@link TypeVariable} with name {@code T} and bounded by
* {@code java.lang.Object}.
*
* @return raw parameter types
*/
public abstract List getRawParameterTypes();
/**
* Returns this method's exception types, if appropriate parametrized with
* the declaring class's type parameters.
*
* @return exception types
*/
public List> getExceptionTypes() {
return getDeclaringType().getExceptionTypes(getMember());
}
/**
* Returns this method's type parameters.
*
* @return type parameters
*/
public TypeVariable>[] getTypeParameters() {
return getMember().getTypeParameters();
}
/**
* Returns this method's return type, if appropriate parametrized with the
* declaring class's type parameters.
*
* @return return type
*/
public abstract TypeLiteral> getReturnType();
/**
* Returns {@code true} if this method literal is based on a constructor.
*/
public abstract boolean isConstructor();
protected abstract Annotation[][] getParameterAnnotations();
private void compileParameterKeys() {
parameterKeys = new ArrayList>(getParameterTypes().size());
int i = 0;
for (TypeLiteral> parameterType : getParameterTypes()) {
Annotation bindingAnnotation = getBindingAnnotation(getParameterAnnotations()[i]);
if (bindingAnnotation != null) {
parameterKeys.add(Key.get(parameterType, bindingAnnotation));
} else {
parameterKeys.add(Key.get(parameterType));
}
i++;
}
}
/**
* Returns the method's declaring type and name in the format used in
* javadoc, e.g. {@code com.bar.Foo#baz(com.bar.Foo, com.bar.Bar)}, with
* resolved type parameters.
*
* @return string representation for this method including the declaring type
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getName()).append("(");
List parameters = new ArrayList();
for (Type parameterType : getRawParameterTypes()) {
// TODO(schmitt): We are not respecting varargs here.
parameters.add(MoreTypes.typeToString(parameterType));
}
sb.append(join(", ", parameters)).append(")");
return String.format("%s#%s", getDeclaringType(), sb.toString());
}
/**
* Constructor-specific implementation of {@link MethodLiteral}.
*/
private static class ConstructorLiteral extends MethodLiteral> {
ConstructorLiteral(Constructor> constructor, TypeLiteral declaringType) {
super(constructor, declaringType);
}
@Override
public TypeLiteral> getReturnType() {
return getDeclaringType();
}
@Override
public boolean isConstructor() {
return true;
}
@Override
protected Annotation[][] getParameterAnnotations() {
return getMember().getParameterAnnotations();
}
@Override
public List getRawParameterTypes() {
return Arrays.asList(getMember().getGenericParameterTypes());
}
}
/**
* Method-specific implementation of {@link MethodLiteral}.
*/
private static class ConcreteMethodLiteral extends MethodLiteral {
ConcreteMethodLiteral(Method method, TypeLiteral typeLiteral) {
super(method, typeLiteral);
}
@Override
public TypeLiteral> getReturnType() {
return getDeclaringType().getReturnType(getMember());
}
@Override
public boolean isConstructor() {
return false;
}
@Override
protected Annotation[][] getParameterAnnotations() {
return getMember().getParameterAnnotations();
}
@Override
public List getRawParameterTypes() {
return Arrays.asList(getMember().getGenericParameterTypes());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy