001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.xbean.blueprint.context.impl;
018    
019    import java.beans.PropertyDescriptor;
020    import java.util.List;
021    
022    import javax.xml.namespace.QName;
023    import org.apache.aries.blueprint.ParserContext;
024    import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
025    import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
026    import org.apache.aries.blueprint.mutable.MutableValueMetadata;
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.osgi.service.blueprint.reflect.BeanProperty;
030    import org.osgi.service.blueprint.reflect.CollectionMetadata;
031    import org.osgi.service.blueprint.reflect.Metadata;
032    import org.osgi.service.blueprint.reflect.ValueMetadata;
033    import org.w3c.dom.Element;
034    import org.w3c.dom.Node;
035    
036    /**
037     * 
038     * @version $Revision: 1.1 $
039     */
040    public class QNameHelper {
041        private static final Log log = LogFactory.getLog(QNameHelper.class);
042        
043        public static Metadata createQNameMetadata(Element element, String qualifiedName, ParserContext parserContext) {
044            MutableBeanMetadata beanMetadata = parserContext.createMetadata(MutableBeanMetadata.class);
045            beanMetadata.setClassName(QName.class.getName());
046            int index = qualifiedName.indexOf(':');
047            if (index >= 0) {
048                String prefix = qualifiedName.substring(0, index);
049                String localName = qualifiedName.substring(index + 1);
050                String uri = recursiveGetAttributeValue(element, "xmlns:" + prefix);
051                beanMetadata.addArgument(valueMetadata(uri, parserContext), String.class.getName(), 0);
052                beanMetadata.addArgument(valueMetadata(localName, parserContext), String.class.getName(), 1);
053                beanMetadata.addArgument(valueMetadata(prefix, parserContext), String.class.getName(), 2);
054            }
055            else {
056                String uri = recursiveGetAttributeValue(element, "xmlns");
057                if (uri != null) {
058                    beanMetadata.addArgument(valueMetadata(uri, parserContext), String.class.getName(), 0);
059                    beanMetadata.addArgument(valueMetadata(qualifiedName, parserContext), String.class.getName(), 1);
060                } else {
061                    beanMetadata.addArgument(valueMetadata(qualifiedName, parserContext), String.class.getName(), 0);
062                }
063            }
064            return beanMetadata;
065        }
066    
067        private static Metadata valueMetadata(String stringValue, ParserContext parserContext) {
068            MutableValueMetadata value = parserContext.createMetadata(MutableValueMetadata.class);
069            value.setStringValue(stringValue);
070            return value;
071        }
072    
073        /**
074         * Recursive method to find a given attribute value in an element or its parents (towards root of dom tree)
075         * @param element element to start searching for attribute in
076         * @param attributeName name of desired attribute
077         * @return value of found attribute
078         */
079        public static String recursiveGetAttributeValue(Element element, String attributeName) {
080            String answer = null;
081            try {
082                answer = element.getAttribute(attributeName);
083            }
084            catch (Exception e) {
085                if (log.isTraceEnabled()) {
086                    log.trace("Caught exception looking up attribute: " + attributeName + " on element: " + element + ". Cause: " + e, e);
087                }
088            }
089            if (answer == null || answer.length() == 0) {
090                Node parentNode = element.getParentNode();
091                if (parentNode instanceof Element) {
092                    return recursiveGetAttributeValue((Element) parentNode, attributeName);
093                }
094            }
095            return answer;
096        }
097        
098        public static void coerceNamespaceAwarePropertyValues(MutableBeanMetadata bd, Element element, PropertyDescriptor descriptor, ParserContext parserContext) {
099            // When the property is an indexed property, the getPropertyType can return null.
100            if (descriptor.getPropertyType() == null) {
101                return;
102            }
103            if (descriptor.getPropertyType().isAssignableFrom(QName.class)) {
104                String name = descriptor.getName();
105                BeanProperty propertyValue = XBeanNamespaceHandler.propertyByName(name, bd);
106                if (propertyValue != null) {
107                    Metadata value = propertyValue.getValue();
108                    if (value instanceof ValueMetadata) {
109                        bd.removeProperty(propertyValue);
110                        Metadata valueMetadata = createQNameMetadata(element, ((ValueMetadata)value).getStringValue(), parserContext);
111                        bd.addProperty(name, valueMetadata);
112                    }
113                    //else??
114                }
115            } else if (descriptor.getPropertyType().isAssignableFrom(QName[].class)) {
116                String name = descriptor.getName();
117                BeanProperty propertyValue = XBeanNamespaceHandler.propertyByName(name, bd);
118                if (propertyValue != null) {
119                    Object value = propertyValue.getValue();
120                    if (value instanceof CollectionMetadata) {
121                        List<Metadata> values = ((CollectionMetadata) value).getValues();
122                        MutableCollectionMetadata newValue = parserContext.createMetadata(MutableCollectionMetadata.class);
123    
124                        for (Metadata v : values) {
125                            if (v instanceof ValueMetadata) {
126                                newValue.addValue(createQNameMetadata(element, ((ValueMetadata)v).getStringValue(), parserContext));
127                            } else {
128                                newValue.addValue(v);
129                            }
130                        }
131                        bd.removeProperty(propertyValue);
132                        bd.addProperty(name, newValue);
133                    }
134                }
135            }
136        }
137    
138    }