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

juzu.impl.common.Introspector Maven / Gradle / Ivy

/*
 * Copyright 2013 eXo Platform SAS
 *
 * 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 juzu.impl.common;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;

/** @author Julien Viet */
public class Introspector {

  public static Class resolveToClass(Type implementation, Class type, int parameterIndex) {
    if (implementation == null) {
      throw new NullPointerException("No null type accepted");
    }

    // First resolve to type
    Type resolvedType = resolve(implementation, type, parameterIndex);

    //
    if (resolvedType != null) {
      return resolveToClass(resolvedType);
    } else {
      return null;
    }
  }

  public static Class resolveToClass(Type type) {
    if (type == null) {
      throw new NullPointerException("No null type accepted");
    }
    if (type instanceof Class) {
      return (Class)type;
    } else if (type instanceof TypeVariable) {
      TypeVariable resolvedTypeVariable = (TypeVariable)type;
      return resolveToClass(resolvedTypeVariable.getBounds()[0]);
    } else {
      throw new UnsupportedOperationException("Type resolution of " + type + " not yet implemented");
    }
  }

  /**
   * A simplistic implementation, it may not handle all cases but it should handle enough.
   *
   * @param implementation the type for which the parameter requires a resolution
   * @param type the type that owns the parameter
   * @param parameterIndex the parameter index
   * @return the resolved type
   */
  public static Type resolve(Type implementation, Class type, int parameterIndex) {
    if (implementation == null) {
      throw new NullPointerException();
    }

    //
    if (implementation == type) {
      TypeVariable>[] tp = type.getTypeParameters();
      if (parameterIndex < tp.length) {
        return tp[parameterIndex];
      } else {
        throw new IllegalArgumentException();
      }
    } else if (implementation instanceof Class) {
      Class c = (Class) implementation;
      Type gsc = c.getGenericSuperclass();
      Type resolved = null;
      if (gsc != null) {
        resolved = resolve(gsc, type, parameterIndex);
        if (resolved == null) {
          // Try with interface
        }
      }
      return resolved;
    } else if (implementation instanceof ParameterizedType) {
      ParameterizedType pt = (ParameterizedType) implementation;
      Type[] typeArgs = pt.getActualTypeArguments();
      Type rawType = pt.getRawType();
      if (rawType == type) {
        return typeArgs[parameterIndex];
      } else if (rawType instanceof Class) {
        Class classRawType = (Class)rawType;
        Type resolved = resolve(classRawType, type, parameterIndex);
        if (resolved == null) {
          return null;
        } else if (resolved instanceof TypeVariable) {
          TypeVariable resolvedTV = (TypeVariable)resolved;
          TypeVariable[] a = classRawType.getTypeParameters();
          for (int i = 0;i < a.length;i++) {
            if (a[i].equals(resolvedTV)) {
              return resolve(implementation, classRawType, i);
            }
          }
          throw new AssertionError();
        } else {
          throw new UnsupportedOperationException("Cannot support resolution of " + resolved);
        }
      } else {
        throw new UnsupportedOperationException();
      }
    } else {
      throw new UnsupportedOperationException("todo " + implementation + " " + implementation.getClass());
    }
  }

  public static boolean instanceOf(Class c, List types) {

    for (String type: types) {
      if (instanceOf(c, type)) {
        return true;
      }
    }

    return false;

  }


  public static boolean instanceOf(Class c, String type) {

    if (c.getName().equals(type)) {
      return true;
    }

    for (Class i : c.getInterfaces()) {
      if (instanceOf(i, type)) {
        return true;
      }
    }

    if (c.getSuperclass() != null) {
      return instanceOf(c.getSuperclass(), type);
    }

    return false;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy