Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   * JBoss, Home of Professional Open Source
   * Copyright 2012, Red Hat, Inc., and individual contributors
   * by the @authors tag. See the copyright.txt in the distribution for a
   * full listing of individual contributors.
   * 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
  * 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 org.jboss.weld.util.reflection;
 import java.util.Map;
 import java.util.Set;
Utility class that discovers transitive type closure of a given type.

Weld Community
Ales Justin
Marko Luksa
Jozef Hartinger
 public class HierarchyDiscovery {

Performs base type normalization before hierarchy discovery is performed.

Type normalization only affects parameterized types (e.g. public class Foo<T extends Serializable>) that are used in form of a raw type (e.g. Foo.class). During the process of type normalization, this raw type (Foo.class is instance of Class<?>) is replaced by a canonical version of the type which in this case would be the parameterized type of Foo<T extends Serializable>

Base type normalization means that only the base type, which is the input for hierarchy discovery, is normalized. Other types discovered during hierarchy discovery are never normalized even if a raw form of a parameterized type is discovered.

A user of this class should recognize whether base type normalization is required and set the normalize parameter accordingly.

In the realm of CDI there is only a single use-case for base type normalization. That is resolving bean types of a bean defined as a class (managed and session beans). Here, e.g. discovered Foo.class needs to be normalized as the correct CDI bean type is Foo<T extends Serializable>, not Foo.class.

In other cases, the complete generic information of the base type is known and thus base type normalization should not be used so that it does not cover intentionally declared raw types (e.g. an injection point with a raw type should be recognized as an injection point with a raw type, not it's canonical version). This covers:

  • type closure of an injection point or delegate
  • type closure of a producer field type
  • type closure of a producer method return type
  • type closure of a parameter type (observer, initializer, producer and disposer methods)
  • type closure of an event
     public static HierarchyDiscovery forNormalizedType(Type type) {
         return new HierarchyDiscovery(Types.getCanonicalType(type));
     private final Map<Class<?>, Typetypes;
     private final Map<TypeVariable<?>, TyperesolvedTypeVariables;
     private final TypeResolver resolver;

Constructs a new HierarchyDiscovery instance.

type the type whose hierarchy will be discovered
     public HierarchyDiscovery(Type type) {
         this(typenew TypeResolver(new HashMap<TypeVariable<?>, Type>()));
     public HierarchyDiscovery(Type typeTypeResolver resolver) {
         this. = new HashMap<Class<?>, Type>();
         this. = resolver;
         this. = resolver.getResolvedTypeVariables();
     public Set<TypegetTypeClosure() {
         return new ArraySet<Type>(this..values());
    public Map<Class<?>, TypegetTypeMap() {
        return ;
    protected void discoverTypes(Type typeboolean rawGeneric) {
        if (!rawGeneric) {
            rawGeneric = Types.isRawGenericType(type);
        if (type instanceof Class<?>) {
            Class<?> clazz = (Class<?>) type;
        } else if (rawGeneric) {
            discoverTypes(Reflections.getRawType(type), rawGeneric);
        } else if (type instanceof GenericArrayType) {
            GenericArrayType arrayType = (GenericArrayTypetype;
            Type genericComponentType = arrayType.getGenericComponentType();
            Class<?> rawComponentType = Reflections.getRawType(genericComponentType);
            if (rawComponentType != null) {
                Class<?> arrayClass = Array.newInstance(rawComponentType, 0).getClass();
        } else if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedTypetype;
            Type rawType = (parameterizedType).getRawType();
            if (rawType instanceof Class<?>) {
                Class<?> clazz = (Class<?>) rawType;
                processTypeVariables(clazz.getTypeParameters(), parameterizedType.getActualTypeArguments());
    protected void discoverFromClass(Class<?> clazzboolean rawGeneric) {
        if (clazz.getSuperclass() != null) {
            discoverTypes(processAndResolveType(clazz.getGenericSuperclass(), clazz.getSuperclass()), rawGeneric);
    protected void discoverInterfaces(Class<?> clazzboolean rawGeneric) {
        Type[] genericInterfaces = clazz.getGenericInterfaces();
        Class<?>[] interfaces = clazz.getInterfaces();
        if (genericInterfaces.length == interfaces.length) {
            // this branch should execute every time!
            for (int i = 0; i < interfaces.lengthi++) {
                discoverTypes(processAndResolveType(genericInterfaces[i], interfaces[i]), rawGeneric);
    protected Type processAndResolveType(Type superclassClass<?> rawSuperclass) {
        if (superclass instanceof ParameterizedType) {
            ParameterizedType parameterizedSuperclass = (ParameterizedTypesuperclass;
            processTypeVariables(rawSuperclass.getTypeParameters(), parameterizedSuperclass.getActualTypeArguments());
            return resolveType(parameterizedSuperclass);
        } else if (superclass instanceof Class<?>) {
            // this is not a parameterized type, nothing to resolve
            return superclass;
        throw new RuntimeException("Unexpected type: " + superclass);
     * Processing part. Every type variable is mapped to the actual type in the resolvedTypeVariablesMap. This map is used later
     * on for resolving types.
    private void processTypeVariables(TypeVariable<?>[] variablesType[] values) {
        for (int i = 0; i < variables.lengthi++) {
            processTypeVariable(variables[i], values[i]);
    private void processTypeVariable(TypeVariable<?> variableType value) {
        if (value instanceof TypeVariable<?>) {
            value = resolveType(value);
     * Resolving part. Using resolvedTypeVariables map which was prepared in the processing part.
    public Type resolveType(Type type) {
        if (type instanceof Class) {
            Type resolvedType = .get(type);
            if (resolvedType != null) {
                return resolvedType;
        return .resolveType(type);
    public TypeResolver getResolver() {
        return ;
New to GrepCode? Check out our FAQ X