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

com.google.inject.assistedinject.Parameter Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
/**
 * Copyright (C) 2007 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.inject.assistedinject;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.inject.ConfigurationException;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.internal.Annotations;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Models a method or constructor parameter.
 *
 * @author [email protected] (Jerome Mourits)
 * @author [email protected] (Jesse Wilson)
 */
class Parameter {
  
  private final Type type;
  private final boolean isAssisted;
  private final Annotation bindingAnnotation;
  private final boolean isProvider;

  private volatile Provider provider;

  public Parameter(Type type, Annotation[] annotations) {
    this.type = type;
    this.bindingAnnotation = getBindingAnnotation(annotations);
    this.isAssisted = hasAssistedAnnotation(annotations);
    this.isProvider = isProvider(type);
  }

  public boolean isProvidedByFactory() {
    return isAssisted;
  }
  
  public Type getType() {
    return type;
  }

  @Override
  public String toString() {
    StringBuilder result = new StringBuilder();
    if (isAssisted) {
      result.append("@Assisted ");
    }
    if (bindingAnnotation != null) {
      result.append(bindingAnnotation).append(" ");
    }
    return result.append(type).toString();
  }

  private boolean hasAssistedAnnotation(Annotation[] annotations) {
    for (Annotation annotation : annotations) {
      if (annotation.annotationType().equals(Assisted.class)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns the Guice {@link Key} for this parameter.
   */
  public Object getValue(Injector injector) {
    if (null == provider) {
      synchronized (this) {
        if (null == provider) {
          provider = isProvider
              ? injector.getProvider(getBindingForType(getProvidedType(type)))
              : injector.getProvider(getPrimaryBindingKey());
        }
      }
    }

    return isProvider ? provider : provider.get();
  }

  public boolean isBound(Injector injector) {
    return isBound(injector, getPrimaryBindingKey())
        || isBound(injector, fixAnnotations(getPrimaryBindingKey()));
  }

  private boolean isBound(Injector injector, Key key) {
    // This method is particularly lame - we really need an API that can test
    // for any binding, implicit or explicit
    try {
      return injector.getBinding(key) != null;
    } catch (ConfigurationException e) {
      return false;
    }
  }

  /**
   * Replace annotation instances with annotation types, this is only
   * appropriate for testing if a key is bound and not for injecting.
   *
   * See Guice bug 125,
   * https://github.com/google/guice/issues/125
   */
  public Key fixAnnotations(Key key) {
    return key.getAnnotation() == null
        ? key
        : Key.get(key.getTypeLiteral(), key.getAnnotation().annotationType());
  }

  Key getPrimaryBindingKey() {
    return isProvider
        ? getBindingForType(getProvidedType(type))
        : getBindingForType(type);
  }

  private Type getProvidedType(Type type) {
    return ((ParameterizedType) type).getActualTypeArguments()[0];
  }

  private boolean isProvider(Type type) {
    return type instanceof ParameterizedType
        && ((ParameterizedType) type).getRawType() == Provider.class;
  }

  private Key getBindingForType(Type type) {
    return bindingAnnotation != null
        ? Key.get(type, bindingAnnotation)
        : Key.get(type);
  }

  /**
   * Returns the unique binding annotation from the specified list, or
   * {@code null} if there are none.
   *
   * @throws IllegalStateException if multiple binding annotations exist.
   */
  private Annotation getBindingAnnotation(Annotation[] annotations) {
    Annotation bindingAnnotation = null;
    for (Annotation annotation : annotations) {
      if (Annotations.isBindingAnnotation(annotation.annotationType())) {
        checkArgument(bindingAnnotation == null,
            "Parameter has multiple binding annotations: %s and %s", bindingAnnotation, annotation);
        bindingAnnotation = annotation;
      }
    }
    return bindingAnnotation;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy