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