/******************************************************************************
 * Copyright (c) 2006, 2010 VMware Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution. 
 * The Eclipse Public License is available at 
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
 * is available at http://www.opensource.org/licenses/apache2.0.php.
 * You may elect to redistribute this code under either of these licenses. 
 * 
 * Contributors:
 *   VMware Inc.
 *****************************************************************************/

package org.eclipse.gemini.blueprint.blueprint.config.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.blueprint.config.internal.support.InstanceEqualityRuntimeBeanReference;
import org.eclipse.gemini.blueprint.blueprint.reflect.internal.support.OrderedManagedProperties;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.parsing.BeanEntry;
import org.springframework.beans.factory.parsing.ConstructorArgumentEntry;
import org.springframework.beans.factory.parsing.ParseState;
import org.springframework.beans.factory.parsing.PropertyEntry;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.ManagedArray;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedProperties;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Stateful class that handles the parsing details of a &lt;component&gt; elements. Borrows heavily from
 * {@link BeanDefinitionParserDelegate}.
 * 
 * <b>Note</b>: Due to its stateful nature, this class is not thread safe.
 * 
 * <b>Note</b>: Since the namespace is important when parsing elements and since mixed elements, from both rfc124 and
 * Spring can coexist in the same file, reusing the {@link BeanDefinitionParserDelegate delegate} isn't entirely
 * possible since the two state needs to be kept in synch.
 * 
 * @author Costin Leau
 */
public class BlueprintParser {

	/** logger */
	private static final Log log = LogFactory.getLog(BlueprintParser.class);

	public static final String BEAN = "bean";
	public static final String COMPONENT_ID_ATTR = "component-id";
	public static final String CONSTRUCTOR_ARG = "argument";
	private static final String FACTORY_REF_ATTR = "factory-ref";
	private static final String LAZY_INIT_ATTR = "activation";
	private static final String LAZY_INIT_VALUE = "lazy";
	private static final String EAGER_INIT_VALUE = "eager";

	public static final String NAMESPACE_URI = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
	public static final String DECLARED_SCOPE = "org.eclipse.gemini.blueprint.blueprint.xml.bean.declared.scope";

	private final ParseState parseState;

	private final Collection<String> usedNames;

	private ParserContext parserContext;
	private BlueprintDefaultsDefinition defaults;

	public BlueprintParser() {
		this(null, null);
	}

	/**
	 * Constructs a new <code>ComponentParser</code> instance. Used by certain reusable static methods.
	 * 
	 * @param parserContext
	 */
	private BlueprintParser(ParserContext parserContext) {
		this(null, null);
		this.parserContext = parserContext;
	}

	public BlueprintParser(ParseState parseState, Collection<String> usedNames) {
		this.parseState = (parseState != null ? parseState : new ParseState());
		this.usedNames = (usedNames != null ? usedNames : new LinkedHashSet<String>());
	}

	public BeanDefinitionHolder parseAsHolder(Element componentElement, ParserContext parserContext) {
		// save parser context
		this.parserContext = parserContext;
		this.defaults = new BlueprintDefaultsDefinition(componentElement.getOwnerDocument(), parserContext);

		// let Spring do its standard parsing
		BeanDefinitionHolder bdHolder = parseComponentDefinitionElement(componentElement, null);

		BeanDefinition bd = bdHolder.getBeanDefinition();
		if (bd != null) {
			bd.setAttribute(ParsingUtils.BLUEPRINT_MARKER_NAME, Boolean.TRUE);
		}

		return bdHolder;
	}

	public BeanDefinition parse(Element componentElement, ParserContext parserContext) {
		return parseAsHolder(componentElement, parserContext).getBeanDefinition();
	}

	/**
	 * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code> if there were errors during
	 * parse. Errors are reported to the {@link org.springframework.beans.factory.parsing.ProblemReporter}.
	 */
	private BeanDefinitionHolder parseComponentDefinitionElement(Element ele, BeanDefinition containingBean) {

		// extract bean name
		String id = ele.getAttribute(BeanDefinitionParserDelegate.ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(BeanDefinitionParserDelegate.NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>(4);
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr =
					StringUtils.tokenizeToStringArray(nameAttr, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;

		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = (String) aliases.remove(0);
			if (log.isDebugEnabled()) {
				log.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases
						+ " as aliases");
			}
		}

		if (containingBean == null) {

			if (checkNameUniqueness(beanName, aliases, usedNames)) {
				error("Bean name '" + beanName + "' is already used in this file", ele);
			}

			if (ParsingUtils.isReservedName(beanName, ele, parserContext)) {
				error("Blueprint reserved name '" + beanName + "' cannot be used", ele);
			}
		}

		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName =
								ParsingUtils.generateBlueprintBeanName(beanDefinition, parserContext.getRegistry(),
										true);
					} else {
						beanName =
								ParsingUtils.generateBlueprintBeanName(beanDefinition, parserContext.getRegistry(),
										false);
						// TODO: should we support 2.0 behaviour (see below):
						// 
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
					}
					if (log.isDebugEnabled()) {
						log.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName
								+ "]");
					}
				} catch (Exception ex) {
					error(ex.getMessage(), ele, ex);
					return null;
				}
			}
			return new BeanDefinitionHolder(beanDefinition, beanName);
		}

		return null;
	}

	/**
	 * Parse the bean definition itself, without regard to name or aliases. May return <code>null</code> if problems
	 * occurred during the parse of the bean definition.
	 */
	private AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName,
			BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(BeanDefinitionParserDelegate.CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(BeanDefinitionParserDelegate.CLASS_ATTRIBUTE).trim();
		}

		try {
			AbstractBeanDefinition beanDefinition =
					BeanDefinitionReaderUtils.createBeanDefinition(null, className, parserContext.getReaderContext()
							.getBeanClassLoader());

			// some early validation
			String activation = ele.getAttribute(LAZY_INIT_ATTR);
			String scope = ele.getAttribute(BeanDefinitionParserDelegate.SCOPE_ATTRIBUTE);

			if (EAGER_INIT_VALUE.equals(activation) && BeanDefinition.SCOPE_PROTOTYPE.equals(scope)) {
				error("Prototype beans cannot be eagerly activated", ele);
			}

			// add marker to indicate that the scope was present
			if (StringUtils.hasText(scope)) {
				beanDefinition.setAttribute(DECLARED_SCOPE, Boolean.TRUE);
			}

			// parse attributes
			parseAttributes(ele, beanName, beanDefinition);

			// inner beans get a predefined scope in RFC 124
			if (containingBean != null) {
				beanDefinition.setLazyInit(true);
				beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
			}

			// parse description
			beanDefinition.setDescription(DomUtils.getChildElementValueByTagName(ele,
					BeanDefinitionParserDelegate.DESCRIPTION_ELEMENT));

			parseConstructorArgElements(ele, beanDefinition);
			parsePropertyElements(ele, beanDefinition);

			beanDefinition.setResource(parserContext.getReaderContext().getResource());
			beanDefinition.setSource(extractSource(ele));

			return beanDefinition;
		} catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		} catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		} catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		} finally {
			this.parseState.pop();
		}

		return null;
	}

	private AbstractBeanDefinition parseAttributes(Element ele, String beanName, AbstractBeanDefinition beanDefinition) {
		AbstractBeanDefinition bd =
				parserContext.getDelegate().parseBeanDefinitionAttributes(ele, beanName, null, beanDefinition);

		// handle lazy flag (initialize)
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTR);
		// check whether the value is "lazy"
		if (StringUtils.hasText(lazyInit)) {
			if (lazyInit.equalsIgnoreCase(LAZY_INIT_VALUE)) {
				bd.setLazyInit(true);
			} else {
				bd.setLazyInit(false);
			}
		} else {
			bd.setLazyInit(getDefaults(ele).getDefaultInitialization());
		}

		// handle factory component
		String componentFactory = ele.getAttribute(FACTORY_REF_ATTR);
		if (StringUtils.hasText(componentFactory)) {
			bd.setFactoryBeanName(componentFactory);
		}

		// check whether the bean is a prototype with destroy method
		if (StringUtils.hasText(bd.getDestroyMethodName())
				&& BeanDefinition.SCOPE_PROTOTYPE.equalsIgnoreCase(bd.getScope())) {
			error("Blueprint prototype beans cannot define destroy methods", ele);
		}

		return bd;
	}

	/**
	 * Validate that the specified bean name and aliases have not been used already.
	 */
	private boolean checkNameUniqueness(String beanName, Collection<String> aliases, Collection<String> usedNames) {
		String foundName = null;

		if (StringUtils.hasText(beanName) && usedNames.contains(beanName)) {
			foundName = beanName;
		}
		if (foundName == null) {
			foundName = (String) CollectionUtils.findFirstMatch(usedNames, aliases);
		}

		usedNames.add(beanName);
		usedNames.addAll(aliases);

		return (foundName != null);
	}

	/**
	 * Parsers contructor arguments.
	 * 
	 * @param ele
	 * @param beanDefinition
	 * @param parserContext
	 */
	private void parseConstructorArgElements(Element ele, AbstractBeanDefinition beanDefinition) {

		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element && DomUtils.nodeNameEquals(node, CONSTRUCTOR_ARG)) {
				parseConstructorArgElement((Element) node, beanDefinition);
			}
		}
	}

	private void parseConstructorArgElement(Element ele, AbstractBeanDefinition beanDefinition) {

		String indexAttr = ele.getAttribute(BeanDefinitionParserDelegate.INDEX_ATTRIBUTE);
		String typeAttr = ele.getAttribute(BeanDefinitionParserDelegate.TYPE_ATTRIBUTE);

		boolean hasIndex = false;
		int index = -1;

		if (StringUtils.hasLength(indexAttr)) {
			hasIndex = true;
			try {
				index = Integer.parseInt(indexAttr);
			} catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}

			if (index < 0) {
				error("'index' cannot be lower than 0", ele);
			}
		}

		try {
			this.parseState.push(hasIndex ? new ConstructorArgumentEntry(index) : new ConstructorArgumentEntry());

			ConstructorArgumentValues values = beanDefinition.getConstructorArgumentValues();
			// Blueprint failure (index duplication)
			Integer indexInt = Integer.valueOf(index);
			if (values.getIndexedArgumentValues().containsKey(indexInt)) {
				error("duplicate 'index' with value=[" + index + "] specified", ele);
			}

			Object value = parsePropertyValue(ele, beanDefinition, null);
			ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
			if (StringUtils.hasLength(typeAttr)) {
				valueHolder.setType(typeAttr);
			}
			valueHolder.setSource(extractSource(ele));

			if (hasIndex) {
				values.addIndexedArgumentValue(index, valueHolder);
			} else {
				values.addGenericArgumentValue(valueHolder);
			}
			// Blueprint failure (mixed index/non-indexed arguments)
			if (!values.getGenericArgumentValues().isEmpty() && !values.getIndexedArgumentValues().isEmpty()) {
				error("indexed and non-indexed constructor arguments are not supported by Blueprint; "
						+ "consider using the Spring namespace instead", ele);
			}
		} finally {
			this.parseState.pop();
		}
	}

	/**
	 * Parses property elements.
	 * 
	 * @param ele
	 * @param beanDefinition
	 * @param parserContext
	 */
	private void parsePropertyElements(Element ele, AbstractBeanDefinition beanDefinition) {

		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element && DomUtils.nodeNameEquals(node, BeanDefinitionParserDelegate.PROPERTY_ELEMENT)) {
				parsePropertyElement((Element) node, beanDefinition);
			}
		}
	}

	private void parsePropertyElement(Element ele, BeanDefinition bd) {
		String propertyName = ele.getAttribute(BeanDefinitionParserDelegate.NAME_ATTRIBUTE);
		if (!StringUtils.hasLength(propertyName)) {
			error("Tag 'property' must have a 'name' attribute", ele);
			return;
		}
		this.parseState.push(new PropertyEntry(propertyName));
		try {
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			Object val = parsePropertyValue(ele, bd, propertyName);
			PropertyValue pv = new PropertyValue(propertyName, val);
			pv.setSource(parserContext.extractSource(ele));
			bd.getPropertyValues().addPropertyValue(pv);
		} finally {
			this.parseState.pop();
		}
	}

	private Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
		String elementName =
				(propertyName != null) ? "<property> element for property '" + propertyName + "'"
						: "<constructor-arg> element";

		// Should only have one child element: ref, value, list, etc.
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element
					&& !DomUtils.nodeNameEquals(node, BeanDefinitionParserDelegate.DESCRIPTION_ELEMENT)) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				} else {
					subElement = (Element) node;
				}
			}
		}

		boolean hasRefAttribute = ele.hasAttribute(BeanDefinitionParserDelegate.REF_ATTRIBUTE);
		boolean hasValueAttribute = ele.hasAttribute(BeanDefinitionParserDelegate.VALUE_ATTRIBUTE);
		if ((hasRefAttribute && hasValueAttribute) || ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			error(elementName
					+ " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}

		if (hasRefAttribute) {
			String refName = ele.getAttribute(BeanDefinitionParserDelegate.REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(parserContext.extractSource(ele));
			return ref;
		} else if (hasValueAttribute) {
			TypedStringValue valueHolder =
					new TypedStringValue(ele.getAttribute(BeanDefinitionParserDelegate.VALUE_ATTRIBUTE));
			valueHolder.setSource(parserContext.extractSource(ele));
			return valueHolder;
		} else if (subElement != null) {
			return parsePropertySubElement(subElement, bd, null);
		} else {
			// Neither child element nor "ref" or "value" attribute found.
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}

	public static Object parsePropertySubElement(ParserContext parserContext, Element ele, BeanDefinition bd) {
		return new BlueprintParser(parserContext).parsePropertySubElement(ele, bd, null);
	}

	public static Map<?, ?> parsePropertyMapElement(ParserContext parserContext, Element ele, BeanDefinition bd) {
		return new BlueprintParser(parserContext).parseMapElement(ele, bd);
	}

	public static Set<?> parsePropertySetElement(ParserContext parserContext, Element ele, BeanDefinition bd) {
		return new BlueprintParser(parserContext).parseSetElement(ele, bd);
	}

	/**
	 * Parse a value, ref or collection sub-element of a property or constructor-arg element. This method is called from
	 * several places to handle reusable elements such as idref, ref, null, value and so on.
	 * 
	 * In fact, this method is the main reason why the BeanDefinitionParserDelegate is not used in full since the
	 * element namespace becomes important as mixed rfc124/bean content can coexist.
	 * 
	 * @param ele subelement of property element; we don't know which yet
	 * @param defaultValueType the default type (class name) for any <code>&lt;value&gt;</code> tag that might be
	 * created
	 */
	private Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		// skip other namespace
		String namespaceUri = ele.getNamespaceURI();

		// check Spring own namespace
		if (parserContext.getDelegate().isDefaultNamespace(namespaceUri)) {
			return parserContext.getDelegate().parsePropertySubElement(ele, bd);
		}
		// let the delegate handle other ns
		else if (!NAMESPACE_URI.equals(namespaceUri)) {
			return parserContext.getDelegate().parseCustomElement(ele);
		}

		// 
		else {
			if (DomUtils.nodeNameEquals(ele, BEAN)) {
				BeanDefinitionHolder bdHolder = parseComponentDefinitionElement(ele, bd);
				if (bdHolder != null) {
					bdHolder = ParsingUtils.decorateBeanDefinitionIfRequired(ele, bdHolder, parserContext);
				}
				return bdHolder;
			}

			if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.REF_ELEMENT)) {
				return parseRefElement(ele);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.IDREF_ELEMENT)) {
				return parseIdRefElement(ele);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.VALUE_ELEMENT)) {
				return parseValueElement(ele, defaultValueType);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.NULL_ELEMENT)) {
				// It's a distinguished null value. Let's wrap it in a TypedStringValue
				// object in order to preserve the source location.
				TypedStringValue nullHolder = new TypedStringValue(null);
				nullHolder.setSource(parserContext.extractSource(ele));
				return nullHolder;
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.ARRAY_ELEMENT)) {
				return parseArrayElement(ele, bd);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.LIST_ELEMENT)) {
				return parseListElement(ele, bd);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.SET_ELEMENT)) {
				return parseSetElement(ele, bd);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.MAP_ELEMENT)) {
				return parseMapElement(ele, bd);
			} else if (DomUtils.nodeNameEquals(ele, BeanDefinitionParserDelegate.PROPS_ELEMENT)) {
				return parsePropsElement(ele);
			}

			// maybe it's a nested service/reference/ref-list/ref-set
			return parserContext.getDelegate().parseCustomElement(ele, bd);
		}
	}

	private Object parseRefElement(Element ele) {
		// A generic reference to any name of any component.
		String refName = ele.getAttribute(COMPONENT_ID_ATTR);
		if (!StringUtils.hasLength(refName)) {
			error("'" + COMPONENT_ID_ATTR + "' is required for <ref> element", ele);
			return null;
		}

		if (!StringUtils.hasText(refName)) {
			error("<ref> element contains empty target attribute", ele);
			return null;
		}
		RuntimeBeanReference ref = new InstanceEqualityRuntimeBeanReference(refName);
		ref.setSource(parserContext.extractSource(ele));
		return ref;
	}

	private Object parseIdRefElement(Element ele) {
		// A generic reference to any name of any bean/component.
		String refName = ele.getAttribute(COMPONENT_ID_ATTR);
		if (!StringUtils.hasLength(refName)) {
			error("'" + COMPONENT_ID_ATTR + "' is required for <idref> element", ele);
			return null;
		}
		if (!StringUtils.hasText(refName)) {
			error("<idref> element contains empty target attribute", ele);
			return null;
		}
		RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName);
		ref.setSource(parserContext.extractSource(ele));
		return ref;
	}

	/**
	 * Return a typed String value Object for the given value element.
	 * 
	 * @param ele element
	 * @param defaultTypeName type class name
	 * @return typed String value Object
	 */
	private Object parseValueElement(Element ele, String defaultTypeName) {
		// It's a literal value.
		String value = DomUtils.getTextValue(ele);
		String specifiedTypeName = ele.getAttribute(BeanDefinitionParserDelegate.TYPE_ATTRIBUTE);
		String typeName = specifiedTypeName;
		if (!StringUtils.hasText(typeName)) {
			typeName = defaultTypeName;
		}
		try {
			TypedStringValue typedValue = buildTypedStringValue(value, typeName);
			typedValue.setSource(extractSource(ele));
			typedValue.setSpecifiedTypeName(specifiedTypeName);
			return typedValue;
		} catch (ClassNotFoundException ex) {
			error("Type class [" + typeName + "] not found for <value> element", ele, ex);
			return value;
		}
	}

	/**
	 * Build a typed String value Object for the given raw value.
	 * 
	 * @see org.springframework.beans.factory.config.TypedStringValue
	 */
	private TypedStringValue buildTypedStringValue(String value, String targetTypeName) throws ClassNotFoundException {

		ClassLoader classLoader = parserContext.getReaderContext().getBeanClassLoader();
		TypedStringValue typedValue;
		if (!StringUtils.hasText(targetTypeName)) {
			typedValue = new TypedStringValue(value);
		} else if (classLoader != null) {
			Class<?> targetType = ClassUtils.forName(targetTypeName, classLoader);
			typedValue = new TypedStringValue(value, targetType);
		} else {
			typedValue = new TypedStringValue(value, targetTypeName);
		}
		return typedValue;
	}

	/**
	 * Parse an array element.
	 */
	public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
		String elementType = arrayEle.getAttribute(BeanDefinitionParserDelegate.VALUE_TYPE_ATTRIBUTE);
		NodeList nl = arrayEle.getChildNodes();
		ManagedArray target = new ManagedArray(elementType, nl.getLength());
		target.setSource(extractSource(arrayEle));
		target.setElementTypeName(elementType);
		target.setMergeEnabled(parseMergeAttribute(arrayEle));
		parseCollectionElements(nl, target, bd, elementType);
		return target;
	}

	/**
	 * Parse a list element.
	 */
	public List<?> parseListElement(Element collectionEle, BeanDefinition bd) {
		String defaultElementType = collectionEle.getAttribute(BeanDefinitionParserDelegate.VALUE_TYPE_ATTRIBUTE);
		NodeList nl = collectionEle.getChildNodes();
		ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
		target.setSource(extractSource(collectionEle));
		target.setElementTypeName(defaultElementType);
		target.setMergeEnabled(parseMergeAttribute(collectionEle));
		parseCollectionElements(nl, target, bd, defaultElementType);
		return target;
	}

	/**
	 * Parse a set element.
	 */
	public Set<?> parseSetElement(Element collectionEle, BeanDefinition bd) {
		String defaultElementType = collectionEle.getAttribute(BeanDefinitionParserDelegate.VALUE_TYPE_ATTRIBUTE);
		NodeList nl = collectionEle.getChildNodes();
		ManagedSet<Object> target = new ManagedSet<Object>(nl.getLength());
		target.setSource(extractSource(collectionEle));
		target.setElementTypeName(defaultElementType);
		target.setMergeEnabled(parseMergeAttribute(collectionEle));
		parseCollectionElements(nl, target, bd, defaultElementType);
		return target;
	}

	protected void parseCollectionElements(NodeList elementNodes, Collection<Object> target, BeanDefinition bd,
			String defaultElementType) {

		for (int i = 0; i < elementNodes.getLength(); i++) {
			Node node = elementNodes.item(i);
			if (node instanceof Element
					&& !DomUtils.nodeNameEquals(node, BeanDefinitionParserDelegate.DESCRIPTION_ELEMENT)) {
				target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
			}
		}
	}

	/**
	 * Parse a map element.
	 */
	public Map<?, ?> parseMapElement(Element mapEle, BeanDefinition bd) {
		String defaultKeyType = mapEle.getAttribute(BeanDefinitionParserDelegate.KEY_TYPE_ATTRIBUTE);
		String defaultValueType = mapEle.getAttribute(BeanDefinitionParserDelegate.VALUE_TYPE_ATTRIBUTE);

		List<Element> entryEles =
				DomUtils.getChildElementsByTagName(mapEle, BeanDefinitionParserDelegate.ENTRY_ELEMENT);
		ManagedMap<Object, Object> map = new ManagedMap<Object, Object>(entryEles.size());
		map.setSource(extractSource(mapEle));
		map.setKeyTypeName(defaultKeyType);
		map.setValueTypeName(defaultValueType);
		map.setMergeEnabled(parseMergeAttribute(mapEle));

		for (Element entryEle : entryEles) {
			// Should only have one value child element: ref, value, list, etc.
			// Optionally, there might be a key child element.
			NodeList entrySubNodes = entryEle.getChildNodes();
			Element keyEle = null;
			Element valueEle = null;
			for (int j = 0; j < entrySubNodes.getLength(); j++) {
				Node node = entrySubNodes.item(j);
				if (node instanceof Element) {
					Element candidateEle = (Element) node;
					if (DomUtils.nodeNameEquals(candidateEle, BeanDefinitionParserDelegate.KEY_ELEMENT)) {
						if (keyEle != null) {
							error("<entry> element is only allowed to contain one <key> sub-element", entryEle);
						} else {
							keyEle = candidateEle;
						}
					} else {
						// Child element is what we're looking for.
						if (valueEle != null) {
							error("<entry> element must not contain more than one value sub-element", entryEle);
						} else {
							valueEle = candidateEle;
						}
					}
				}
			}

			// Extract key from attribute or sub-element.
			Object key = null;
			boolean hasKeyAttribute = entryEle.hasAttribute(BeanDefinitionParserDelegate.KEY_ATTRIBUTE);
			boolean hasKeyRefAttribute = entryEle.hasAttribute(BeanDefinitionParserDelegate.KEY_REF_ATTRIBUTE);
			if ((hasKeyAttribute && hasKeyRefAttribute) || ((hasKeyAttribute || hasKeyRefAttribute)) && keyEle != null) {
				error("<entry> element is only allowed to contain either "
						+ "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
			}
			if (hasKeyAttribute) {
				key =
						buildTypedStringValueForMap(entryEle.getAttribute(BeanDefinitionParserDelegate.KEY_ATTRIBUTE),
								defaultKeyType, entryEle);
			} else if (hasKeyRefAttribute) {
				String refName = entryEle.getAttribute(BeanDefinitionParserDelegate.KEY_REF_ATTRIBUTE);
				if (!StringUtils.hasText(refName)) {
					error("<entry> element contains empty 'key-ref' attribute", entryEle);
				}
				RuntimeBeanReference ref = new RuntimeBeanReference(refName);
				ref.setSource(extractSource(entryEle));
				key = ref;
			} else if (keyEle != null) {
				key = parseKeyElement(keyEle, bd, defaultKeyType);
			} else {
				error("<entry> element must specify a key", entryEle);
			}

			// Extract value from attribute or sub-element.
			Object value = null;
			boolean hasValueAttribute = entryEle.hasAttribute(BeanDefinitionParserDelegate.VALUE_ATTRIBUTE);
			boolean hasValueRefAttribute = entryEle.hasAttribute(BeanDefinitionParserDelegate.VALUE_REF_ATTRIBUTE);
			if ((hasValueAttribute && hasValueRefAttribute) || ((hasValueAttribute || hasValueRefAttribute))
					&& valueEle != null) {
				error("<entry> element is only allowed to contain either "
						+ "'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
			}
			if (hasValueAttribute) {
				value =
						buildTypedStringValueForMap(
								entryEle.getAttribute(BeanDefinitionParserDelegate.VALUE_ATTRIBUTE), defaultValueType,
								entryEle);
			} else if (hasValueRefAttribute) {
				String refName = entryEle.getAttribute(BeanDefinitionParserDelegate.VALUE_REF_ATTRIBUTE);
				if (!StringUtils.hasText(refName)) {
					error("<entry> element contains empty 'value-ref' attribute", entryEle);
				}
				RuntimeBeanReference ref = new RuntimeBeanReference(refName);
				ref.setSource(extractSource(entryEle));
				value = ref;
			} else if (valueEle != null) {
				value = parsePropertySubElement(valueEle, bd, defaultValueType);
			} else {
				error("<entry> element must specify a value", entryEle);
			}

			// Add final key and value to the Map.
			map.put(key, value);
		}

		return map;
	}

	/**
	 * Parse a props element.
	 */
	public Properties parsePropsElement(Element propsEle) {
		ManagedProperties props = new OrderedManagedProperties();
		props.setSource(extractSource(propsEle));
		props.setMergeEnabled(parseMergeAttribute(propsEle));

		List propEles = DomUtils.getChildElementsByTagName(propsEle, BeanDefinitionParserDelegate.PROP_ELEMENT);
		for (Iterator it = propEles.iterator(); it.hasNext();) {
			Element propEle = (Element) it.next();
			String key = propEle.getAttribute(BeanDefinitionParserDelegate.KEY_ATTRIBUTE);
			// Trim the text value to avoid unwanted whitespace
			// caused by typical XML formatting.
			String value = DomUtils.getTextValue(propEle).trim();

			TypedStringValue keyHolder = new TypedStringValue(key);
			keyHolder.setSource(extractSource(propEle));
			TypedStringValue valueHolder = new TypedStringValue(value);
			valueHolder.setSource(extractSource(propEle));
			props.put(keyHolder, valueHolder);
		}

		return props;
	}

	private boolean parseMergeAttribute(Element element) {
		return parserContext.getDelegate().parseMergeAttribute(element);
	}

	/**
	 * Build a typed String value Object for the given raw value.
	 * 
	 * @see org.springframework.beans.factory.config.TypedStringValue
	 */
	private Object buildTypedStringValueForMap(String value, String defaultTypeName, Element entryEle) {
		try {
			TypedStringValue typedValue = buildTypedStringValue(value, defaultTypeName);
			typedValue.setSource(extractSource(entryEle));
			return typedValue;
		} catch (ClassNotFoundException ex) {
			error("Type class [" + defaultTypeName + "] not found for Map key/value type", entryEle, ex);
			return value;
		}
	}

	/**
	 * Parse a key sub-element of a map element.
	 */
	private Object parseKeyElement(Element keyEle, BeanDefinition bd, String defaultKeyTypeName) {
		NodeList nl = keyEle.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error("<key> element must not contain more than one value sub-element", keyEle);
				} else {
					subElement = (Element) node;
				}
			}
		}
		return parsePropertySubElement(subElement, bd, defaultKeyTypeName);
	}

	// util methods (used as shortcuts)
	private Object extractSource(Element ele) {
		return parserContext.extractSource(ele);
	}

	/**
	 * Reports an error with the given message for the given source element.
	 */
	private void error(String message, Node source) {
		parserContext.getReaderContext().error(message, source, parseState.snapshot());
	}

	/**
	 * Reports an error with the given message for the given source element.
	 */
	private void error(String message, Node source, Throwable cause) {
		parserContext.getReaderContext().error(message, source, parseState.snapshot(), cause);
	}

	private BlueprintDefaultsDefinition getDefaults(Element ele) {
		if (defaults == null) {
			defaults = new BlueprintDefaultsDefinition(ele.getOwnerDocument(), parserContext);
		}
		return defaults;
	}
}