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.factory.config;
018:
019: import org.springframework.beans.BeanMetadataElement;
020: import org.springframework.util.Assert;
021: import org.springframework.util.ClassUtils;
022: import org.springframework.util.ObjectUtils;
023:
024: /**
025: * Holder for a typed String value. Can be added to bean definitions
026: * in order to explicitly specify a target type for a String value,
027: * for example for collection elements.
028: *
029: * <p>This holder will just store the String value and the target type.
030: * The actual conversion will be performed by the bean factory.
031: *
032: * @author Juergen Hoeller
033: * @since 1.2
034: * @see BeanDefinition#getPropertyValues
035: * @see org.springframework.beans.MutablePropertyValues#addPropertyValue
036: */
037: public class TypedStringValue implements BeanMetadataElement {
038:
039: private String value;
040:
041: private Object targetType;
042:
043: private Object source;
044:
045: /**
046: * Create a new {@link TypedStringValue} for the given String value.
047: * @param value the String value
048: */
049: public TypedStringValue(String value) {
050: setValue(value);
051: }
052:
053: /**
054: * Create a new {@link TypedStringValue} for the given String value
055: * and target type.
056: * @param value the String value
057: * @param targetType the type to convert to
058: */
059: public TypedStringValue(String value, Class targetType) {
060: setValue(value);
061: setTargetType(targetType);
062: }
063:
064: /**
065: * Create a new {@link TypedStringValue} for the given String value
066: * and target type.
067: * @param value the String value
068: * @param targetTypeName the type to convert to
069: */
070: public TypedStringValue(String value, String targetTypeName) {
071: setValue(value);
072: setTargetTypeName(targetTypeName);
073: }
074:
075: /**
076: * Set the String value.
077: * Only necessary for manipulating a registered value,
078: * for example in BeanFactoryPostProcessors.
079: * @see PropertyPlaceholderConfigurer
080: */
081: public void setValue(String value) {
082: this .value = value;
083: }
084:
085: /**
086: * Return the String value.
087: */
088: public String getValue() {
089: return this .value;
090: }
091:
092: /**
093: * Set the type to convert to.
094: * Only necessary for manipulating a registered value,
095: * for example in BeanFactoryPostProcessors.
096: * @see PropertyPlaceholderConfigurer
097: */
098: public void setTargetType(Class targetType) {
099: Assert.notNull(targetType, "'targetType' must not be null");
100: this .targetType = targetType;
101: }
102:
103: /**
104: * Return the type to convert to.
105: */
106: public Class getTargetType() {
107: if (!(this .targetType instanceof Class)) {
108: throw new IllegalStateException(
109: "Typed String value does not carry a resolved target type");
110: }
111: return (Class) this .targetType;
112: }
113:
114: /**
115: * Specify the type to convert to.
116: */
117: public void setTargetTypeName(String targetTypeName) {
118: Assert.notNull(targetTypeName,
119: "'targetTypeName' must not be null");
120: this .targetType = targetTypeName;
121: }
122:
123: /**
124: * Return the type to convert to.
125: */
126: public String getTargetTypeName() {
127: if (this .targetType instanceof Class) {
128: return ((Class) this .targetType).getName();
129: } else {
130: return (String) this .targetType;
131: }
132: }
133:
134: /**
135: * Return whether this typed String value carries a target type .
136: */
137: public boolean hasTargetType() {
138: return (this .targetType instanceof Class);
139: }
140:
141: /**
142: * Determine the type to convert to, resolving it from a specified class name
143: * if necessary. Will also reload a specified Class from its name when called
144: * with the target type already resolved.
145: * @param classLoader the ClassLoader to use for resolving a (potential) class name
146: * @return the resolved type to convert to
147: * @throws ClassNotFoundException if the type cannot be resolved
148: */
149: public Class resolveTargetType(ClassLoader classLoader)
150: throws ClassNotFoundException {
151: if (this .targetType == null) {
152: return null;
153: }
154: Class resolvedClass = ClassUtils.forName(getTargetTypeName(),
155: classLoader);
156: this .targetType = resolvedClass;
157: return resolvedClass;
158: }
159:
160: /**
161: * Set the configuration source <code>Object</code> for this metadata element.
162: * <p>The exact type of the object will depend on the configuration mechanism used.
163: */
164: public void setSource(Object source) {
165: this .source = source;
166: }
167:
168: public Object getSource() {
169: return this .source;
170: }
171:
172: public boolean equals(Object other) {
173: if (this == other) {
174: return true;
175: }
176: if (!(other instanceof TypedStringValue)) {
177: return false;
178: }
179: TypedStringValue otherValue = (TypedStringValue) other;
180: return (ObjectUtils
181: .nullSafeEquals(this .value, otherValue.value) && ObjectUtils
182: .nullSafeEquals(this .targetType, otherValue.targetType));
183: }
184:
185: public int hashCode() {
186: return ObjectUtils.nullSafeHashCode(this .value) * 29
187: + ObjectUtils.nullSafeHashCode(this .targetType);
188: }
189:
190: public String toString() {
191: return "TypedStringValue: value [" + this .value
192: + "], target type [" + this .targetType + "]";
193: }
194:
195: }
|