[teiid-commits] teiid SVN: r2107 - in trunk: connector-api/src/main/java/org/teiid/connector/api and 13 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Fri May 7 17:35:46 EDT 2010
Author: shawkins
Date: 2010-05-07 17:35:44 -0400 (Fri, 07 May 2010)
New Revision: 2107
Removed:
trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java
trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java
Modified:
trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java
trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java
trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java
trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java
trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java
Log:
TEIID-1087: added support xpathquery that returns a full result (as opposed to xpathvalue) and allowed both functions to be namespace aware.
Modified: trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java
===================================================================
--- trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/common-core/src/main/java/com/metamatrix/common/types/XMLType.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -46,7 +46,7 @@
public final class XMLType extends Streamable<SQLXML> implements SQLXML {
public enum Type {
- UNKNOWN, DOCUMENT, FRAGMENT, SIBLINGS, COMMENT, PI
+ UNKNOWN, DOCUMENT, FRAGMENT, SIBLINGS, COMMENT, PI, TEXT
}
private static final long serialVersionUID = -7922647237095135723L;
Modified: trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
===================================================================
--- trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -136,6 +136,7 @@
//xml
public static final String XPATHVALUE = "xpathvalue"; //$NON-NLS-1$
+ public static final String XPATHQUERY = "xpathquery"; //$NON-NLS-1$
public static final String XSLTRANSFORM = "xsltransform"; //$NON-NLS-1$
public static final String XMLELEMENT = "xmlelement"; //$NON-NLS-1$
public static final String XMLCONCAT = "xmlconcat"; //$NON-NLS-1$
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2010-05-07 21:35:44 UTC (rev 2107)
@@ -1932,25 +1932,38 @@
<tbody>
<row>
<entry>
- <para><code>XPATHVALUE(doc, xpath)</code></para>
+ <para><code>XPATHVALUE(doc, xpath [, namepaces])</code></para>
</entry>
<entry>
- <para>Takes a document and an XPATH query and returns a
- string value for the result. An attempt is made to provide a
+ <para>Applies the XPATH query to the document and returns a
+ string value for the first matching result. An attempt is made to provide a
meaningful result for non-text nodes.</para>
+ <para>The optional namespaces string is used to provide default and prefix to uri mappings for the given xpath. The format is the same as namespace declarations in an xml element: xmlns:foo="uri"</para>
</entry>
<entry>
- <para>Doc in {string, xml} and xpath in {string}. Return value is a string.
+ <para>Doc in {string, xml} and xpath, namespaces in {string}. Return value is a string.
</para>
</entry>
</row>
<row>
<entry>
+ <para><code>XPATHQUERY(doc, xpath [, namepaces])</code></para>
+ </entry>
+ <entry>
+ <para>Takes a document and an XPATH query and returns a SQL/XML of the result.</para>
+ <para>The optional namespaces string is used to provide default and prefix to uri mappings for the given xpath. The format is the same as namespace declarations in an xml element: xmlns:foo="uri"</para>
+ </entry>
+ <entry>
+ <para>Doc in {string, xml} and xpath, namespaces in {string}. Return value is a string.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
<para><code>XSLTRANSFORM(doc, xsl)</code></para>
</entry>
<entry>
- <para>Takes a document and an xsl stylesheet and returns a
- clob of the result. If either argument is null, the result is null.</para>
+ <para>Applies an xsl stylesheet to the given document. If either argument is null, the result is null.</para>
</entry>
<entry>
<para>Doc, xsl in {string, xml}. Return value is a clob.
Deleted: trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/internal/core/xml/XPathHelper.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -1,117 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.internal.core.xml;
-
-import java.io.IOException;
-import java.io.Reader;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import net.sf.saxon.om.Item;
-import net.sf.saxon.sxpath.XPathEvaluator;
-import net.sf.saxon.sxpath.XPathExpression;
-import net.sf.saxon.trans.XPathException;
-
-import com.metamatrix.core.util.ArgCheck;
-
-
-/**
- * A collection of methods to help with evaluating an XPath against a document. These
- * utilities currently use Jaxen for XPath implementation.
- * @since 4.2
- */
-public class XPathHelper {
-
- /**
- * Get the first XPath match when evaluating an XPath on a document. If nothing is
- * matched, null is returned.
- * @param documentReader A reader for the XML document. The reader will always be closed by this method.
- * @param xpath An xpath expression, for example: a/b/c/getText()
- * @return String representation of the first matching item or null if none
- * @throws IllegalArgumentException If <code>documentReader</code> or <code>xpath</code> is null
- * @throws XPathException If an error occurs evaluating the XPath
- * @throws IOException If an error occurs closing the reader
- * @since 4.2
- */
- public static String getSingleMatchAsString(Reader documentReader, String xpath) throws XPathException, IOException {
- Object o = getSingleMatch(documentReader, xpath);
-
- if(o == null) {
- return null;
- }
-
- // Return string value of node type
- if(o instanceof Item) {
- return ((Item)o).getStringValue();
- }
-
- // Return string representation of non-node value
- return o.toString();
- }
-
- /**
- * Get the first XPath match when evaluating an XPath on a document. If nothing is
- * matched, null is returned.
- * @param documentReader A reader for the XML document. The reader will always be closed by this method.
- * @param xpath An xpath expression, for example: a/b/c/getText()
- * @return String representation of the first matching item or null if none
- * @throws IllegalArgumentException If <code>documentReader</code> or <code>xpath</code> is null
- * @throws XPathException If an error occurs evaluating the XPath
- * @throws IOException If an error occurs closing the reader
- * @since 4.2
- */
- public static Object getSingleMatch(Reader documentReader, String xpath) throws XPathException, IOException {
- ArgCheck.isNotNull(documentReader);
- ArgCheck.isNotNull(xpath);
-
- try {
- Source s = new StreamSource(documentReader);
- XPathEvaluator eval = new XPathEvaluator();
-
- // Wrap the string() function to force a string return
- XPathExpression expr = eval.createExpression(xpath);
- return expr.evaluateSingle(s);
-
- } finally {
- // Always close the reader
- documentReader.close();
- }
- }
-
- /**
- * Validate whether the XPath is a valid XPath. If not valid, an XPathException will be thrown.
- * @param xpath An xpath expression, for example: a/b/c/getText()
- * @throws XPathException If an error occurs parsing the xpath
- * @since 4.2
- */
- public static void validateXpath(String xpath) throws XPathException {
- if(xpath == null) {
- return;
- }
-
- XPathEvaluator eval = new XPathEvaluator();
- eval.createExpression(xpath); // throws XPathException
- }
-
-}
Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -166,7 +166,8 @@
addParseNumberFunctions();
// xml functions
- addXpathFunction();
+ addXpathQueryFunction();
+ addXpathValueFunction();
addXslTransformFunction();
addXmlElement();
addXmlConcat();
@@ -881,25 +882,64 @@
);
}
- /**
- *
- * @since 4.2
- */
- private void addXpathFunction() {
- functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
+ private void addXpathValueFunction() {
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
- functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
- new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("namespace", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHVALUE, QueryPlugin.Util.getString("SystemSource.xpathvalue_description"), XML, XML_FUNCTION_CLASS, "xpathValue", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("namespace", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpathvalue_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
}
+ private void addXpathQueryFunction() {
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("namespaces", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ functions.add(new FunctionMethod(SourceSystemFunctions.XPATHQUERY, QueryPlugin.Util.getString("SystemSource.xpath_description"), XML, XML_FUNCTION_CLASS, "xpathQuery", //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter[] {
+ new FunctionParameter("document", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("xpath", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param2")), //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("namespaces", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xpath_param3"))}, //$NON-NLS-1$ //$NON-NLS-2$
+ new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xpath_result")) ) ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
private void addXslTransformFunction() {
functions.add(new FunctionMethod(SourceSystemFunctions.XSLTRANSFORM, QueryPlugin.Util.getString("SystemSource.xsltransform_description"), XML, XML_FUNCTION_CLASS, "xslTransform", //$NON-NLS-1$ //$NON-NLS-2$
new FunctionParameter[] {
@@ -1008,7 +1048,7 @@
* Get all function signatures for this metadata source.
* @return Unordered collection of {@link FunctionMethod}s
*/
- public Collection getFunctionMethods() {
+ public Collection<FunctionMethod> getFunctionMethods() {
return this.functions;
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -27,11 +27,13 @@
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
+import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Timestamp;
import java.util.Calendar;
+import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.EventFilter;
import javax.xml.stream.FactoryConfigurationError;
@@ -41,15 +43,24 @@
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
-import net.sf.saxon.trans.XPathException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.MetaMatrixProcessingException;
@@ -62,7 +73,6 @@
import com.metamatrix.common.types.XMLTranslator;
import com.metamatrix.common.types.XMLType;
import com.metamatrix.common.types.XMLType.Type;
-import com.metamatrix.internal.core.xml.XPathHelper;
import com.metamatrix.query.QueryPlugin;
import com.metamatrix.query.function.FunctionMethods;
import com.metamatrix.query.processor.xml.XMLUtil;
@@ -99,31 +109,7 @@
}
YEAR_ZERO = cal.getTimeInMillis();
}
-
- public static Object xpathValue(Object document, Object xpathStr) throws FunctionExecutionException {
- Reader stream = null;
-
- if (document instanceof SQLXML) {
- try {
- stream = ((SQLXML)document).getCharacterStream();
- } catch (SQLException e) {
- throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.xpathvalue_takes_only_string", document.getClass().getName())); //$NON-NLS-1$
- }
- } else if(document instanceof String) {
- stream = new StringReader((String)document);
- } else {
- throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.xpathvalue_takes_only_string", document.getClass().getName())); //$NON-NLS-1$
- }
-
- try {
- return XPathHelper.getSingleMatchAsString(stream, (String) xpathStr);
- } catch(IOException e) {
- throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.wrap_exception", xpathStr, e.getMessage())); //$NON-NLS-1$
- } catch(XPathException e) {
- throw new FunctionExecutionException(QueryPlugin.Util.getString("XMLSystemFunctions.wrap_exception", xpathStr, e.getMessage())); //$NON-NLS-1$
- }
- }
-
+
public static ClobType xslTransform(CommandContext context, String xmlResults, String styleSheet) throws Exception {
return xslTransform(context, DataTypeManager.transformValue(xmlResults, DataTypeManager.DefaultDataClasses.XML), DataTypeManager.transformValue(styleSheet, DataTypeManager.DefaultDataClasses.XML));
}
@@ -313,52 +299,62 @@
if (object == null) {
return;
}
- if (object instanceof XMLType) {
- XMLType xml = (XMLType)object;
- Reader r = null;
- try {
+ Reader r = null;
+ try {
+ if (object instanceof XMLType) {
+ XMLType xml = (XMLType)object;
r = xml.getCharacterStream();
- if (!(r instanceof BufferedReader)) {
- r = new BufferedReader(r);
- }
- switch(xml.getType()) {
- case FRAGMENT:
- case SIBLINGS:
- case PI:
- case COMMENT: //write the value directly to the writer
- eventWriter.flush();
- int chr = -1;
- while ((chr = r.read()) != -1) {
- writer.write(chr);
- }
- break;
- case UNKNOWN: //assume a document
- case DOCUMENT: //filter the doc declaration
- XMLInputFactory inputFactory = XMLInputFactory.newInstance();
- XMLEventReader eventReader = inputFactory.createXMLEventReader(r);
- eventReader = inputFactory.createFilteredReader(eventReader, new EventFilter() {
- @Override
- public boolean accept(XMLEvent event) {
- return !event.isStartDocument() && !event.isEndDocument();
- }
- });
- eventWriter.add(eventReader);
- break;
- }
- } catch (SQLException e) {
- throw new IOException(e);
- } finally {
- if (r != null) {
- r.close();
- }
+ Type type = xml.getType();
+ convertReader(writer, eventWriter, r, type);
+ } else if (object instanceof Clob) {
+ Clob clob = (Clob)object;
+ r = clob.getCharacterStream();
+ convertReader(writer, eventWriter, r, Type.TEXT);
+ } else {
+ String val = getStringValue(object);
+ eventWriter.add(eventFactory.createCharacters(val));
}
- } else {
- String val = getStringValue(object);
- eventWriter.add(eventFactory.createCharacters(val));
+ } catch (SQLException e) {
+ throw new IOException(e);
+ } finally {
+ if (r != null) {
+ r.close();
+ }
}
//TODO: blob - with base64 encoding
- //TODO: full clob?
}
+
+ private static void convertReader(Writer writer,
+ XMLEventWriter eventWriter, Reader r, Type type)
+ throws XMLStreamException, IOException, FactoryConfigurationError {
+ if (!(r instanceof BufferedReader)) {
+ r = new BufferedReader(r);
+ }
+ switch(type) {
+ case FRAGMENT:
+ case SIBLINGS:
+ case PI:
+ case COMMENT: //write the value directly to the writer
+ eventWriter.flush();
+ int chr = -1;
+ while ((chr = r.read()) != -1) {
+ writer.write(chr);
+ }
+ break;
+ case UNKNOWN: //assume a document
+ case DOCUMENT: //filter the doc declaration
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ XMLEventReader eventReader = inputFactory.createXMLEventReader(r);
+ eventReader = inputFactory.createFilteredReader(eventReader, new EventFilter() {
+ @Override
+ public boolean accept(XMLEvent event) {
+ return !event.isStartDocument() && !event.isEndDocument();
+ }
+ });
+ eventWriter.add(eventReader);
+ break;
+ }
+ }
public static XMLType xmlComment(String comment) {
return new XMLType(new SQLXMLImpl("<!--" + comment + "-->")); //$NON-NLS-1$ //$NON-NLS-2$
@@ -401,5 +397,131 @@
return resultBuffer.toString();
}
+
+ public static String xpathValue(XMLType document, String xpathStr, String namespaces) throws IOException, XPathExpressionException, SQLException, FunctionExecutionException {
+ Reader stream = document.getCharacterStream();
+ return xpathValue(stream, xpathStr, namespaces);
+ }
+ public static String xpathValue(String document, String xpathStr, String namespaces) throws IOException, XPathExpressionException, FunctionExecutionException {
+ return xpathValue(new StringReader(document), xpathStr, namespaces);
+ }
+
+ public static String xpathValue(String document, String xpathStr) throws IOException, XPathExpressionException, FunctionExecutionException {
+ return xpathValue(document, xpathStr, null);
+ }
+
+ public static String xpathValue(XMLType document, String xpathStr) throws IOException, SQLException, XPathExpressionException, FunctionExecutionException {
+ return xpathValue(document, xpathStr, null);
+ }
+
+ public static XMLType xpathQuery(CommandContext context, String document, String xpathStr) throws IOException, MetaMatrixComponentException, MetaMatrixProcessingException, XPathExpressionException {
+ return xpathQuery(context, document, xpathStr, null);
+ }
+
+ public static XMLType xpathQuery(CommandContext context, XMLType document, String xpathStr) throws IOException, SQLException, XPathExpressionException, MetaMatrixComponentException, MetaMatrixProcessingException {
+ return xpathQuery(context, document, xpathStr, null);
+ }
+
+ public static XMLType xpathQuery(CommandContext context, String document, String xpathStr, String namespaces) throws IOException, MetaMatrixComponentException, MetaMatrixProcessingException, XPathExpressionException {
+ Reader stream = new StringReader(document);
+ return xpathQuery(context, xpathStr, stream, namespaces);
+ }
+
+ public static XMLType xpathQuery(CommandContext context, XMLType document, String xpathStr, String namespaces) throws IOException, SQLException, XPathExpressionException, MetaMatrixComponentException, MetaMatrixProcessingException {
+ Reader stream = ((SQLXML)document).getCharacterStream();
+ return xpathQuery(context, xpathStr, stream, namespaces);
+ }
+
+ private static XMLType xpathQuery(CommandContext context, String xpathStr,
+ Reader stream, String namespaces) throws XPathExpressionException,
+ MetaMatrixComponentException, MetaMatrixProcessingException,
+ IOException {
+ try {
+ XPathFactory xpathFactory = XPathFactory.newInstance();
+ XPath xp = xpathFactory.newXPath();
+ NamespaceContext nc = getNamespaces(namespaces);
+ if (nc != null) {
+ xp.setNamespaceContext(nc);
+ }
+ final NodeList nodes = (NodeList)xp.evaluate(xpathStr, new InputSource(stream), XPathConstants.NODESET);
+ if (nodes.getLength() == 0) {
+ return null;
+ }
+ Type type = nodes.getLength() > 1 ? Type.SIBLINGS : Type.FRAGMENT;
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ if (node.getNodeType() == Node.TEXT_NODE) {
+ type = Type.TEXT;
+ }
+ }
+ SQLXML sqlXml = XMLUtil.saveToBufferManager(context.getBufferManager(), new XMLTranslator() {
+
+ @Override
+ public void translate(Writer writer) throws TransformerException {
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ transformer.transform(new DOMSource(node), new StreamResult(writer));
+ }
+ }
+ }, Streamable.STREAMING_BATCH_SIZE_IN_BYTES);
+ XMLType result = new XMLType(sqlXml);
+ result.setType(type);
+ return result;
+ } finally {
+ stream.close();
+ }
+ }
+
+ public static String xpathValue(Reader documentReader, String xpath, String namespaces) throws IOException, XPathExpressionException, FunctionExecutionException {
+ try {
+ XPathFactory xpathFactory = XPathFactory.newInstance();
+ XPath xp = xpathFactory.newXPath();
+ NamespaceContext nc = getNamespaces(namespaces);
+ if (nc != null) {
+ xp.setNamespaceContext(nc);
+ }
+ Node node = (Node)xp.evaluate(xpath, new InputSource(documentReader), XPathConstants.NODE);
+ if (node == null) {
+ return null;
+ }
+ return node.getTextContent();
+ } finally {
+ // Always close the reader
+ documentReader.close();
+ }
+ }
+
+ public static NamespaceContext getNamespaces(String namespaces) throws FunctionExecutionException {
+ if (namespaces == null) {
+ return null;
+ }
+ XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+ try {
+ XMLStreamReader eventReader = inputFactory.createXMLStreamReader(new StringReader("<x " + namespaces + " />")); //$NON-NLS-1$ //$NON-NLS-2$
+ eventReader.next();
+ return eventReader.getNamespaceContext();
+ } catch (XMLStreamException e) {
+ throw new FunctionExecutionException(e, QueryPlugin.Util.getString("XMLSystemFunctions.invalid_namespaces", namespaces)); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Validate whether the XPath is a valid XPath. If not valid, an XPathExpressionException will be thrown.
+ * @param xpath An xpath expression, for example: a/b/c/getText()
+ * @throws XPathExpressionException
+ */
+ public static void validateXpath(String xpath) throws XPathExpressionException {
+ if(xpath == null) {
+ return;
+ }
+
+ XPathFactory factory = XPathFactory.newInstance();
+ XPath xp = factory.newXPath();
+ xp.compile(xpath);
+ }
+
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverVisitor.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -31,17 +31,12 @@
import java.util.List;
import java.util.Map;
-import org.teiid.connector.api.SourceSystemFunctions;
-
-import net.sf.saxon.trans.XPathException;
-
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.QueryMetadataException;
import com.metamatrix.api.exception.query.QueryResolverException;
import com.metamatrix.api.exception.query.UnresolvedSymbolDescription;
import com.metamatrix.common.types.DataTypeManager;
import com.metamatrix.common.types.DataTypeManager.DefaultDataClasses;
-import com.metamatrix.internal.core.xml.XPathHelper;
import com.metamatrix.query.QueryPlugin;
import com.metamatrix.query.function.FunctionDescriptor;
import com.metamatrix.query.function.FunctionForm;
@@ -442,25 +437,8 @@
} else if(fd.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
ResolverUtil.ResolvedLookup lookup = ResolverUtil.resolveLookup(function, metadata);
fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType());
- } else if(fd.getName().equalsIgnoreCase(SourceSystemFunctions.XPATHVALUE)) {
- // Validate the xpath value is valid
- if(args[1] != null && args[1] instanceof Constant) {
- Constant xpathConst = (Constant) args[1];
- if(xpathConst.getType().equals(DataTypeManager.DefaultDataClasses.STRING)) {
- String value = (String) xpathConst.getValue();
- if(value == null) {
- throw new QueryResolverException(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", QueryPlugin.Util.getString("ResolveFunctionsVisitor.xpath_cant_be_null"))); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ }
- try {
- XPathHelper.validateXpath(value);
- } catch(XPathException e) {
- throw new QueryResolverException(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", e.getMessage())); //$NON-NLS-1$
- }
- }
- }
- }
-
// Resolve the function
function.setFunctionDescriptor(fd);
function.setType(fd.getReturnType());
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -1243,7 +1243,7 @@
}
parts.add(")"); //$NON-NLS-1$
- } else if (name.equalsIgnoreCase(SourceSystemFunctions.XMLELEMENT)){
+ } else if (name.equalsIgnoreCase(SourceSystemFunctions.XMLELEMENT) || name.equalsIgnoreCase(SourceSystemFunctions.XMLPI)){
parts.add(name);
parts.add("(NAME "); //$NON-NLS-1$
outputDisplayName((String)((Constant)args[0]).getValue());
Modified: trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -31,15 +31,21 @@
import java.util.Map;
import java.util.Set;
+import javax.xml.xpath.XPathExpressionException;
+
+import org.teiid.connector.api.SourceSystemFunctions;
+
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.MetaMatrixProcessingException;
import com.metamatrix.api.exception.query.ExpressionEvaluationException;
+import com.metamatrix.api.exception.query.FunctionExecutionException;
import com.metamatrix.api.exception.query.QueryMetadataException;
import com.metamatrix.api.exception.query.QueryValidatorException;
import com.metamatrix.common.types.DataTypeManager;
import com.metamatrix.query.QueryPlugin;
import com.metamatrix.query.eval.Evaluator;
import com.metamatrix.query.function.FunctionLibrary;
+import com.metamatrix.query.function.source.XMLSystemFunctions;
import com.metamatrix.query.metadata.SupportConstants;
import com.metamatrix.query.resolver.util.ResolverUtil;
import com.metamatrix.query.sql.LanguageObject;
@@ -319,7 +325,25 @@
// can't use this pseudo-function in non-XML queries
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.The_rowlimit_function_cannot_be_used_in_a_non-XML_command"), obj); //$NON-NLS-1$
}
- }
+ } else if(obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.XPATHVALUE) || obj.getFunctionDescriptor().getName().equalsIgnoreCase(SourceSystemFunctions.XPATHQUERY)) {
+ // Validate the xpath value is valid
+ if(obj.getArgs()[1] instanceof Constant) {
+ Constant xpathConst = (Constant) obj.getArgs()[1];
+ try {
+ XMLSystemFunctions.validateXpath((String)xpathConst.getValue());
+ } catch(XPathExpressionException e) {
+ handleValidationError(QueryPlugin.Util.getString("QueryResolver.invalid_xpath", e.getMessage()), obj); //$NON-NLS-1$
+ }
+ }
+ if (obj.getArgs().length > 2 && obj.getArgs()[2] instanceof Constant) {
+ Constant xpathConst = (Constant) obj.getArgs()[2];
+ try {
+ XMLSystemFunctions.getNamespaces((String)xpathConst.getValue());
+ } catch(FunctionExecutionException e) {
+ handleValidationError(e.getMessage(), obj);
+ }
+ }
+ }
}
// ############### Visitor methods for stored procedure lang objects ##################
Modified: trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties 2010-05-07 21:35:44 UTC (rev 2107)
@@ -764,9 +764,12 @@
SystemSource.Bitfunc2_arg1=First integer
SystemSource.Bitfunc2_arg2=Second integer
SystemSource.Convert_desc=Convert from {0} to target type
-SystemSource.xpath_description=Retrieve the first match content for an XPath statement
+SystemSource.xpathvalue_description=Retrieve the first match content for an XPath statement
+SystemSource.xpath_description=Evaluate the XPath expression against a document
SystemSource.xpath_param1=Source document
SystemSource.xpath_param2=XPath expression
+SystemSource.xpath_param2=Namespaces
+SystemSource.xpathvalue_result=Single result
SystemSource.xpath_result=XPath result
SystemSource.xsltransform_description=Transform the document with the given stylesheet.
SystemSource.xsltransform_param1=Source document
@@ -778,10 +781,10 @@
SystemSource.xmlelement_result=XML result
SystemSource.xmlconcat_description=Concat XML types.
SystemSource.xmlconcat_param1=First element
-SystemSource.xmlcomment_description=Creates an XML comment.
+SystemSource.xmlcomment_description=Create an XML comment.
SystemSource.xmlconcat_param1=String comment
SystemSource.xmlconcat_result=XML result
-SystemSource.xmlpi_description=Creates an XML processing instruction.
+SystemSource.xmlpi_description=Create an XML processing instruction.
SystemSource.xmlpi_param1=Target
SystemSource.xmlpi_param2=Content
SystemSource.xmlpi_result=XML result
@@ -900,4 +903,5 @@
SetClause.resolvingError=Cannot set symbol ''{1}'' with expected type {2} to expression ''{0}''
NewCalculateCostUtil.badCost=Unexpected format encountered for max or min value
-WorkerPool.Max_thread=Reached maximum thread count "{0}" for worker pool "{1}" with a queue size of "{2}".
\ No newline at end of file
+WorkerPool.Max_thread=Reached maximum thread count "{0}" for worker pool "{1}" with a queue size of "{2}".
+XMLSystemFunctions.invalid_namespaces=Invalid namespaces supplied for XPath expression - ''{0}''
\ No newline at end of file
Deleted: trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/internal/core/xml/TestXPathHelper.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -1,185 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.internal.core.xml;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-
-import junit.framework.TestCase;
-
-import net.sf.saxon.trans.XPathException;
-
-import org.jdom.Attribute;
-import org.jdom.Element;
-
-import com.metamatrix.core.util.FileUtil;
-import com.metamatrix.core.util.UnitTestUtil;
-
-
-/**
- * @since 4.2
- */
-public class TestXPathHelper extends TestCase {
-
- /**
- * Constructor for TestXPathHelper.
- * @param name
- */
- public TestXPathHelper(String name) {
- super(name);
- }
-
- // =========================================================================
- // H E L P E R M E T H O D S
- // =========================================================================
-
- public String getContentOfTestFile( final String testFilePath ) {
- final File file = UnitTestUtil.getTestDataFile(testFilePath);
- assertNotNull(file);
- assertEquals(true,file.exists());
- final FileUtil util = new FileUtil(file.getAbsolutePath());
- assertNotNull(util);
- return util.read();
- }
-
- public String helpTestXpathValue(final String xmlFilePath, final String xpath,
- final String expected) throws XPathException, IOException {
- final String actual = helpGetNode(xmlFilePath,xpath);
- assertEquals(expected,actual);
- return actual;
- }
-
- public String helpGetNode(final String xmlFilePath, final String xpath ) throws XPathException, IOException {
- final String xmlContent = getContentOfTestFile(xmlFilePath);
- final Reader docReader = new StringReader(xmlContent);
- return XPathHelper.getSingleMatchAsString(docReader,xpath);
- }
-
- public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri,
- final String textContent) {
- assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
- final Element element = (Element)jdomNode;
- assertEquals(name, element.getName());
- assertEquals(prefix, element.getNamespacePrefix());
- assertEquals(namespaceUri, element.getNamespaceURI());
-
- final String actualTextContent = element.getText();
- if (textContent == null) {
- assertEquals(0, actualTextContent.length());
- } else {
- assertEquals(textContent, actualTextContent);
- }
- }
-
- public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri) {
- assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
- final Element element = (Element)jdomNode;
- assertEquals(name, element.getName());
- assertEquals(prefix, element.getNamespacePrefix());
- assertEquals(namespaceUri, element.getNamespaceURI());
- }
-
- public void helpCheckAttribute(final Object jdomNode, final String name,
- final String prefix, final String namespaceUri,
- final String value ) {
- assertTrue("Supplied JDOM node is not an Attribute",jdomNode instanceof Attribute); //$NON-NLS-1$
- final Attribute attribute = (Attribute)jdomNode;
- assertEquals(name,attribute.getName());
- assertEquals(prefix,attribute.getNamespacePrefix());
- assertEquals(namespaceUri,attribute.getNamespaceURI());
-
- final String actualTextContent = attribute.getValue();
- assertEquals(value,actualTextContent);
- }
-
- // =========================================================================
- // T E S T C A S E S
- // =========================================================================
-
- public void testValidateXpath_Defect15088() {
- // Mismatched tick and quote
- final String xpath = "//*[local-name()='bookName\"]"; //$NON-NLS-1$
- try {
- XPathHelper.validateXpath(xpath);
- fail("Expected validation error but got none"); //$NON-NLS-1$
- } catch(XPathException e) {
- }
- }
-
- public void testValidateXpath_null() throws Exception {
- XPathHelper.validateXpath(null);
- }
-
- public void testValidateXpath_valid() throws Exception {
- XPathHelper.validateXpath("//shipTo/@country"); //$NON-NLS-1$
- }
-
- public void testGetSingleMatch_01_001() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "//shipTo/@country"; //$NON-NLS-1$
- final String expectedValue = "US"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,expectedValue);
- }
-
- public void testGetSingleMatch_01_002() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "//@partNum"; //$NON-NLS-1$
- final String expectedValue = "872-AA"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,expectedValue);
- }
-
- public void testGetSingleMatch_01_003() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "//productName"; //$NON-NLS-1$
- final String expectedValue = "Lawnmower"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,expectedValue);
- }
-
- public void testGetSingleMatch_01_004() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "/*:Envelope/billTo/zip"; //$NON-NLS-1$
- final String expectedValue = "95819"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,expectedValue);
- }
-
- public void testGetSingleMatch_02_001() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "/*:Envelope/*:HEADER/*:RequestID"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,null);
- }
-
- public void testGetSingleMatch_03() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "//*[local-name()=\"ReadOnly\"]"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,"false"); //$NON-NLS-1$
- }
-
- public void testGetSingleMatch_04() throws Exception {
- final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
- final String xpath = "//*:ReadOnly"; //$NON-NLS-1$
- helpTestXpathValue(xmlFilePath,xpath,"false"); //$NON-NLS-1$
- }
-
-}
Modified: trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -1390,4 +1390,15 @@
String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
assertEquals("<!--comment-->", xml);
}
+
+ @Test public void testInvokeXpathQuery() throws Exception {
+ CommandContext c = new CommandContext();
+ c.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
+ XMLType result = (XMLType)helpInvokeMethod("xpathquery", new Class[] {DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING},
+ new Object[] {"<foo><bar>1</bar><bar>2</bar></foo>", "/foo/bar"}, c);
+
+ String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
+ assertEquals("<bar>1</bar><bar>2</bar>", xml);
+ }
+
}
Modified: trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/source/TestXMLSystemFunctions.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -22,86 +22,188 @@
package com.metamatrix.query.function.source;
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import javax.xml.xpath.XPathExpressionException;
+
+import org.jdom.Attribute;
+import org.jdom.Element;
+import org.junit.Test;
+
import com.metamatrix.api.exception.query.FunctionExecutionException;
import com.metamatrix.common.types.SQLXMLImpl;
import com.metamatrix.common.types.XMLType;
+import com.metamatrix.core.util.FileUtil;
+import com.metamatrix.core.util.UnitTestUtil;
+ at SuppressWarnings("nls")
+public class TestXMLSystemFunctions {
+
+ public String getContentOfTestFile( final String testFilePath ) {
+ final File file = UnitTestUtil.getTestDataFile(testFilePath);
+ final FileUtil util = new FileUtil(file.getAbsolutePath());
+ return util.read();
+ }
+
+ public String helpTestXpathValue(final String xmlFilePath, final String xpath,
+ String namespaces, final String expected) throws IOException, XPathExpressionException, FunctionExecutionException {
+ final String actual = helpGetNode(xmlFilePath,xpath, namespaces);
+ assertEquals(expected,actual);
+ return actual;
+ }
-/**
- * @since 4.2
- */
-public class TestXMLSystemFunctions extends TestCase {
+ public String helpGetNode(final String xmlFilePath, final String xpath, String namespaces ) throws IOException, XPathExpressionException, FunctionExecutionException {
+ final String xmlContent = getContentOfTestFile(xmlFilePath);
+ final Reader docReader = new StringReader(xmlContent);
+ return XMLSystemFunctions.xpathValue(docReader,xpath, namespaces);
+ }
- public void testElement() throws Exception {
+ public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri,
+ final String textContent) {
+ assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
+ final Element element = (Element)jdomNode;
+ assertEquals(name, element.getName());
+ assertEquals(prefix, element.getNamespacePrefix());
+ assertEquals(namespaceUri, element.getNamespaceURI());
+
+ final String actualTextContent = element.getText();
+ if (textContent == null) {
+ assertEquals(0, actualTextContent.length());
+ } else {
+ assertEquals(textContent, actualTextContent);
+ }
+ }
+
+ public void helpCheckElement(final Object jdomNode, final String name, final String prefix, final String namespaceUri) {
+ assertTrue("Supplied JDOM node is not an Element", jdomNode instanceof Element); //$NON-NLS-1$
+ final Element element = (Element)jdomNode;
+ assertEquals(name, element.getName());
+ assertEquals(prefix, element.getNamespacePrefix());
+ assertEquals(namespaceUri, element.getNamespaceURI());
+ }
+
+ public void helpCheckAttribute(final Object jdomNode, final String name,
+ final String prefix, final String namespaceUri,
+ final String value ) {
+ assertTrue("Supplied JDOM node is not an Attribute",jdomNode instanceof Attribute); //$NON-NLS-1$
+ final Attribute attribute = (Attribute)jdomNode;
+ assertEquals(name,attribute.getName());
+ assertEquals(prefix,attribute.getNamespacePrefix());
+ assertEquals(namespaceUri,attribute.getNamespaceURI());
+
+ final String actualTextContent = attribute.getValue();
+ assertEquals(value,actualTextContent);
+ }
+
+ @Test public void testElement() throws Exception {
String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
String xpath = "a/b/c"; //$NON-NLS-1$
- String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
assertEquals("test", value); //$NON-NLS-1$
}
- public void testAttribute() throws Exception {
+ @Test public void testAttribute() throws Exception {
String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b c=\"test\"></b></a>"; //$NON-NLS-1$
String xpath = "a/b/@c"; //$NON-NLS-1$
- String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
assertEquals("test", value); //$NON-NLS-1$
}
- public void testText() throws Exception {
+ @Test public void testText() throws Exception {
String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
String xpath = "a/b/c/text()"; //$NON-NLS-1$
- String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
assertEquals("test", value); //$NON-NLS-1$
}
- public void testNoMatch() throws Exception {
+ @Test public void testNoMatch() throws Exception {
String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
String xpath = "x"; //$NON-NLS-1$
- String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
assertEquals(null, value);
}
- public void testNoXMLHeader() throws Exception {
+ @Test public void testNoXMLHeader() throws Exception {
String doc = "<a><b><c>test</c></b></a>"; //$NON-NLS-1$
String xpath = "a/b/c/text()"; //$NON-NLS-1$
- String value = (String) XMLSystemFunctions.xpathValue(doc, xpath);
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
assertEquals("test", value); //$NON-NLS-1$
}
// simulate what would happen if someone passed the output of an XML query to the xpathvalue function
- public void testXMLInput() throws Exception {
+ @Test public void testXMLInput() throws Exception {
XMLType doc = new XMLType(new SQLXMLImpl("<foo/>"));//$NON-NLS-1$
String xpath = "a/b/c"; //$NON-NLS-1$
- try {
- XMLSystemFunctions.xpathValue(doc, xpath);
- } catch(FunctionExecutionException e) {
- // expected
- //System.out.println(e.getMessage());
- }
+ String value = XMLSystemFunctions.xpathValue(doc, xpath);
+ assertNull(value);
}
- public void testBadTypeInput() throws Exception {
- Integer doc = new Integer(1);
- String xpath = "a/b/c"; //$NON-NLS-1$
- try {
- XMLSystemFunctions.xpathValue(doc, xpath);
- fail("Expected exception passing xml stream to xpathvalue()"); //$NON-NLS-1$
- } catch(FunctionExecutionException e) {
- // expected
- //System.out.println(e.getMessage());
- }
- }
-
- public void testBadXPath() throws Exception {
+ @Test(expected=XPathExpressionException.class) public void testBadXPath() throws Exception {
String doc = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>"; //$NON-NLS-1$
String xpath = ":BOGUS:"; //$NON-NLS-1$
- try {
- XMLSystemFunctions.xpathValue(doc, xpath);
- fail("Expected exception passing bad xpath"); //$NON-NLS-1$
- } catch(FunctionExecutionException e) {
- // expected
- }
+ XMLSystemFunctions.xpathValue(doc, xpath);
}
+
+ @Test(expected=XPathExpressionException.class) public void testValidateXpath_Defect15088() throws Exception {
+ // Mismatched tick and quote
+ final String xpath = "//*[local-name()='bookName\"]"; //$NON-NLS-1$
+ XMLSystemFunctions.validateXpath(xpath);
+ }
+ @Test public void testValidateXpath_null() throws Exception {
+ XMLSystemFunctions.validateXpath(null);
+ }
+
+ @Test public void testValidateXpath_valid() throws Exception {
+ XMLSystemFunctions.validateXpath("//shipTo/@country"); //$NON-NLS-1$
+ }
+
+ @Test public void testGetSingleMatch_01_001() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "//shipTo/@country"; //$NON-NLS-1$
+ final String expectedValue = "US"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+ }
+
+ @Test public void testGetSingleMatch_01_002() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "//@partNum"; //$NON-NLS-1$
+ final String expectedValue = "872-AA"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+ }
+
+ @Test public void testGetSingleMatch_01_003() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "//productName"; //$NON-NLS-1$
+ final String expectedValue = "Lawnmower"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,null, expectedValue);
+ }
+
+ @Test public void testGetSingleMatch_01_004() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "/SOAP-ENV:Envelope/billTo/zip"; //$NON-NLS-1$
+ final String expectedValue = "95819"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,"xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"", expectedValue);
+ }
+
+ @Test public void testGetSingleMatch_03() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "//*[local-name()=\"ReadOnly\"]"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,null, "false"); //$NON-NLS-1$
+ }
+
+ /**
+ * * is no longer valid to match the namespace
+ */
+ @Test(expected=XPathExpressionException.class) public void testGetSingleMatch_04() throws Exception {
+ final String xmlFilePath = "testdoc.xml"; //$NON-NLS-1$
+ final String xpath = "//*:ReadOnly"; //$NON-NLS-1$
+ helpTestXpathValue(xmlFilePath,xpath,null, "false"); //$NON-NLS-1$
+ }
+
}
Modified: trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/parser/TestParser.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -6737,5 +6737,10 @@
SQLXMLFunction f = new SQLXMLFunction("xmlforest", Arrays.asList((SingleElementSymbol)new AliasSymbol("table", new ElementSymbol("a"))));
helpTestExpression("xmlforest(a as \"table\")", "xmlforest(a AS \"table\")", f);
}
+
+ @Test public void testXmlPi() throws Exception {
+ Function f = new Function("xmlpi", new Expression[] {new Constant("a"), new ElementSymbol("val")});
+ helpTestExpression("xmlpi(NAME a, val)", "xmlpi(NAME a, val)", f);
+ }
}
Modified: trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/resolver/TestResolver.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -2171,23 +2171,6 @@
assertTrue("Params should be not equal", ! params[0].equals(params[1])); //$NON-NLS-1$
}
- @Test public void testXpathValueValid_defect15088() {
- String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', 'a/b/c')"; //$NON-NLS-1$
- helpResolve(userSql, FakeMetadataFactory.exampleBQTCached(), AnalysisRecord.createNonRecordingRecord());
- }
-
- @Test public void testXpathValueInvalid_defect15088() throws Exception {
- String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"; //$NON-NLS-1$
- Command command = helpParse(userSql);
-
- try {
- QueryResolver.resolveCommand(command, FakeMetadataFactory.exampleBQTCached(), AnalysisRecord.createNonRecordingRecord());
- fail("Expected resolver exception on invalid xpath value"); //$NON-NLS-1$
- } catch(QueryResolverException e) {
- //System.out.println(e.getMessage());
- }
- }
-
@Test public void testNullConstantInSelect() throws Exception {
String userSql = "SELECT null as x"; //$NON-NLS-1$
Query query = (Query)helpParse(userSql);
Modified: trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java 2010-05-07 20:25:05 UTC (rev 2106)
+++ trunk/engine/src/test/java/com/metamatrix/query/validator/TestValidator.java 2010-05-07 21:35:44 UTC (rev 2107)
@@ -65,6 +65,7 @@
import com.metamatrix.query.unittest.FakeMetadataObject;
import com.metamatrix.query.unittest.FakeMetadataStore;
+ at SuppressWarnings("nls")
public class TestValidator {
public static Map getStoredProcedureExternalMetadata(GroupSymbol virtualProc, QueryMetadataInterface metadata)
@@ -1961,5 +1962,21 @@
@Test public void testValidateNoExpressionName() {
helpValidate("SELECT xmlelement(name a, xmlattributes('1'))", new String[] {"'1'"}, exampleMetadata2()); //$NON-NLS-1$ //$NON-NLS-2$
}
+
+ @Test public void testXpathValueValid_defect15088() {
+ String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', 'a/b/c')"; //$NON-NLS-1$
+ helpValidate(userSql, new String[] {}, FakeMetadataFactory.exampleBQTCached());
+ }
+ @Test public void testXpathValueInvalid_defect15088() throws Exception {
+ String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"; //$NON-NLS-1$
+ helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"}, FakeMetadataFactory.exampleBQTCached());
+ }
+
+ @Test public void testXpathValueInvalidNamespaces() throws Exception {
+ String userSql = "SELECT xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=\"bookName\"]', 'xmlns==')"; //$NON-NLS-1$
+ helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=\"bookName\"]', 'xmlns==')"}, FakeMetadataFactory.exampleBQTCached());
+ }
+
+
}
More information about the teiid-commits
mailing list