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}