/** * Template method to convert a {@code null} source. * <p>The default implementation returns {@code null} or the Java 8 * {@link java.util.Optional#empty()} instance if the target type is * {@code java.util.Optional}. Subclasses may override this to return * custom {@code null} objects for specific target types. * @param sourceType the source type to convert from * @param targetType the target type to convert to * @return the converted null object */ @Nullable protected Object convertNullSource(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { if (targetType.getObjectType() == Optional.class) { return Optional.empty(); } return null; }
@Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { Class<?> sourceClass = sourceType.getObjectType(); if (String.class == sourceClass) { // no conversion required return false; } return (CharSequence.class.isAssignableFrom(sourceClass) || StringWriter.class.isAssignableFrom(sourceClass) || ObjectToObjectConverter.hasConversionMethodOrConstructor(sourceClass, String.class)); }
@Nullable private Object handleConverterNotFound( @Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { assertNotPrimitiveTargetType(sourceType, targetType); return null; } if ((sourceType == null || sourceType.isAssignableTo(targetType)) && targetType.getObjectType().isInstance(source)) { return source; } throw new ConverterNotFoundException(sourceType, targetType); }
@Override @Nullable public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return convertNullSource(sourceType, targetType); } return this.converterFactory.getConverter(targetType.getObjectType()).convert(source); }
@Override public boolean canConvert(TypeDescriptor sourceTypeDescriptor, TypeDescriptor targetTypeDescriptor) { if (conversionService.canConvert(sourceTypeDescriptor, targetTypeDescriptor)) { return true; } // TODO: what does this mean? This method is not used in SpEL so probably ignorable? Class<?> sourceType = sourceTypeDescriptor.getObjectType(); Class<?> targetType = targetTypeDescriptor.getObjectType(); return canConvert(sourceType, targetType); }
@Override public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { // Check raw type first... if (this.typeInfo.getTargetType() != targetType.getObjectType()) { return false; } // Full check for complex generic type match required? ResolvableType rt = targetType.getResolvableType(); if (!(rt.getType() instanceof Class) && !rt.isAssignableFrom(this.targetType) && !this.targetType.hasUnresolvableGenerics()) { return false; } return !(this.converter instanceof ConditionalConverter) || ((ConditionalConverter) this.converter).matches(sourceType, targetType); }
@Test public void test_binaryPlusWithTime_ToString() { ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext()); Time time = new Time(new Date().getTime()); VariableReference var = new VariableReference("timeVar", -1, -1); var.setValue(expressionState, time); StringLiteral n2 = new StringLiteral("\" is now\"", -1, -1, "\" is now\""); OpPlus o = new OpPlus(-1, -1, var, n2); TypedValue value = o.getValueInternal(expressionState); assertEquals(String.class, value.getTypeDescriptor().getObjectType()); assertEquals(String.class, value.getTypeDescriptor().getType()); assertEquals(time + " is now", value.getValue()); }
@Test public void fieldScalar() throws Exception { TypeDescriptor typeDescriptor = new TypeDescriptor(getClass().getField("fieldScalar")); assertFalse(typeDescriptor.isPrimitive()); assertFalse(typeDescriptor.isArray()); assertFalse(typeDescriptor.isCollection()); assertFalse(typeDescriptor.isMap()); assertEquals(Integer.class, typeDescriptor.getType()); assertEquals(Integer.class, typeDescriptor.getObjectType()); }
@Test public void parameterPrimitive() throws Exception { TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterPrimitive", int.class), 0)); assertEquals(int.class, desc.getType()); assertEquals(Integer.class, desc.getObjectType()); assertEquals("int", desc.getName()); assertEquals("int", desc.toString()); assertTrue(desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertFalse(desc.isCollection()); assertFalse(desc.isMap()); }
@Test public void parameterScalar() throws Exception { TypeDescriptor desc = new TypeDescriptor(new MethodParameter(getClass().getMethod("testParameterScalar", String.class), 0)); assertEquals(String.class, desc.getType()); assertEquals(String.class, desc.getObjectType()); assertEquals("java.lang.String", desc.getName()); assertEquals("java.lang.String", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertFalse(desc.isCollection()); assertFalse(desc.isArray()); assertFalse(desc.isMap()); }
@Test public void parameterListNoParamTypes() throws Exception { MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterListNoParamTypes", List.class), 0); TypeDescriptor desc = new TypeDescriptor(methodParameter); assertEquals(List.class, desc.getType()); assertEquals(List.class, desc.getObjectType()); assertEquals("java.util.List", desc.getName()); assertEquals("java.util.List<?>", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertTrue(desc.isCollection()); assertFalse(desc.isArray()); assertNull(desc.getElementTypeDescriptor()); assertFalse(desc.isMap()); }
@Test public void valueOfScalar() { TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(Integer.class); assertFalse(typeDescriptor.isPrimitive()); assertFalse(typeDescriptor.isArray()); assertFalse(typeDescriptor.isCollection()); assertFalse(typeDescriptor.isMap()); assertEquals(Integer.class, typeDescriptor.getType()); assertEquals(Integer.class, typeDescriptor.getObjectType()); }
@Test public void valueOfPrimitive() { TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(int.class); assertTrue(typeDescriptor.isPrimitive()); assertFalse(typeDescriptor.isArray()); assertFalse(typeDescriptor.isCollection()); assertFalse(typeDescriptor.isMap()); assertEquals(Integer.TYPE, typeDescriptor.getType()); assertEquals(Integer.class, typeDescriptor.getObjectType()); }
@Test public void test_binaryPlusWithLeftStringOperand() { ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext()); StringLiteral n1 = new StringLiteral("\"number is \"", -1, -1, "\"number is \""); LongLiteral n2 = new LongLiteral("123", -1, -1, 123); OpPlus o = new OpPlus(-1, -1, n1, n2); TypedValue value = o.getValueInternal(expressionState); assertEquals(String.class, value.getTypeDescriptor().getObjectType()); assertEquals(String.class, value.getTypeDescriptor().getType()); assertEquals("number is 123", value.getValue()); }
@Test public void test_binaryPlusWithStringOperands() { ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext()); StringLiteral n1 = new StringLiteral("\"foo\"", -1, -1, "\"foo\""); StringLiteral n2 = new StringLiteral("\"bar\"", -1, -1, "\"bar\""); OpPlus o = new OpPlus(-1, -1, n1, n2); TypedValue value = o.getValueInternal(expressionState); assertEquals(String.class, value.getTypeDescriptor().getObjectType()); assertEquals(String.class, value.getTypeDescriptor().getType()); assertEquals("foobar", value.getValue()); }
@Test public void test_binaryPlusWithRightStringOperand() { ExpressionState expressionState = new ExpressionState(new StandardEvaluationContext()); LongLiteral n1 = new LongLiteral("123", -1, -1, 123); StringLiteral n2 = new StringLiteral("\" is a number\"", -1, -1, "\" is a number\""); OpPlus o = new OpPlus(-1, -1, n1, n2); TypedValue value = o.getValueInternal(expressionState); assertEquals(String.class, value.getTypeDescriptor().getObjectType()); assertEquals(String.class, value.getTypeDescriptor().getType()); assertEquals("123 is a number", value.getValue()); }
@Test public void parameterArray() throws Exception { MethodParameter methodParameter = new MethodParameter(getClass().getMethod("testParameterArray", Integer[].class), 0); TypeDescriptor desc = new TypeDescriptor(methodParameter); assertEquals(Integer[].class, desc.getType()); assertEquals(Integer[].class, desc.getObjectType()); assertEquals("java.lang.Integer[]", desc.getName()); assertEquals("java.lang.Integer[]", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertFalse(desc.isCollection()); assertTrue(desc.isArray()); assertEquals(Integer.class, desc.getElementTypeDescriptor().getType()); assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor()); assertFalse(desc.isMap()); }
@Test public void collection() { TypeDescriptor desc = TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class)); assertEquals(List.class, desc.getType()); assertEquals(List.class, desc.getObjectType()); assertEquals("java.util.List", desc.getName()); assertEquals("java.util.List<java.lang.Integer>", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertTrue(desc.isCollection()); assertFalse(desc.isArray()); assertEquals(Integer.class, desc.getElementTypeDescriptor().getType()); assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor()); assertFalse(desc.isMap()); }
@Test public void map() { TypeDescriptor desc = TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)); assertEquals(Map.class, desc.getType()); assertEquals(Map.class, desc.getObjectType()); assertEquals("java.util.Map", desc.getName()); assertEquals("java.util.Map<java.lang.String, java.lang.Integer>", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertFalse(desc.isCollection()); assertFalse(desc.isArray()); assertTrue(desc.isMap()); assertEquals(String.class, desc.getMapKeyTypeDescriptor().getType()); assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getType()); }
@Test public void collectionNested() { TypeDescriptor desc = TypeDescriptor.collection(List.class, TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class))); assertEquals(List.class, desc.getType()); assertEquals(List.class, desc.getObjectType()); assertEquals("java.util.List", desc.getName()); assertEquals("java.util.List<java.util.List<java.lang.Integer>>", desc.toString()); assertTrue(!desc.isPrimitive()); assertEquals(0, desc.getAnnotations().length); assertTrue(desc.isCollection()); assertFalse(desc.isArray()); assertEquals(List.class, desc.getElementTypeDescriptor().getType()); assertEquals(TypeDescriptor.valueOf(Integer.class), desc.getElementTypeDescriptor().getElementTypeDescriptor()); assertFalse(desc.isMap()); }