001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.expression; 018 019import org.springframework.core.convert.TypeDescriptor; 020import org.springframework.util.ObjectUtils; 021 022/** 023 * Encapsulates an object and a {@link TypeDescriptor} that describes it. 024 * The type descriptor can contain generic declarations that would not 025 * be accessible through a simple {@code getClass()} call on the object. 026 * 027 * @author Andy Clement 028 * @author Juergen Hoeller 029 * @since 3.0 030 */ 031public class TypedValue { 032 033 public static final TypedValue NULL = new TypedValue(null); 034 035 036 private final Object value; 037 038 private TypeDescriptor typeDescriptor; 039 040 041 /** 042 * Create a {@link TypedValue} for a simple object. The {@link TypeDescriptor} 043 * is inferred from the object, so no generic declarations are preserved. 044 * @param value the object value 045 */ 046 public TypedValue(Object value) { 047 this.value = value; 048 this.typeDescriptor = null; // initialized when/if requested 049 } 050 051 /** 052 * Create a {@link TypedValue} for a particular value with a particular 053 * {@link TypeDescriptor} which may contain additional generic declarations. 054 * @param value the object value 055 * @param typeDescriptor a type descriptor describing the type of the value 056 */ 057 public TypedValue(Object value, TypeDescriptor typeDescriptor) { 058 this.value = value; 059 this.typeDescriptor = typeDescriptor; 060 } 061 062 063 public Object getValue() { 064 return this.value; 065 } 066 067 public TypeDescriptor getTypeDescriptor() { 068 if (this.typeDescriptor == null && this.value != null) { 069 this.typeDescriptor = TypeDescriptor.forObject(this.value); 070 } 071 return this.typeDescriptor; 072 } 073 074 075 @Override 076 public boolean equals(Object other) { 077 if (this == other) { 078 return true; 079 } 080 if (!(other instanceof TypedValue)) { 081 return false; 082 } 083 TypedValue otherTv = (TypedValue) other; 084 // Avoid TypeDescriptor initialization if not necessary 085 return (ObjectUtils.nullSafeEquals(this.value, otherTv.value) && 086 ((this.typeDescriptor == null && otherTv.typeDescriptor == null) || 087 ObjectUtils.nullSafeEquals(getTypeDescriptor(), otherTv.getTypeDescriptor()))); 088 } 089 090 @Override 091 public int hashCode() { 092 return ObjectUtils.nullSafeHashCode(this.value); 093 } 094 095 @Override 096 public String toString() { 097 return "TypedValue: '" + this.value + "' of [" + getTypeDescriptor() + "]"; 098 } 099 100}