All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.inject.rebind.reflect.MethodLiteral Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 2.1.2
Show newest version
/*
 * 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