001: /*
002: * Copyright 2002-2007 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: * http://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:
017: package org.springframework.beans;
018:
019: import java.io.Serializable;
020:
021: import org.springframework.core.AttributeAccessorSupport;
022: import org.springframework.util.Assert;
023: import org.springframework.util.ObjectUtils;
024:
025: /**
026: * Object to hold information and value for an individual bean property.
027: * Using an object here, rather than just storing all properties in
028: * a map keyed by property name, allows for more flexibility, and the
029: * ability to handle indexed properties etc in an optimized way.
030: *
031: * <p>Note that the value doesn't need to be the final required type:
032: * A {@link BeanWrapper} implementation should handle any necessary conversion,
033: * as this object doesn't know anything about the objects it will be applied to.
034: *
035: * @author Rod Johnson
036: * @author Rob Harrop
037: * @author Juergen Hoeller
038: * @since 13 May 2001
039: * @see PropertyValues
040: * @see BeanWrapper
041: */
042: public class PropertyValue extends AttributeAccessorSupport implements
043: BeanMetadataElement, Serializable {
044:
045: private final String name;
046:
047: private final Object value;
048:
049: private Object source;
050:
051: private boolean converted = false;
052:
053: private Object convertedValue;
054:
055: /** Package-visible field for caching the resolved property path tokens */
056: volatile Object resolvedTokens;
057:
058: /**
059: * Create a new PropertyValue instance.
060: * @param name the name of the property (never <code>null</code>)
061: * @param value the value of the property (possibly before type conversion)
062: */
063: public PropertyValue(String name, Object value) {
064: this .name = name;
065: this .value = value;
066: }
067:
068: /**
069: * Copy constructor.
070: * @param original the PropertyValue to copy (never <code>null</code>)
071: */
072: public PropertyValue(PropertyValue original) {
073: Assert.notNull(original, "Original must not be null");
074: this .name = original.getName();
075: this .value = original.getValue();
076: this .source = original.getSource();
077: copyAttributesFrom(original);
078: }
079:
080: /**
081: * Return the name of the property.
082: */
083: public String getName() {
084: return this .name;
085: }
086:
087: /**
088: * Return the value of the property.
089: * <p>Note that type conversion will <i>not</i> have occurred here.
090: * It is the responsibility of the BeanWrapper implementation to
091: * perform type conversion.
092: */
093: public Object getValue() {
094: return this .value;
095: }
096:
097: /**
098: * Set the configuration source <code>Object</code> for this metadata element.
099: * <p>The exact type of the object will depend on the configuration mechanism used.
100: */
101: public void setSource(Object source) {
102: this .source = source;
103: }
104:
105: public Object getSource() {
106: return this .source;
107: }
108:
109: /**
110: * Return whether this holder contains a converted value already (<code>true</code>),
111: * or whether the value still needs to be converted (<code>false</code>).
112: */
113: public synchronized boolean isConverted() {
114: return this .converted;
115: }
116:
117: /**
118: * Set the converted value of the constructor argument,
119: * after processed type conversion.
120: */
121: public synchronized void setConvertedValue(Object value) {
122: this .converted = true;
123: this .convertedValue = value;
124: }
125:
126: /**
127: * Return the converted value of the constructor argument,
128: * after processed type conversion.
129: */
130: public synchronized Object getConvertedValue() {
131: return this .convertedValue;
132: }
133:
134: public boolean equals(Object other) {
135: if (this == other) {
136: return true;
137: }
138: if (!(other instanceof PropertyValue)) {
139: return false;
140: }
141: PropertyValue otherPv = (PropertyValue) other;
142: return (this .name.equals(otherPv.name)
143: && ObjectUtils
144: .nullSafeEquals(this .value, otherPv.value) && ObjectUtils
145: .nullSafeEquals(this .source, otherPv.source));
146: }
147:
148: public int hashCode() {
149: return this .name.hashCode() * 29
150: + (this .value == null ? 0 : this .value.hashCode());
151: }
152:
153: public String toString() {
154: return "PropertyValue: name='" + this .name + "', value=["
155: + this .value + "]";
156: }
157:
158: }
|