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 java.util.HashMap;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import org.springframework.beans.MutablePropertyValues;
027: import org.springframework.beans.PropertyValue;
028: import org.springframework.util.ObjectUtils;
029:
030: /**
031: * Visitor base class for traversing {@link BeanDefinition} objects, in particular
032: * the property values and constructor argument values contained in them.
033: *
034: * <p>The abstract {@link #resolveStringValue} method has to be implemented
035: * in concrete subclasses, following arbitrary resolution strategies.
036: *
037: * <p>Used by {@link PropertyPlaceholderConfigurer} to parse all String values
038: * contained in a BeanDefinition, resolving any placeholders found.
039: *
040: * @author Juergen Hoeller
041: * @since 1.2
042: * @see BeanDefinition
043: * @see BeanDefinition#getPropertyValues
044: * @see BeanDefinition#getConstructorArgumentValues
045: * @see #resolveStringValue(String)
046: * @see PropertyPlaceholderConfigurer
047: */
048: public abstract class BeanDefinitionVisitor {
049:
050: /**
051: * Traverse the given BeanDefinition object and the MutablePropertyValues
052: * and ConstructorArgumentValues contained in them.
053: * @param beanDefinition the BeanDefinition object to traverse
054: * @see #resolveStringValue(String)
055: */
056: public void visitBeanDefinition(BeanDefinition beanDefinition) {
057: visitBeanClassName(beanDefinition);
058: visitScope(beanDefinition);
059: visitPropertyValues(beanDefinition.getPropertyValues());
060: ConstructorArgumentValues cas = beanDefinition
061: .getConstructorArgumentValues();
062: visitIndexedArgumentValues(cas.getIndexedArgumentValues());
063: visitGenericArgumentValues(cas.getGenericArgumentValues());
064: }
065:
066: protected void visitBeanClassName(BeanDefinition beanDefinition) {
067: String beanClassName = beanDefinition.getBeanClassName();
068: if (beanClassName != null) {
069: String resolvedName = resolveStringValue(beanClassName);
070: if (!beanClassName.equals(resolvedName)) {
071: beanDefinition.setBeanClassName(resolvedName);
072: }
073: }
074: }
075:
076: protected void visitScope(BeanDefinition beanDefinition) {
077: String scope = beanDefinition.getScope();
078: if (scope != null) {
079: String resolvedScope = resolveStringValue(scope);
080: if (!scope.equals(resolvedScope)) {
081: beanDefinition.setScope(resolvedScope);
082: }
083: }
084: }
085:
086: protected void visitPropertyValues(MutablePropertyValues pvs) {
087: PropertyValue[] pvArray = pvs.getPropertyValues();
088: for (int i = 0; i < pvArray.length; i++) {
089: PropertyValue pv = pvArray[i];
090: Object newVal = resolveValue(pv.getValue());
091: if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {
092: pvs.addPropertyValue(pv.getName(), newVal);
093: }
094: }
095: }
096:
097: protected void visitIndexedArgumentValues(Map ias) {
098: for (Iterator it = ias.values().iterator(); it.hasNext();) {
099: ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) it
100: .next();
101: Object newVal = resolveValue(valueHolder.getValue());
102: if (!ObjectUtils.nullSafeEquals(newVal, valueHolder
103: .getValue())) {
104: valueHolder.setValue(newVal);
105: }
106: }
107: }
108:
109: protected void visitGenericArgumentValues(List gas) {
110: for (Iterator it = gas.iterator(); it.hasNext();) {
111: ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) it
112: .next();
113: Object newVal = resolveValue(valueHolder.getValue());
114: if (!ObjectUtils.nullSafeEquals(newVal, valueHolder
115: .getValue())) {
116: valueHolder.setValue(newVal);
117: }
118: }
119: }
120:
121: protected Object resolveValue(Object value) {
122: if (value instanceof BeanDefinition) {
123: visitBeanDefinition((BeanDefinition) value);
124: } else if (value instanceof BeanDefinitionHolder) {
125: visitBeanDefinition(((BeanDefinitionHolder) value)
126: .getBeanDefinition());
127: } else if (value instanceof RuntimeBeanReference) {
128: RuntimeBeanReference ref = (RuntimeBeanReference) value;
129: String newBeanName = resolveStringValue(ref.getBeanName());
130: if (!newBeanName.equals(ref.getBeanName())) {
131: return new RuntimeBeanReference(newBeanName);
132: }
133: } else if (value instanceof List) {
134: visitList((List) value);
135: } else if (value instanceof Set) {
136: visitSet((Set) value);
137: } else if (value instanceof Map) {
138: visitMap((Map) value);
139: } else if (value instanceof TypedStringValue) {
140: TypedStringValue typedStringValue = (TypedStringValue) value;
141: String stringValue = typedStringValue.getValue();
142: if (stringValue != null) {
143: String visitedString = resolveStringValue(stringValue);
144: typedStringValue.setValue(visitedString);
145: }
146: } else if (value instanceof String) {
147: return resolveStringValue((String) value);
148: }
149: return value;
150: }
151:
152: protected void visitList(List listVal) {
153: for (int i = 0; i < listVal.size(); i++) {
154: Object elem = listVal.get(i);
155: Object newVal = resolveValue(elem);
156: if (!ObjectUtils.nullSafeEquals(newVal, elem)) {
157: listVal.set(i, newVal);
158: }
159: }
160: }
161:
162: protected void visitSet(Set setVal) {
163: for (Iterator it = new HashSet(setVal).iterator(); it.hasNext();) {
164: Object elem = it.next();
165: Object newVal = resolveValue(elem);
166: if (!ObjectUtils.nullSafeEquals(newVal, elem)) {
167: setVal.remove(elem);
168: setVal.add(newVal);
169: }
170: }
171: }
172:
173: protected void visitMap(Map mapVal) {
174: for (Iterator it = new HashMap(mapVal).entrySet().iterator(); it
175: .hasNext();) {
176: Map.Entry entry = (Map.Entry) it.next();
177: Object key = entry.getKey();
178: Object newKey = resolveValue(key);
179: boolean isNewKey = !ObjectUtils.nullSafeEquals(key, newKey);
180: Object val = entry.getValue();
181: Object newVal = resolveValue(val);
182: if (isNewKey) {
183: mapVal.remove(key);
184: }
185: if (isNewKey || !ObjectUtils.nullSafeEquals(newVal, val)) {
186: mapVal.put(newKey, newVal);
187: }
188: }
189: }
190:
191: /**
192: * Resolve the given String value, for example parsing placeholders.
193: * @param strVal the original String value
194: * @return the resolved String value
195: */
196: protected abstract String resolveStringValue(String strVal);
197:
198: }
|