/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.cxf.ws.transfer.dialect.fragment.language; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.namespace.NamespaceContext; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.apache.cxf.helpers.XPathUtils; import org.apache.cxf.ws.transfer.Representation; import org.apache.cxf.ws.transfer.dialect.fragment.ExpressionType; import org.apache.cxf.ws.transfer.dialect.fragment.faults.InvalidExpression; /** * Implementation of the QName language. */ public class FragmentDialectLanguageQName implements FragmentDialectLanguage { private static Pattern qNamePattern; public FragmentDialectLanguageQName() { if (qNamePattern == null) { String qName = getQNamePatternString(); qNamePattern = Pattern.compile("^" + qName); } } /** * Returns regex string, which describes QName format. * @return */ public static String getQNamePatternString() { // See http://www.w3.org/TR/REC-xml-names/#NT-PrefixedName // NCNameStartChar // see http://www.w3.org/TR/REC-xml-names/#NT-NCName // and http://www.w3.org/TR/REC-xml/#NT-NameStartChar String ncNameStartChar = "[A-Z]|_|[a-z]|[\\x{c0}-\\x{d6}]|[\\x{d8}-\\x{f6}]|[\\x{f8}-\\x{2ff}]|" + "[\\x{370}-\\x{37d}]|[\\x{37f}-\\x{1fff}]|[\\x{200c}-\\x{200d}]|" + "[\\x{2070}-\\x{218f}]|[\\x{2c00}-\\x{2fef}]|[\\x{3001}-\\x{d7ff}]|" + "[\\x{f900}-\\x{fdcf}]|[\\x{fdf0}-\\x{fffd}]|[\\x{10000}-\\x{effff}]"; // NCNameChar // see http://www.w3.org/TR/REC-xml/#NT-NameChar String ncNameChar = ncNameStartChar + "|-|\\.|[0-9]|\\x{b7}|[\\x{0300}-\\x{036f}]|[\\x{203f}-\\x{2040}]"; // NCName // see http://www.w3.org/TR/REC-xml/#NT-Name String ncName = String.format("(%s)(%s)*", ncNameStartChar, ncNameChar); // QName // see http://www.w3.org/TR/REC-xml-names/#NT-QName return String.format("((%s):)?(%s)", ncName, ncName); } @Override public Object getResourceFragment(final Representation representation, ExpressionType expression) { String expressionStr = getXPathFromQNameExpression(expression); // Evaluate XPath XPathUtils xu = new XPathUtils(new NamespaceContext() { @Override public String getNamespaceURI(String prefix) { if (prefix != null && !prefix.isEmpty()) { Element resource = (Element) representation.getAny(); return resource.getAttribute("xmlns:" + prefix); } else { return null; } } @Override public String getPrefix(String s) { throw new UnsupportedOperationException(); } @Override public Iterator<String> getPrefixes(String s) { throw new UnsupportedOperationException(); } }); Node resource = (Node) representation.getAny(); if (resource == null) { // Returns empty NodeList return new NodeList() { @Override public Node item(int i) { return null; } @Override public int getLength() { return 0; } }; } return xu.getValueList(expressionStr, resource); } /** * Converts expression in QName language to XPath expression. * @param expression Expression in QName language. * @return Expression in XPath language. */ private String getXPathFromQNameExpression(ExpressionType expression) { if (expression.getContent().size() == 1) { String expressionValue = (String) expression.getContent().get(0); Matcher m = qNamePattern.matcher(expressionValue); if (m.matches()) { return "/node()/" + expressionValue; } else { throw new InvalidExpression(); } } else { throw new InvalidExpression(); } } }