/** * If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} * from the provided map key. * <p>Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property * to the class of the provided map key. For example, if this describes a * {@code java.util.Map<java.lang.Number, java.lang.String<} and the key * argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be * {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>} * and the key argument is a {@code java.lang.Integer}, the returned * TypeDescriptor will be {@code java.lang.Integer} as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param mapKey the map key * @return the map key type descriptor * @throws IllegalStateException if this type is not a {@code java.util.Map} * @see #narrow(Object) */ @Nullable public TypeDescriptor getMapKeyTypeDescriptor(Object mapKey) { return narrow(mapKey, getMapKeyTypeDescriptor()); }
/** * If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} * from the provided map value. * <p>Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property * to the class of the provided map value. For example, if this describes a * {@code java.util.Map<java.lang.String, java.lang.Number<} and the value * argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be * {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>} * and the value argument is a {@code java.lang.Integer}, the returned * TypeDescriptor will be {@code java.lang.Integer} as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param mapValue the map value * @return the map value type descriptor * @throws IllegalStateException if this type is not a {@code java.util.Map} * @see #narrow(Object) */ @Nullable public TypeDescriptor getMapValueTypeDescriptor(Object mapValue) { return narrow(mapValue, getMapValueTypeDescriptor()); }
/** * If this type is a {@link Collection} or an array, creates a element TypeDescriptor * from the provided collection or array element. * <p>Narrows the {@link #getElementTypeDescriptor() elementType} property to the class * of the provided collection or array element. For example, if this describes a * {@code java.util.List<java.lang.Number<} and the element argument is an * {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer}. * If this describes a {@code java.util.List<?>} and the element argument is an * {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer} * as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param element the collection or array element * @return a element type descriptor, narrowed to the type of the provided element * @throws IllegalStateException if this type is not a {@code java.util.Collection} * or array type * @see #narrow(Object) */ @Nullable public TypeDescriptor elementTypeDescriptor(Object element) { return narrow(element, getElementTypeDescriptor()); }
@Override public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException { if (this.member instanceof Method) { Method method = (Method) this.member; try { ReflectionUtils.makeAccessible(method); Object value = method.invoke(target); return new TypedValue(value, this.typeDescriptor.narrow(value)); } catch (Exception ex) { throw new AccessException("Unable to access property '" + name + "' through getter method", ex); } } else { Field field = (Field) this.member; try { ReflectionUtils.makeAccessible(field); Object value = field.get(target); return new TypedValue(value, this.typeDescriptor.narrow(value)); } catch (Exception ex) { throw new AccessException("Unable to access field '" + name + "'", ex); } } }
/** * If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} * from the provided map value. * <p>Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property * to the class of the provided map value. For example, if this describes a * {@code java.util.Map<java.lang.String, java.lang.Number<} and the value * argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be * {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>} * and the value argument is a {@code java.lang.Integer}, the returned * TypeDescriptor will be {@code java.lang.Integer} as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param mapValue the map value * @return the map value type descriptor * @throws IllegalStateException if this type is not a {@code java.util.Map} * @see #narrow(Object) */ @Nullable public TypeDescriptor getMapValueTypeDescriptor(Object mapValue) { return narrow(mapValue, getMapValueTypeDescriptor()); }
/** * If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} * from the provided map key. * <p>Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property * to the class of the provided map key. For example, if this describes a * {@code java.util.Map<java.lang.Number, java.lang.String<} and the key * argument is a {@code java.lang.Integer}, the returned TypeDescriptor will be * {@code java.lang.Integer}. If this describes a {@code java.util.Map<?, ?>} * and the key argument is a {@code java.lang.Integer}, the returned * TypeDescriptor will be {@code java.lang.Integer} as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param mapKey the map key * @return the map key type descriptor * @throws IllegalStateException if this type is not a {@code java.util.Map} * @see #narrow(Object) */ @Nullable public TypeDescriptor getMapKeyTypeDescriptor(Object mapKey) { return narrow(mapKey, getMapKeyTypeDescriptor()); }
/** * If this type is a {@link Collection} or an array, creates a element TypeDescriptor * from the provided collection or array element. * <p>Narrows the {@link #getElementTypeDescriptor() elementType} property to the class * of the provided collection or array element. For example, if this describes a * {@code java.util.List<java.lang.Number<} and the element argument is an * {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer}. * If this describes a {@code java.util.List<?>} and the element argument is an * {@code java.lang.Integer}, the returned TypeDescriptor will be {@code java.lang.Integer} * as well. * <p>Annotation and nested type context will be preserved in the narrowed * TypeDescriptor that is returned. * @param element the collection or array element * @return a element type descriptor, narrowed to the type of the provided element * @throws IllegalStateException if this type is not a {@code java.util.Collection} * or array type * @see #narrow(Object) */ @Nullable public TypeDescriptor elementTypeDescriptor(Object element) { return narrow(element, getElementTypeDescriptor()); }
@Override public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { try { this.argumentConversionOccurred = ReflectionHelper.convertArguments( context.getTypeConverter(), arguments, this.originalMethod, this.varargsPosition); if (this.originalMethod.isVarArgs()) { arguments = ReflectionHelper.setupArgumentsForVarargsInvocation( this.originalMethod.getParameterTypes(), arguments); } ReflectionUtils.makeAccessible(this.methodToInvoke); Object value = this.methodToInvoke.invoke(target, arguments); return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.originalMethod, -1)).narrow(value)); } catch (Exception ex) { throw new AccessException("Problem invoking method: " + this.methodToInvoke, ex); } }
@Override public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException { if (this.member instanceof Method) { Method method = (Method) this.member; try { ReflectionUtils.makeAccessible(method); Object value = method.invoke(target); return new TypedValue(value, this.typeDescriptor.narrow(value)); } catch (Exception ex) { throw new AccessException("Unable to access property '" + name + "' through getter method", ex); } } else { Field field = (Field) this.member; try { ReflectionUtils.makeAccessible(field); Object value = field.get(target); return new TypedValue(value, this.typeDescriptor.narrow(value)); } catch (Exception ex) { throw new AccessException("Unable to access field '" + name + "'", ex); } } }
Object result = method.invoke(method.getClass(), functionArgs); compilable = !argumentConversionOccurred; return new TypedValue(result, new TypeDescriptor(new MethodParameter(method, -1)).narrow(result));
@Test public void narrow() { TypeDescriptor desc = TypeDescriptor.valueOf(Number.class); Integer value = Integer.valueOf(3); desc = desc.narrow(value); assertEquals(Integer.class, desc.getType()); }
@Override public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { try { this.argumentConversionOccurred = ReflectionHelper.convertArguments( context.getTypeConverter(), arguments, this.originalMethod, this.varargsPosition); if (this.originalMethod.isVarArgs()) { arguments = ReflectionHelper.setupArgumentsForVarargsInvocation( this.originalMethod.getParameterTypes(), arguments); } ReflectionUtils.makeAccessible(this.methodToInvoke); Object value = this.methodToInvoke.invoke(target, arguments); return new TypedValue(value, new TypeDescriptor(new MethodParameter(this.originalMethod, -1)).narrow(value)); } catch (Exception ex) { throw new AccessException("Problem invoking method: " + this.methodToInvoke, ex); } }
Object result = method.invoke(method.getClass(), functionArgs); compilable = !argumentConversionOccurred; return new TypedValue(result, new TypeDescriptor(new MethodParameter(method, -1)).narrow(result));
private TypeDescriptor narrow(Object value, TypeDescriptor typeDescriptor) { if (typeDescriptor != null) { return typeDescriptor.narrow(value); } else { return (value != null ? new TypeDescriptor(value.getClass(), null, null, null, this.annotations) : null); } }
/** * If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} from the provided map value. * Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value. * For example, if this describes a java.util.Map<java.lang.String, java.lang.Number< and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer. * If this describes a java.util.Map<?, ?> and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well. * Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned. * @param mapValue the map value * @return the map value type descriptor * @throws IllegalStateException if this type is not a java.util.Map. */ public TypeDescriptor getMapValueTypeDescriptor(Object mapValue) { return narrow(mapValue, getMapValueTypeDescriptor()); }
/** * If this type is a {@link Collection} or an Array, creates a element TypeDescriptor from the provided collection or array element. * Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element. * For example, if this describes a java.util.List<java.lang.Number< and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer. * If this describes a java.util.List<?> and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well. * Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned. * @param element the collection or array element * @return a element type descriptor, narrowed to the type of the provided element * @throws IllegalStateException if this type is not a java.util.Collection or Array type * @see #narrow(Object) */ public TypeDescriptor elementTypeDescriptor(Object element) { return narrow(element, getElementTypeDescriptor()); }