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 */
017package org.apache.camel.builder.xml;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.w3c.dom.Attr;
023import org.w3c.dom.Element;
024import org.w3c.dom.NamedNodeMap;
025import org.w3c.dom.Node;
026
027import org.apache.camel.model.language.VtdXmlExpression;
028import org.apache.camel.model.language.XPathExpression;
029import org.apache.camel.model.language.XQueryExpression;
030import org.apache.camel.spi.NamespaceAware;
031import org.apache.camel.util.ObjectHelper;
032
033/**
034 * A helper class for working with namespaces or creating namespace based expressions
035 *
036 * @version 
037 */
038public class Namespaces {
039    public static final String DEFAULT_NAMESPACE = "http://camel.apache.org/schema/spring";
040    public static final String IN_NAMESPACE = "http://camel.apache.org/xml/in/";
041    public static final String OUT_NAMESPACE = "http://camel.apache.org/xml/out/";
042    public static final String FUNCTION_NAMESPACE = "http://camel.apache.org/xml/function/";
043    public static final String SYSTEM_PROPERTIES_NAMESPACE = "http://camel.apache.org/xml/variables/system-properties";
044    public static final String ENVIRONMENT_VARIABLES = "http://camel.apache.org/xml/variables/environment-variables";
045    public static final String EXCHANGE_PROPERTY = "http://camel.apache.org/xml/variables/exchange-property";
046
047    private Map<String, String> namespaces = new HashMap<String, String>();
048
049    /**
050     * Creates a namespaces object from the given XML element
051     *
052     * @param element the XML element representing the XPath namespace context
053     */
054    public Namespaces(Element element) {
055        add(element);
056    }
057
058    /**
059     * Creates a namespace context with a single prefix and URI
060     */
061    public Namespaces(String prefix, String uri) {
062        add(prefix, uri);
063    }
064
065    /**
066     * Returns true if the given namespaceURI is empty or if it matches the
067     * given expected namespace
068     */
069    public static boolean isMatchingNamespaceOrEmptyNamespace(String namespaceURI, String expectedNamespace) {
070        return ObjectHelper.isEmpty(namespaceURI) || namespaceURI.equals(expectedNamespace);
071    }
072
073    public Namespaces add(String prefix, String uri) {
074        namespaces.put(prefix, uri);
075        return this;
076    }
077
078    public Namespaces add(Element element) {
079        // let's set the parent first in case we overload a prefix here
080        Node parentNode = element.getParentNode();
081        if (parentNode instanceof org.w3c.dom.Element) {
082            add((Element) parentNode);
083        }
084        NamedNodeMap attributes = element.getAttributes();
085        int size = attributes.getLength();
086        for (int i = 0; i < size; i++) {
087            Attr node = (Attr) attributes.item(i);
088            String name = node.getName();
089            if (name.startsWith("xmlns:")) {
090                String prefix = name.substring("xmlns:".length());
091                String uri = node.getValue();
092                add(prefix, uri);
093            }
094        }
095        return this;
096    }
097
098    /**
099     * Creates the XPath expression using the VTD-XML library using the current namespace context
100     */
101    public VtdXmlExpression vtdxml(String expression) {
102        VtdXmlExpression answer = new VtdXmlExpression(expression);
103        configure(answer);
104        return answer;
105    }
106
107    /**
108     * Creates the XPath expression using the current namespace context
109     */
110    public XPathExpression xpath(String expression) {
111        XPathExpression answer = new XPathExpression(expression);
112        configure(answer);
113        return answer;
114    }
115
116    /**
117     * Creates the XPath expression using the current namespace context
118     */
119    public XPathExpression xpath(String expression, Class<?> resultType) {
120        XPathExpression answer = xpath(expression);
121        answer.setResultType(resultType);
122        return answer;
123    }
124
125    /**
126     * Creates the XQuery expression using the current namespace context
127     */
128    public XQueryExpression xquery(String expression) {
129        XQueryExpression answer = new XQueryExpression(expression);
130        configure(answer);
131        return answer;
132    }
133
134    /**
135     * Creates the XQuery expression using the current namespace context
136     * and the given expected return type
137     */
138    public XQueryExpression xquery(String expression, Class<?> resultType) {
139        XQueryExpression answer = new XQueryExpression(expression);
140        answer.setResultType(resultType);
141        configure(answer);
142        return answer;
143    }
144
145    public Map<String, String> getNamespaces() {
146        return namespaces;
147    }
148
149    /**
150     * Configures the namespace aware object
151     */
152    public void configure(NamespaceAware namespaceAware) {
153        namespaceAware.setNamespaces(getNamespaces());
154    }
155}