static Class<?> getTypeClass(Type type) {

    if (type instanceof Class<?>) {
      return (Class<?>) type;
    }
    if (type instanceof ParameterizedType) {
      ParameterizedType pt = (ParameterizedType) type;
      Class<?> c = (Class<?>) pt.getRawType();
      if (ValuedEnum.class.isAssignableFrom(c)) {
        Type[] types = pt.getActualTypeArguments();
        if (types == null || types.length != 1) {
          c = int.class;
        } else {
          c = getTypeClass(pt.getActualTypeArguments()[0]);
        }
      }
      return c;
    }
    if (type instanceof GenericArrayType) {
      if (Object.class.isAssignableFrom(
          getTypeClass(((GenericArrayType) type).getGenericComponentType()))) {
        return Object[].class;
      }
    }
    throw new UnsupportedOperationException("Unknown type type : " + type.getClass().getName());
  }
    private boolean matchesArgs(Type[] parameterTypes, Annotation[][] anns, int offset) {
      int totalArgs = offset;
      for (int i = 0, n = templateArguments == null ? 0 : templateArguments.length; i < n; i++) {
        if (totalArgs >= parameterTypes.length) {
          return false;
        }

        Type paramType = parameterTypes[offset + i];

        TemplateArg arg = templateArguments[i];
        if (arg instanceof TypeRef) {
          if (!paramType.equals(Class.class)) {
            return false;
          }
        } else if (arg instanceof Constant) {
          try {
            getTypeClass(paramType).cast(((Constant) arg).value);
          } catch (ClassCastException ex) {
            return false;
          }
        }
        totalArgs++;
      }

      for (int i = 0, n = paramTypes == null ? 0 : paramTypes.length; i < n; i++) {
        if (totalArgs >= parameterTypes.length) {
          return false;
        }

        TypeRef paramType = paramTypes[i];
        Type parameterType = parameterTypes[totalArgs];
        if (!paramType.matches(parameterType, annotations(anns == null ? null : anns[i]))) {
          return false;
        }

        totalArgs++;
      }

      if (totalArgs != parameterTypes.length) {
        BridJ.error("Not enough args for " + this);
        return false;
      }

      return true;
    }
  static boolean equivalentTypes(
      Type a, Class ac, Annotations aAnnotations, Type b, Class bc, Annotations bAnnotations) {
    if (a.equals(b)) {
      return true;
    }

    int as = getIntegralSize(a, ac, aAnnotations);
    int bs = getIntegralSize(b, bc, bAnnotations);

    // System.out.println("a = " + a + ", b = " + b + ", as = " + as + ", bs = " + bs + ", equiv = "
    // + (as != -1 && as == bs));
    return as != -1 && as == bs;
  }