
com.google.gwt.inject.rebind.util.GuiceUtil 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 2009 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.util;
import com.google.gwt.inject.client.Ginjector;
import com.google.gwt.inject.rebind.binding.Dependency;
import com.google.gwt.inject.rebind.binding.Injectable;
import com.google.gwt.inject.rebind.reflect.FieldLiteral;
import com.google.gwt.inject.rebind.reflect.MemberLiteral;
import com.google.gwt.inject.rebind.reflect.MethodLiteral;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Util object that offers helper methods which can retrieve {@link Key Keys}
* and additional dependency injection information on types or members.
*/
// TODO(schmitt): Figure out how to make this class entirely static (or move
// hasInject()).
@Singleton
public class GuiceUtil {
private final MemberCollector memberCollector;
@Inject
public GuiceUtil(@Injectable MemberCollector memberCollector) {
this.memberCollector = memberCollector;
}
/**
* Retrieves a key based on the passed {@link Ginjector} method. If the
* passed method is used for member injection, returns a key for the
* parameter, otherwise for the method return type. Always uses the method's
* binding annotation if present.
*
* @param method method for which to retrieve the key
* @return key based on passed method
*/
public Key> getKey(MethodLiteral, ?> method) {
if (isMemberInject(method)) {
return getKey(method.getParameterTypes().get(0).getType(), method.getBindingAnnotation());
}
return getKey(method.getReturnType().getType(), method.getBindingAnnotation());
}
/**
* Returns a key based on the passed field, taking any binding annotations
* into account.
*
* @param field field for which to retrieve the key
* @return key for passed field
*/
public Key> getKey(FieldLiteral> field) {
return getKey(field.getFieldType().getType(), field.getBindingAnnotation());
}
/**
* Gets the Guice binding key for a given Java type with optional
* annotations.
*
* @param type Java type to convert in to a key
* @param bindingAnnotation binding annotation for this key
* @return Guice Key instance for this type/annotations
* @throws ProvisionException in case of any failure
*/
private Key> getKey(Type type, Annotation bindingAnnotation) throws ProvisionException {
if (bindingAnnotation == null) {
return Key.get(type);
} else {
return Key.get(type, bindingAnnotation);
}
}
/**
* Returns true if the passed {@link Ginjector} method is used for member
* injection (i.e. takes exactly one parameter and returns void) or is a
* regular {@link Ginjector} method that returns a type.
*
* @param method method to be checked
* @return true if the passed method is used for member injection
*/
public boolean isMemberInject(MethodLiteral, ?> method) {
// TODO(schmitt): Consider returning an enum for the type of ginjector
// method instead.
return method.getReturnType().getRawType().equals(Void.TYPE);
}
/**
* Returns true if the passed method has an {@literal @}{@code Inject}
* annotation and the injection is marked as optional (
* {@literal @}{@code Inject(optional = true)}).
*
* Note that {@link javax.inject.Inject} does not have an optional parameter
* and therefore cannot be optional.
*
* @param member method to be checked
* @return true if method is injected optionally
*/
public boolean isOptional(MemberLiteral, ?> member) {
Inject annotation = member.getAnnotation(Inject.class);
return annotation != null && annotation.optional();
}
/**
* Collects and returns all keys required to member-inject the given class.
*
* @param typeKey key causing member injection
* @param type class for which required keys are calculated
* @return keys required to inject given class
*/
public Collection getMemberInjectionDependencies(
Key> typeKey, TypeLiteral> type) {
Set required = new LinkedHashSet();
for (MethodLiteral, Method> method : memberCollector.getMethods(type)) {
required.addAll(getDependencies(typeKey, method));
}
for (FieldLiteral> field : memberCollector.getFields(type)) {
Key> key = getKey(field);
required.add(new Dependency(typeKey, key, isOptional(field), false,
"member injection of " + field));
}
return required;
}
/**
* Collects and returns all keys required to inject the given method.
*
* @param typeKey the key that depends on injecting the arguments of method
* @param method method for which required keys are calculated
* @return required keys
*/
public Collection getDependencies(Key> typeKey, MethodLiteral, ?> method) {
String context;
if (method.isConstructor()) {
context = "@Inject constructor of " + method.getDeclaringType();
} else if (typeKey == Dependency.GINJECTOR) {
context = "Member injector " + method;
} else {
context = "Member injection via " + method;
}
Set required = new LinkedHashSet();
for (Key> key : method.getParameterKeys()) {
required.add(new Dependency(typeKey, key, isOptional(method), false, context));
}
return required;
}
/**
* Returns {@code true} if the passed member has a inject annotation.
*/
public static boolean hasInject(MemberLiteral, ?> member) {
return member.isAnnotationPresent(Inject.class)
|| member.isAnnotationPresent(javax.inject.Inject.class);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy