protected Object parseCustomMapElement()

in xbean-spring/src/main/java/org/apache/xbean/spring/context/v2c/XBeanNamespaceHandler.java [617:698]


    protected Object parseCustomMapElement(MappingMetaData metadata, Element element, String name) {
        Map map = new ManagedMap();

        Element parent = (Element) element.getParentNode();
        String entryName = metadata.getMapEntryName(getLocalName(parent), name);
        String keyName = metadata.getMapKeyName(getLocalName(parent), name);
        String dups = metadata.getMapDupsMode(getLocalName(parent), name);
        boolean flat = metadata.isFlatMap(getLocalName(parent), name);
        String defaultKey = metadata.getMapDefaultKey(getLocalName(parent), name);

        if (entryName == null) entryName = "property";
        if (keyName == null) keyName = "key";
        if (dups == null) dups = "replace";

        // TODO : support further customizations
        //String valueName = "value";
        //boolean keyIsAttr = true;
        //boolean valueIsAttr = false;
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element childElement = (Element) node;

                String localName = childElement.getLocalName();
                String uri = childElement.getNamespaceURI();
                if (localName == null || localName.equals("xmlns") || localName.startsWith("xmlns:")) {
                    continue;
                }

                // we could use namespaced attributes to differentiate real spring
                // attributes from namespace-specific attributes
                if (!flat && !isEmpty(uri) && localName.equals(entryName)) {
                    String key = childElement.getAttribute(keyName);
                    if (key == null || key.length() == 0) {
                        key = defaultKey;
                    }
                    if (key == null) {
                        throw new RuntimeException("No key defined for map " + entryName);
                    }

                    Object keyValue = getValue(key, null);

                    Element valueElement = getFirstChildElement(childElement);
                    Object value;
                    if (valueElement != null) {
                        String valueElUri = valueElement.getNamespaceURI();
                        String valueElLocalName = valueElement.getLocalName();
                        if (valueElUri == null || 
                            valueElUri.equals(SPRING_SCHEMA) || 
                            valueElUri.equals(SPRING_SCHEMA_COMPAT) ||
                            valueElUri.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
                            if (BeanDefinitionParserDelegate.BEAN_ELEMENT.equals(valueElLocalName)) {
                                value = parserContext.getDelegate().parseBeanDefinitionElement(valueElement, null);
                            } else {
                                value = parserContext.getDelegate().parsePropertySubElement(valueElement, null);
                            }
                        } else {
                            value = parserContext.getDelegate().parseCustomElement(valueElement);
                        }
                    } else {
                        value = getElementText(childElement);
                    }

                    addValueToMap(map, keyValue, value, dups);
                } else if (flat && !isEmpty(uri)) {
                    String key = childElement.getAttribute(keyName);
                    if (key == null || key.length() == 0) {
                        key = defaultKey;
                    }
                    if (key == null) {
                        throw new RuntimeException("No key defined for map entry " + entryName);
                    }
                    Object keyValue = getValue(key, null);
                    childElement.removeAttribute(keyName);
                    BeanDefinitionHolder bdh = parseBeanFromExtensionElement(childElement);
                    addValueToMap(map, keyValue, bdh, dups);
                }
            }
        }
        return map;
    }