private static Stream<MetaClass> getConcreteBounds(final MetaType[] bounds) { return Arrays .stream(bounds) .flatMap(bound -> { if (bound instanceof MetaClass) { return Collections.singletonList(bound).stream(); } else if (bound instanceof MetaTypeVariable) { final MetaTypeVariable mtv = (MetaTypeVariable) bound; return getConcreteBounds(mtv.getBounds()); } else { return Collections.emptyList().stream(); } }).map(mt -> (MetaClass) mt); }
private static MetaClass getTypeVariableValue(final MetaTypeVariable typeVariable, final MetaClass clazz) { int idx = -1; final MetaTypeVariable[] typeVariables = clazz.getTypeParameters(); for (int i = 0; i < typeVariables.length; i++) { if (typeVariables[i].getName().equals(typeVariable.getName())) { idx = i; break; } } if (idx != -1) { final MetaType type = clazz.getParameterizedType().getTypeParameters()[idx]; if (type instanceof MetaClass) { return (MetaClass) type; } } return null; }
@Test public void testFieldWithTwoUpperBoundedTypeVarParam() throws Exception { final MetaClass metaClass = getMetaClass(ClassWithGenericCollections.class); final MetaMethod field = metaClass.getDeclaredMethod("hasDoubleBoundedTypeVarFromSelf", new Class[] {}); assertNotNull(field); final MetaTypeVariable returnType = (MetaTypeVariable) field.getGenericReturnType(); assertEquals("B", returnType.getName()); assertEquals("Should have two upper bounds", Arrays.asList(getMetaClass(Collection.class), getMetaClass(Serializable.class)), Arrays.asList(returnType.getBounds())); }
@Test public void testFieldWithSingleUpperBoundedTypeVarParam() throws Exception { final MetaClass metaClass = getMetaClass(ClassWithGenericCollections.class); final MetaMethod field = metaClass.getDeclaredMethod("hasSingleBoundedTypeVarFromSelf", new Class[] {}); assertNotNull(field); final MetaTypeVariable returnType = (MetaTypeVariable) field.getGenericReturnType(); assertEquals("B", returnType.getName()); assertEquals("Should have a single upper bound", Arrays.asList(getMetaClass(Serializable.class)), Arrays.asList(returnType.getBounds())); }
@Test public void testFieldWithUnboundedTypeVarParam() throws Exception { final MetaClass metaClass = getMetaClass(ClassWithGenericCollections.class); final MetaField field = metaClass.getDeclaredField("hasUnboundedTypeVarFromClass"); assertNotNull(field); assertEquals("Collection", field.getType().getName()); assertEquals("java.util.Collection", field.getType().getFullyQualifiedName()); assertEquals("java.util.Collection<T>", field.getType().getParameterizedType().getName()); assertEquals("java.util.Collection<T>", field.getType().getFullyQualifiedNameWithTypeParms()); assertEquals("java.util.Collection", field.getType().getErased().getFullyQualifiedNameWithTypeParms()); assertEquals(1, field.getType().getParameterizedType().getTypeParameters().length); final MetaTypeVariable typeVar = (MetaTypeVariable) field.getType().getParameterizedType().getTypeParameters()[0]; assertEquals("T", typeVar.getName()); assertEquals("Should have no upper bound", Arrays.asList(getMetaClass(Object.class)), Arrays.asList(typeVar.getBounds())); }
private static Stream<MetaClass> getConcreteBounds(final MetaType[] bounds) { return Arrays .stream(bounds) .flatMap(bound -> { if (bound instanceof MetaClass) { return Collections.singletonList(bound).stream(); } else if (bound instanceof MetaTypeVariable) { final MetaTypeVariable mtv = (MetaTypeVariable) bound; return getConcreteBounds(mtv.getBounds()); } else { return Collections.emptyList().stream(); } }).map(mt -> (MetaClass) mt); }
private static MetaClass getTypeVariableValue(final MetaTypeVariable typeVariable, final MetaClass clazz) { int idx = -1; final MetaTypeVariable[] typeVariables = clazz.getTypeParameters(); for (int i = 0; i < typeVariables.length; i++) { if (typeVariables[i].getName().equals(typeVariable.getName())) { idx = i; break; } } if (idx != -1) { final MetaType type = clazz.getParameterizedType().getTypeParameters()[idx]; if (type instanceof MetaClass) { return (MetaClass) type; } } return null; }
private MetaClass getTypeOrFirstUpperBound(MetaType clazz, final MetaMethod method) { if (clazz instanceof MetaTypeVariable) { final MetaType[] bounds = ((MetaTypeVariable) clazz).getBounds(); if (bounds.length == 1 && bounds[0] instanceof MetaClass) { clazz = ((MetaTypeVariable) clazz).getBounds()[0]; } else { // TODO add full support for generics in errai codegen logger.log(TreeLogger.WARN, "Ignoring method: " + method + " in class " + bindable + ". Methods using " + "multiple type parameters or type parameters with multiple bounds are currently not supported in " + "@Bindable types! Invoking this method on a bound model will have unpredictable results."); return null; } } else if (clazz instanceof MetaParameterizedType) { clazz = ((MetaParameterizedType) clazz).getRawType(); } if (clazz instanceof MetaClass) { return (MetaClass) clazz; } logger.log(TreeLogger.WARN, "Ignoring method: " + method + " in class " + bindable + ". Method cannot be proxied!"); return null; }
@Override public MetaClass getType() { MetaClass returnType = method.getReturnType(); if (method.getGenericReturnType() != null && method.getGenericReturnType() instanceof MetaTypeVariable) { typeVariables = new HashMap<String, MetaClass>(); resolveTypeVariables(); final MetaTypeVariable typeVar = (MetaTypeVariable) method.getGenericReturnType(); if (typeVariables.containsKey(typeVar.getName())) { returnType = typeVariables.get(typeVar.getName()); } else if (writer.getTypeParm(typeVar.getName()) != null) { returnType = writer.getTypeParm(typeVar.getName()); } else { // returning NullType as a stand-in for an unbounded wildcard type since this is a parameterized method // and there is not RHS qualification for the parameter. // // ie when calling GWT.create() and assigning it to a concrete type. // // TODO: might be worth flushing this out for clarify in the future. return MetaClassFactory.get(NullType.class); } } assert returnType != null; return returnType; }
private MetaClass getTypeOrFirstUpperBound(MetaType clazz, final MetaMethod method) { if (clazz instanceof MetaTypeVariable) { final MetaType[] bounds = ((MetaTypeVariable) clazz).getBounds(); if (bounds.length == 1 && bounds[0] instanceof MetaClass) { clazz = ((MetaTypeVariable) clazz).getBounds()[0]; } else { // TODO add full support for generics in errai codegen logger.log(TreeLogger.WARN, "Ignoring method: " + method + " in class " + bindable + ". Methods using " + "multiple type parameters or type parameters with multiple bounds are currently not supported in " + "@Bindable types! Invoking this method on a bound model will have unpredictable results."); return null; } } else if (clazz instanceof MetaParameterizedType) { clazz = ((MetaParameterizedType) clazz).getRawType(); } if (clazz instanceof MetaClass) { return (MetaClass) clazz; } logger.log(TreeLogger.WARN, "Ignoring method: " + method + " in class " + bindable + ". Method cannot be proxied!"); return null; }
@Override public MetaClass getType() { MetaClass returnType = method.getReturnType(); if (method.getGenericReturnType() != null && method.getGenericReturnType() instanceof MetaTypeVariable) { typeVariables = new HashMap<String, MetaClass>(); resolveTypeVariables(); final MetaTypeVariable typeVar = (MetaTypeVariable) method.getGenericReturnType(); if (typeVariables.containsKey(typeVar.getName())) { returnType = typeVariables.get(typeVar.getName()); } else if (writer.getTypeParm(typeVar.getName()) != null) { returnType = writer.getTypeParm(typeVar.getName()); } else { // returning NullType as a stand-in for an unbounded wildcard type since this is a parameterized method // and there is not RHS qualification for the parameter. // // ie when calling GWT.create() and assigning it to a concrete type. // // TODO: might be worth flushing this out for clarify in the future. return MetaClassFactory.get(NullType.class); } } assert returnType != null; return returnType; }
final boolean hasAssignableUpperBound = getConcreteBounds(((MetaTypeVariable) from).getBounds()) .filter(fromBound -> fromBound.isAssignableFrom((MetaClass) to)) .findAny()
throw new IllegalArgumentException("Call parameter \"" + callParmType + "\" is of unexpected metatype " + callParmType.getClass()); typeVariables.put(typeVar.getName(), resolvedType);
final boolean hasAssignableUpperBound = getConcreteBounds(((MetaTypeVariable) from).getBounds()) .filter(fromBound -> fromBound.isAssignableFrom((MetaClass) to)) .findAny()
throw new IllegalArgumentException("Call parameter \"" + callParmType + "\" is of unexpected metatype " + callParmType.getClass()); typeVariables.put(typeVar.getName(), resolvedType);
&& gSuperClass != null && gSuperClass.getTypeParameters().length > 0) { for (int i = 0; i < superClass.getTypeParameters().length; i++) { final String varName = superClass.getTypeParameters()[i].getName(); if (gSuperClass.getTypeParameters()[i] instanceof MetaClass) { typeVariables.put(varName, (MetaClass) gSuperClass.getTypeParameters()[i]);
&& gSuperClass != null && gSuperClass.getTypeParameters().length > 0) { for (int i = 0; i < superClass.getTypeParameters().length; i++) { final String varName = superClass.getTypeParameters()[i].getName(); if (gSuperClass.getTypeParameters()[i] instanceof MetaClass) { typeVariables.put(varName, (MetaClass) gSuperClass.getTypeParameters()[i]);
final MetaType type = ((MetaParameterizedType) genTypes[i]).getTypeParameters()[0]; if (type instanceof MetaTypeVariable) { writer.recordTypeParm(((MetaTypeVariable) type).getName(), (MetaClass) parameters[i]);
final MetaType type = ((MetaParameterizedType) genTypes[i]).getTypeParameters()[0]; if (type instanceof MetaTypeVariable) { writer.recordTypeParm(((MetaTypeVariable) type).getName(), (MetaClass) parameters[i]);
int i = 0; for (final MetaTypeVariable metaTypeVariable : toProxy.getTypeParameters()) { typeVariableMap.put(metaTypeVariable.getName(), metaParameterizedType.getTypeParameters()[i++]);