INTEXT-12 - Add XQuery support
For reference: https://jira.springsource.org/browse/INTEXT-12
This commit is contained in:
committed by
Gunnar Hillert
parent
e353bf49f5
commit
0180a51729
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
|
||||
/**
|
||||
* The namespace handler for the "int-xquery" namespace
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class IntegrationXQueryNamespaceHandler extends
|
||||
AbstractIntegrationNamespaceHandler {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("xquery-router", new XQueryRouterParser());
|
||||
registerBeanDefinitionParser("xquery-transformer", new XQueryTransformerParser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.xquery.core.XQueryExecutor;
|
||||
import org.springframework.integration.xquery.support.XQueryParameter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* The common utility class for the XQuery components that will be performing the
|
||||
* common operations used in the parsers like, creating the XQueryExecutor instance
|
||||
* etc.
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryParserUtils {
|
||||
|
||||
/**
|
||||
* Create the instance of the {@link XQueryExecutor}
|
||||
* @param element
|
||||
* @return
|
||||
*/
|
||||
public static final AbstractBeanDefinition getXQueryExecutor(Element element) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XQueryExecutor.class);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "converter");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "xq-datasource","xQDataSource");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "format-output");
|
||||
NodeList list = element.getElementsByTagNameNS(element.getNamespaceURI(), "xquery");
|
||||
Attr xQueryAttribute = element.getAttributeNode("xquery");
|
||||
Attr xQueryResource = element.getAttributeNode("xquery-file-resource");
|
||||
|
||||
Assert.isTrue(!(xQueryAttribute != null && xQueryResource != null),
|
||||
"Only one of xquery or xquery-file-resource may be specified");
|
||||
|
||||
Assert.isTrue(!(xQueryAttribute != null && list != null && list.getLength() > 0),
|
||||
"At most one of the xquery attribute " +
|
||||
"or the xquery child element should to be provided");
|
||||
|
||||
Assert.isTrue(!(xQueryResource != null && list != null && list.getLength() > 0),
|
||||
"At most one of the xquery-file-resource attribute " +
|
||||
"or the xquery child element should to be provided");
|
||||
|
||||
Assert.isTrue(xQueryResource != null || xQueryAttribute != null || (list != null && list.getLength() > 0),
|
||||
"At least one of xquery, xquery-file-resource attributes or the xquery child element needs to be provided");
|
||||
|
||||
if(xQueryResource != null) {
|
||||
//resource specified
|
||||
String textContent = xQueryResource.getTextContent();
|
||||
Assert.isTrue(StringUtils.hasText(textContent),"Non empty, non null resource path should be provided");
|
||||
Resource resource;
|
||||
if(textContent.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
|
||||
resource = new ClassPathResource(textContent.substring(ResourceUtils.CLASSPATH_URL_PREFIX.length()));
|
||||
}
|
||||
else if(textContent.startsWith(ResourceUtils.FILE_URL_PREFIX)) {
|
||||
resource = new FileSystemResource(textContent.substring(ResourceUtils.FILE_URL_PREFIX.length()));
|
||||
}
|
||||
else {
|
||||
//assuming its a classpath resource
|
||||
resource = new ClassPathResource(textContent);
|
||||
}
|
||||
builder.addPropertyValue("xQueryFileResource", resource);
|
||||
}
|
||||
else {
|
||||
//child element or attribute defined
|
||||
String textContent;
|
||||
if(xQueryAttribute == null) {
|
||||
//child might be element specified
|
||||
Assert.isTrue(list != null && list.getLength() == 1,"Maximum one xquery child node may be specified");
|
||||
textContent = list.item(0).getTextContent();
|
||||
}
|
||||
else {
|
||||
//xquery specified in the attribute
|
||||
textContent = xQueryAttribute.getTextContent();
|
||||
}
|
||||
if(StringUtils.hasText(textContent)) {
|
||||
builder.addPropertyValue("xQuery", textContent.trim());
|
||||
}
|
||||
}
|
||||
|
||||
//lets get the parameter nodes
|
||||
NodeList parameters = element.getElementsByTagNameNS(element.getNamespaceURI(), "xquery-parameter");
|
||||
if(parameters != null && parameters.getLength() > 0) {
|
||||
ManagedList<AbstractBeanDefinition> params = new ManagedList<AbstractBeanDefinition>();
|
||||
for(int i = 0;i < parameters.getLength();i++) {
|
||||
Node node = parameters.item(i);
|
||||
NamedNodeMap attrs = node.getAttributes();
|
||||
Assert.isTrue(attrs.getLength() > 1,
|
||||
"One of ref, value or expression should be present with the name attribute");
|
||||
Attr nameAttr = (Attr)attrs.getNamedItem("name");
|
||||
|
||||
//TODO No check for the mutually exclusivity of these attributes, needed?
|
||||
|
||||
//create a new XQueryParameter instance
|
||||
BeanDefinitionBuilder paramBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(XQueryParameter.class);
|
||||
paramBuilder.addConstructorArgValue(nameAttr.getTextContent());
|
||||
Attr attr;
|
||||
//add the value if present
|
||||
if(attrs.getNamedItem("value") != null) {
|
||||
attr = (Attr)attrs.getNamedItem("value");
|
||||
paramBuilder.addPropertyValue("parameterValue",attr.getTextContent());
|
||||
}
|
||||
else if(attrs.getNamedItem("ref") != null) {
|
||||
attr = (Attr)attrs.getNamedItem("ref");
|
||||
paramBuilder.addPropertyReference("parameterValue", attr.getTextContent());
|
||||
}
|
||||
else if(attrs.getNamedItem("expression") != null) {
|
||||
attr = (Attr)attrs.getNamedItem("expression");
|
||||
paramBuilder.addPropertyValue("expression", attr.getTextContent());
|
||||
}
|
||||
params.add(paramBuilder.getBeanDefinition());
|
||||
}
|
||||
builder.addPropertyValue("xQueryParameters", params);
|
||||
}
|
||||
|
||||
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractRouterParser;
|
||||
import org.springframework.integration.xquery.router.XQueryRouter;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* The parser for the XQuery router
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryRouterParser extends AbstractRouterParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinition doParseRouter(Element element,
|
||||
ParserContext parserContext) {
|
||||
BeanDefinitionBuilder routerBuilder = BeanDefinitionBuilder.genericBeanDefinition(XQueryRouter.class);
|
||||
AbstractBeanDefinition executor = XQueryParserUtils.getXQueryExecutor(element);
|
||||
routerBuilder.addPropertyValue("executor", executor);
|
||||
return routerBuilder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractTransformerParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The parser for the XQuery transformer component
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryTransformerParser extends AbstractTransformerParser {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.config.xml.AbstractTransformerParser#getTransformerClassName()
|
||||
*/
|
||||
@Override
|
||||
protected String getTransformerClassName() {
|
||||
return "org.springframework.integration.xquery.transformer.XQueryTransformer";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.config.xml.AbstractTransformerParser#parseTransformer(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void parseTransformer(Element element,
|
||||
ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
AbstractBeanDefinition executor = XQueryParserUtils.getXQueryExecutor(element);
|
||||
builder.addPropertyValue("executor", executor);
|
||||
//Add the result type and the result class attributes
|
||||
String resultType = element.getAttribute("result-type");
|
||||
boolean hasResultType = StringUtils.hasText(resultType);
|
||||
String xqueryResultMapper = element.getAttribute("xquery-result-mapper");
|
||||
boolean hasResultMapper = StringUtils.hasText(xqueryResultMapper);
|
||||
Assert.isTrue(!(hasResultType && hasResultMapper),
|
||||
"Only one of result-type or xquery-result-mapper may be specified");
|
||||
if(hasResultType) {
|
||||
Class<?> type = null;
|
||||
if("string".equalsIgnoreCase(resultType)) {
|
||||
type = String.class;
|
||||
}
|
||||
else if("boolean".equalsIgnoreCase(resultType)) {
|
||||
type = Boolean.class;
|
||||
}
|
||||
else if("number".equalsIgnoreCase(resultType)) {
|
||||
type = Number.class;
|
||||
}
|
||||
else if("node".equalsIgnoreCase(resultType)) {
|
||||
type = Node.class;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
type = Class.forName(resultType);
|
||||
} catch (ClassNotFoundException e) {
|
||||
new IllegalArgumentException("Class " + resultType + " specified in result-type not found, " +
|
||||
"have you provided the fully qualified name?",e);
|
||||
}
|
||||
}
|
||||
builder.addPropertyValue("resultType", type);
|
||||
}
|
||||
else if(hasResultMapper) {
|
||||
builder.addPropertyReference("resultMapper", xqueryResultMapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xquery.XQConnection;
|
||||
import javax.xml.xquery.XQConstants;
|
||||
import javax.xml.xquery.XQDataSource;
|
||||
import javax.xml.xquery.XQException;
|
||||
import javax.xml.xquery.XQPreparedExpression;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.xml.DefaultXmlPayloadConverter;
|
||||
import org.springframework.integration.xml.XmlPayloadConverter;
|
||||
import org.springframework.integration.xquery.support.AbstractXQueryResultMapper;
|
||||
import org.springframework.integration.xquery.support.BooleanResultMapper;
|
||||
import org.springframework.integration.xquery.support.NodeResultMapper;
|
||||
import org.springframework.integration.xquery.support.NumberResultMapper;
|
||||
import org.springframework.integration.xquery.support.StringResultMapper;
|
||||
import org.springframework.integration.xquery.support.XQueryParameter;
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.springframework.integration.xquery.support.XQueryUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The common logic for performing the common xquery operations would reside in this
|
||||
* implementation.
|
||||
* The class would be instantiated with the xquery to be executed and the parameters
|
||||
* that would be used. It would return the result of the execution with the
|
||||
* {@link Message} instance passed to one of its execute methods.
|
||||
* Currently doesn't support advanced mapping techniques of mapping the resulting Node(s)
|
||||
* to a custom object type
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryExecutor implements InitializingBean,BeanClassLoaderAware {
|
||||
|
||||
|
||||
private static final String SAXON_XQ_DATASOURCE_CLASS = "net.sf.saxon.xqj.SaxonXQDataSource";
|
||||
|
||||
private final Log logger = LogFactory.getLog(XQueryExecutor.class);
|
||||
|
||||
/**
|
||||
* The payload converter
|
||||
*/
|
||||
private XmlPayloadConverter converter = new DefaultXmlPayloadConverter();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private volatile Map resultMappers;
|
||||
|
||||
private volatile boolean formatOutput;
|
||||
|
||||
/**
|
||||
* The xQuery that this Executor will execute
|
||||
*/
|
||||
private String xQuery;
|
||||
|
||||
private XQDataSource xqDataSource;
|
||||
|
||||
private Map<String, XQueryParameter> xQueryParameterMap;
|
||||
|
||||
//maintained internally and used for setting the values
|
||||
private List<String> xQueryParameters;
|
||||
|
||||
//The resource to the XQuery's .xq file
|
||||
private Resource xQueryFileResource;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String password;
|
||||
|
||||
private ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
//TODO: Can we have a static xml resource which will be used always to execute the
|
||||
//given XQuery as against the one sent in the payload. The default is to use the one in the
|
||||
//payload unless one for static xml is provided
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if(resultMappers == null) {
|
||||
resultMappers = new HashMap<Class<?>,XQueryResultMapper<?>>();
|
||||
}
|
||||
addDefaultMappers();
|
||||
|
||||
if(xqDataSource == null) {
|
||||
xqDataSource = discoverXQDataSource();//default
|
||||
}
|
||||
if(xQuery == null) {
|
||||
//perhaps resource specified
|
||||
Assert.notNull(xQueryFileResource, "One of XQuery or the XQuery resource is mandatory");
|
||||
xQuery = XQueryUtils.readXQueryFromResource(xQueryFileResource);
|
||||
}
|
||||
|
||||
try {
|
||||
XQConnection conn = getConnection();
|
||||
XQPreparedExpression expression = conn.prepareExpression(xQuery);
|
||||
QName[] extParameters = expression.getAllExternalVariables();
|
||||
if(extParameters != null && extParameters.length > 0) {
|
||||
xQueryParameters = new ArrayList<String>();
|
||||
for(QName qName:extParameters) {
|
||||
xQueryParameters.add(qName.getLocalPart());
|
||||
}
|
||||
}
|
||||
expression.close();
|
||||
conn.close();
|
||||
} catch (XQException e) {
|
||||
throw new MessagingException("Caught Exception while opening a connection to the datasource", e);
|
||||
}
|
||||
|
||||
if(xQueryParameters != null) {
|
||||
if (xQueryParameterMap == null) {
|
||||
throw new MessagingException("Expecting " + xQueryParameters.size() + " parameters in the xquery, " +
|
||||
"but none provided to the router");
|
||||
}
|
||||
|
||||
//now check if all the parameter needed are present in the map
|
||||
List<String> missingParameters = new ArrayList<String>();
|
||||
for(String xQueryParameter:xQueryParameters) {
|
||||
if(!xQueryParameterMap.containsKey(xQueryParameter)) {
|
||||
missingParameters.add(xQueryParameter);
|
||||
}
|
||||
}
|
||||
|
||||
if(missingParameters.size() > 0) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[").append("$").append(missingParameters.get(0));
|
||||
if(missingParameters.size() > 1) {
|
||||
for(int i = 1;i < missingParameters.size();i++) {
|
||||
builder.append(", ").append("$").append(missingParameters.get(i));
|
||||
}
|
||||
}
|
||||
builder.append("]");
|
||||
throw new MessagingException("Missing parameter(s) " + builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
Assert.notNull(classLoader, "Non null class loader instance expected");
|
||||
this.classLoader = classLoader;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The method that finds an implementation in the classpath for some well known
|
||||
* providers. This will kick into action only if an {@link XQDataSource} is not
|
||||
* explicitly provided by the user by invoking {@link XQueryExecutor#setXQDataSource(XQDataSource)}
|
||||
* The method currently looks for Saxon's implementation only
|
||||
*
|
||||
* @return the instantiated {@link XQDataSource}
|
||||
*/
|
||||
private XQDataSource discoverXQDataSource() {
|
||||
Object xqDataSource = null;
|
||||
try {
|
||||
if(ClassUtils.isPresent(SAXON_XQ_DATASOURCE_CLASS, classLoader)) {
|
||||
xqDataSource = Class.forName(SAXON_XQ_DATASOURCE_CLASS).newInstance();
|
||||
}
|
||||
//For now its just Saxon we will discover, we can add other implementations here later
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Unable to discover/instantiate an XQDataSource, " +
|
||||
"see nested exception for details", e);
|
||||
}
|
||||
Assert.notNull(xqDataSource, "No XQDataSource provided nor any known implementation discovered in the classpath");
|
||||
logger.info("Using \"" + xqDataSource.getClass() + "\" as the XQDataSource implementation");
|
||||
return (XQDataSource)xqDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection, uses userName and password if one is set
|
||||
* @return
|
||||
* @throws XQException
|
||||
*/
|
||||
private XQConnection getConnection() throws XQException {
|
||||
XQConnection conn;
|
||||
if(StringUtils.hasText(userName)) {
|
||||
conn = xqDataSource.getConnection(userName,password);
|
||||
}
|
||||
else {
|
||||
conn = xqDataSource.getConnection();
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* There are some default mappers defined, those will be added if the user has not provided
|
||||
* some implementations for them
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addDefaultMappers() {
|
||||
if(!resultMappers.containsKey(String.class)) {
|
||||
StringResultMapper mapper = new StringResultMapper();
|
||||
mapper.setFormatOutput(formatOutput);
|
||||
resultMappers.put(String.class, mapper);
|
||||
}
|
||||
|
||||
if(!resultMappers.containsKey(Boolean.class)) {
|
||||
BooleanResultMapper mapper = new BooleanResultMapper();
|
||||
mapper.setFormatOutput(formatOutput);
|
||||
resultMappers.put(Boolean.class, mapper);
|
||||
}
|
||||
|
||||
if(!resultMappers.containsKey(Number.class)) {
|
||||
NumberResultMapper mapper = new NumberResultMapper();
|
||||
mapper.setFormatOutput(formatOutput);
|
||||
resultMappers.put(Number.class, mapper);
|
||||
}
|
||||
|
||||
if(!resultMappers.containsKey(Node.class)) {
|
||||
NodeResultMapper mapper = new NodeResultMapper();
|
||||
mapper.setFormatOutput(formatOutput);
|
||||
resultMappers.put(Node.class, mapper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the XQuery for result and produce the result as a {@link List} of {@link String}
|
||||
* @param message the source message that would be used to derive the values of the parameters
|
||||
*
|
||||
* @return The {@link List} of results
|
||||
*/
|
||||
public List<String> executeForString(Message<?> message) {
|
||||
return execute(message,String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the XQuery for result and produce the result as a {@link List} of {@link Boolean}
|
||||
* @param message the source message that would be used to derive the values of the parameters
|
||||
*
|
||||
* @return The {@link List} of results
|
||||
*/
|
||||
public List<Boolean> executeForBoolean(Message<?> message) {
|
||||
return execute(message,Boolean.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the XQuery for result and produce the result as a {@link List} of {@link Number}
|
||||
* @param message the source message that would be used to derive the values of the parameters
|
||||
*
|
||||
* @return The {@link List} of results
|
||||
*/
|
||||
public List<Number> executeForNumber(Message<?> message) {
|
||||
return execute(message,Number.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the XQuery for result and produce the result as a {@link List} of {@link Node}
|
||||
* @param message the source message that would be used to derive the values of the parameters
|
||||
*
|
||||
* @return The {@link List} of results
|
||||
*/
|
||||
public List<Node> executeForNode(Message<?> message) {
|
||||
return execute(message,Node.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given XQuery and returns a {@link List} of the provided type
|
||||
* @param <T>
|
||||
* @param message
|
||||
* @param returnType
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked"})
|
||||
public <T> List<T> execute(Message<?> message,Class<T> returnType) {
|
||||
Assert.notNull(message,"Non null message expected");
|
||||
Assert.notNull(returnType,"Non null type expected");
|
||||
Assert.isTrue(resultMappers.containsKey(returnType),"No Result mapper found for the type " + returnType.getName());
|
||||
return execute(message, (XQueryResultMapper<T>)resultMappers.get(returnType));
|
||||
}
|
||||
|
||||
/**
|
||||
* The method that executes the actual XQuery and uses the provided mapper
|
||||
* to get the result that is returned.
|
||||
* @param <T>
|
||||
* @param message
|
||||
* @param mapper
|
||||
* @return
|
||||
*/
|
||||
public <T> List<T> execute(Message<?> message,XQueryResultMapper<T> mapper) {
|
||||
Node node = converter.convertToNode(message.getPayload());
|
||||
|
||||
if(node == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
XQConnection connection = null;
|
||||
XQPreparedExpression expression = null;
|
||||
try {
|
||||
connection = getConnection();
|
||||
expression = connection.prepareExpression(xQuery);
|
||||
expression.bindNode(XQConstants.CONTEXT_ITEM, node, null);
|
||||
|
||||
//bind the parameter values
|
||||
if(xQueryParameters != null && xQueryParameters.size() > 0) {
|
||||
//bind them one by one
|
||||
for(String parameter:xQueryParameters) {
|
||||
XQueryParameter xQueryParam = xQueryParameterMap.get(parameter);
|
||||
//TODO: Check what possible values can be supported to be set here
|
||||
//Accordingly do we need to set the third parameter for XQItemType
|
||||
expression.bindObject(new QName(xQueryParam.getParameterName()),
|
||||
xQueryParam.evaluate(message), null);
|
||||
}
|
||||
}
|
||||
|
||||
XQResultSequence result = expression.executeQuery();
|
||||
return mapper.mapResults(result);
|
||||
|
||||
} catch (XQException e) {
|
||||
throw new MessagingException("Caught Exception while opening a connection to the datasource", e);
|
||||
} finally {
|
||||
try {
|
||||
if(expression != null) {
|
||||
expression.close();
|
||||
}
|
||||
if(connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (XQException e) {
|
||||
logger.error("Caught Exception while closing the XQ expression.connection", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all the result mappers to be used by this executor.
|
||||
* @param <T>
|
||||
* @param mappers
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public <T> void setResultMappers(Map<Class<T>, XQueryResultMapper<T>> mappers) {
|
||||
Assert.notNull(mappers);
|
||||
this.resultMappers = new HashMap<Class<T>, XQueryResultMapper<T>>(mappers);
|
||||
//not iterate through them and set the format
|
||||
for(Object mapper:resultMappers.values()) {
|
||||
if(mapper instanceof AbstractXQueryResultMapper) {
|
||||
((AbstractXQueryResultMapper)mapper).setFormatOutput(formatOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Set the {@link XmlPayloadConverter} that would be used to convert the payload
|
||||
* into the XML {@link Node}
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
public void setConverter(XmlPayloadConverter converter) {
|
||||
Assert.notNull(converter, "Provide a non null instance of XmlPayloadConverter");
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The XQuery string that would be evaluated to determine the channel names
|
||||
* @param xQuery
|
||||
*/
|
||||
public void setXQuery(String xQuery) {
|
||||
Assert.isTrue(xQueryFileResource == null, "Only one of XQuery resource file or XQuery may be specified");
|
||||
Assert.notNull(xQuery, "Provide a non null XQuery");
|
||||
this.xQuery = xQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the XQuery's .xq file as the resource. The contents of this file will be read as xQuery
|
||||
*
|
||||
* @param xQueryFileResource
|
||||
*/
|
||||
public void setXQueryFileResource(Resource xQueryFileResource) {
|
||||
Assert.isTrue(xQuery == null,"Only one of XQuery resource file or XQuery may be specified");
|
||||
this.xQueryFileResource = xQueryFileResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link XQDataSource}
|
||||
* @param xqDataSource
|
||||
*/
|
||||
public void setXQDataSource(XQDataSource xqDataSource) {
|
||||
Assert.notNull(xqDataSource, "Provide a non null instance of the XQDatasource");
|
||||
this.xqDataSource = xqDataSource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the parameter map where the parameter name is the key and the
|
||||
* {@link XQueryParameter} instance is the value
|
||||
*
|
||||
* @param xQueryParameterMap
|
||||
*/
|
||||
public void setXQueryParameterMap(
|
||||
Map<String, XQueryParameter> xQueryParameterMap) {
|
||||
this.xQueryParameterMap = xQueryParameterMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to add a {@link XQueryParameter} to the map
|
||||
* @param param
|
||||
*/
|
||||
public void addXQueryParameter(XQueryParameter param) {
|
||||
if(xQueryParameterMap == null) {
|
||||
xQueryParameterMap = new HashMap<String, XQueryParameter>();
|
||||
}
|
||||
xQueryParameterMap.put(param.getParameterName(), param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that would be used to set the parameters in the parameter
|
||||
* map. Any non conflicting parameters would be retained
|
||||
* @param params
|
||||
*/
|
||||
public void setXQueryParameters(List<XQueryParameter> params) {
|
||||
if(params != null && params.size() > 0) {
|
||||
if(xQueryParameterMap == null)
|
||||
xQueryParameterMap = new HashMap<String, XQueryParameter>();
|
||||
for(XQueryParameter param:params) {
|
||||
xQueryParameterMap.put(param.getParameterName(), param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the output result is an xml, the value of this parameter will determine
|
||||
* if the output xml is to be formatted or not. By default, the output will
|
||||
* not be formatted
|
||||
*
|
||||
* @param formatOutput
|
||||
*/
|
||||
public void setFormatOutput(boolean formatOutput) {
|
||||
this.formatOutput = formatOutput;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO: Support date, dateTime data types
|
||||
|
||||
|
||||
/**
|
||||
* Sets the user name to be used while obtaining the connection.
|
||||
*
|
||||
*/
|
||||
public void setUserName(String userName) {
|
||||
Assert.hasText(userName, "Null or empty string provided as user name");
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password to be used for obtaining the connection
|
||||
* The value if ignored if the userName is null
|
||||
*
|
||||
* @param password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
Assert.notNull(password, "Null password provided");
|
||||
//Can password be empty string?
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.router.AbstractMappingMessageRouter;
|
||||
import org.springframework.integration.xquery.core.XQueryExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The message router that will evaluate the provided XQuery on the xml to determine the channel(s)
|
||||
* to which the message will be routed
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryRouter extends AbstractMappingMessageRouter {
|
||||
|
||||
private XQueryExecutor executor;
|
||||
|
||||
private Class<?> resultType;
|
||||
|
||||
@Override
|
||||
public void onInit() {
|
||||
super.onInit();
|
||||
Assert.notNull(executor,"No XQueryExecutor instance provided");
|
||||
if(resultType == null) {
|
||||
resultType = String.class;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.router.AbstractMappingMessageRouter#getChannelKeys(org.springframework.integration.Message)
|
||||
*/
|
||||
@Override
|
||||
protected List<Object> getChannelKeys(Message<?> message) {
|
||||
List<Object> channelKeys = null;
|
||||
//Accept the key types in this class and then execute the appropriate method
|
||||
channelKeys = new ArrayList<Object>(executor.execute(message, resultType));
|
||||
return channelKeys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "int-xml:xquery-router";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the executor to be used for executing the XQueries
|
||||
* @param executor
|
||||
*/
|
||||
public void setExecutor(XQueryExecutor executor) {
|
||||
Assert.notNull(executor,"Provide a non null implementation of the executor");
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the type of the object that would returned in the {@link List} returned
|
||||
* from getChannelKeys method. If non specified, {@link String} is assumed.
|
||||
* @param resultType
|
||||
*/
|
||||
public void setResultType(Class<?> resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_BOOLEAN;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_DECIMAL;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_DOUBLE;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_FLOAT;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_INT;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_INTEGER;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_LONG;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_NEGATIVE_INTEGER;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_NONNEGATIVE_INTEGER;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_NONPOSITIVE_INTEGER;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_POSITIVE_INTEGER;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_SHORT;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_STRING;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_UNSIGNED_INT;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_UNSIGNED_LONG;
|
||||
import static javax.xml.xquery.XQItemType.XQBASETYPE_UNSIGNED_SHORT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_ATTRIBUTE;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_COMMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_DOCUMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_DOCUMENT_ELEMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_DOCUMENT_SCHEMA_ELEMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_ELEMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_NODE;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_PI;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_SCHEMA_ATTRIBUTE;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_SCHEMA_ELEMENT;
|
||||
import static javax.xml.xquery.XQItemType.XQITEMKIND_TEXT;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.xquery.XQException;
|
||||
import javax.xml.xquery.XQItemType;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The absract base class for {@link XQueryResultMapper} implementations
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractXQueryResultMapper<T> implements XQueryResultMapper<T> {
|
||||
|
||||
protected volatile boolean formatOutput;
|
||||
/**
|
||||
* The getBaseType method throws an exception if the item kind is of some specific types
|
||||
* This method will be used to check if the getBaseType method can be invoked or not
|
||||
* on the given element
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
protected boolean shouldSkipBaseType(XQItemType type) {
|
||||
return isNodeType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method checks if the given type is a numeric field and returns an appropriate implementation
|
||||
* of the {@link Number}
|
||||
*
|
||||
* @param type
|
||||
* @param result
|
||||
* @return the appropriate {@link Number} implementation or null if cannot be converted to number
|
||||
*/
|
||||
protected Number convertToNumber(XQItemType type,XQResultSequence result) throws XQException {
|
||||
boolean skipBaseTypes = shouldSkipBaseType(type);
|
||||
Number value = null;
|
||||
if(!skipBaseTypes) {
|
||||
int baseType = type.getBaseType();
|
||||
if(baseType == XQBASETYPE_DOUBLE) {
|
||||
value = Double.valueOf(result.getDouble());
|
||||
|
||||
}
|
||||
else if(baseType == XQBASETYPE_FLOAT) {
|
||||
value = Float.valueOf(result.getFloat());
|
||||
}
|
||||
else if(baseType == XQBASETYPE_DECIMAL) {
|
||||
value = Double.valueOf(result.getAtomicValue());
|
||||
//TODO: Should DECIMAL be BigDecimal?
|
||||
}
|
||||
|
||||
else if(baseType == XQBASETYPE_INT
|
||||
|| baseType == XQBASETYPE_NEGATIVE_INTEGER
|
||||
|| baseType == XQBASETYPE_POSITIVE_INTEGER
|
||||
|| baseType == XQBASETYPE_NONNEGATIVE_INTEGER
|
||||
|| baseType == XQBASETYPE_NONPOSITIVE_INTEGER
|
||||
|| baseType == XQBASETYPE_UNSIGNED_INT) {
|
||||
value = Integer.valueOf(result.getInt());
|
||||
}
|
||||
else if(baseType == XQBASETYPE_INTEGER) {
|
||||
value = BigInteger.valueOf(result.getInt());
|
||||
}
|
||||
else if(baseType == XQBASETYPE_LONG
|
||||
|| baseType == XQBASETYPE_UNSIGNED_LONG) {
|
||||
value = Long.valueOf(result.getLong());
|
||||
}
|
||||
else if(baseType == XQBASETYPE_SHORT
|
||||
|| baseType == XQBASETYPE_UNSIGNED_SHORT) {
|
||||
value = Short.valueOf(result.getShort());
|
||||
}
|
||||
else if(baseType == XQBASETYPE_STRING) {
|
||||
String strValue = result.getAtomicValue();
|
||||
value = convertStringToNumber(strValue);
|
||||
}
|
||||
}
|
||||
else if(XQITEMKIND_TEXT == type.getItemKind()) {
|
||||
String textContent = result.getNode().getTextContent();
|
||||
value = convertStringToNumber(textContent);
|
||||
}
|
||||
else if(XQITEMKIND_ATTRIBUTE == type.getItemKind()) {
|
||||
String textContent = ((Attr)result.getNode()).getValue();
|
||||
value = convertStringToNumber(textContent);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**Helper method that will be used to convert a String value to Number
|
||||
* @param value
|
||||
* @param strValue
|
||||
* @return
|
||||
*/
|
||||
private Number convertStringToNumber(String strValue) {
|
||||
Number value = null;
|
||||
try {
|
||||
if(StringUtils.hasText(strValue)) {
|
||||
if(strValue.indexOf(".") > 0) {
|
||||
value = Double.valueOf(strValue);
|
||||
}
|
||||
else {
|
||||
value = Long.valueOf(strValue);
|
||||
}
|
||||
}
|
||||
} catch(NumberFormatException ne) {
|
||||
value = null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the given text content as String if the type is a string base type
|
||||
* @param type
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
protected String convertToString(XQItemType type,XQResultSequence result) throws XQException {
|
||||
boolean skipBaseTypes = shouldSkipBaseType(type);
|
||||
String value = null;
|
||||
if(!skipBaseTypes) {
|
||||
int baseType = type.getBaseType();
|
||||
if(baseType == XQBASETYPE_STRING) {
|
||||
value = result.getAtomicValue();
|
||||
}
|
||||
}
|
||||
else if(XQITEMKIND_TEXT == type.getItemKind()) {
|
||||
value = result.getNode().getTextContent();
|
||||
}
|
||||
else if(XQITEMKIND_ATTRIBUTE == type.getItemKind()) {
|
||||
value = ((Attr)result.getNode()).getValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the data type of the string and converts to boolean if applicable.
|
||||
* The types have to be either boolean or string. For a string value,
|
||||
* the returned value is same as Boolean.valueOf(strValue)
|
||||
*
|
||||
* @param type
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
protected Boolean convertToBoolean(XQItemType type,XQResultSequence result) throws XQException {
|
||||
boolean skipBaseTypes = shouldSkipBaseType(type);
|
||||
Boolean value = null;
|
||||
if(!skipBaseTypes) {
|
||||
if(type.getBaseType() == XQBASETYPE_BOOLEAN) {
|
||||
value = Boolean.valueOf(result.getBoolean());
|
||||
}
|
||||
else if(type.getBaseType() == XQBASETYPE_STRING) {
|
||||
value = Boolean.valueOf(result.getAtomicValue());
|
||||
}
|
||||
}
|
||||
else if(XQITEMKIND_TEXT == type.getItemKind()) {
|
||||
String textContent = result.getNode().getTextContent();
|
||||
value = Boolean.valueOf(textContent);
|
||||
}
|
||||
else if(XQITEMKIND_ATTRIBUTE == type.getItemKind()) {
|
||||
String textContent = ((Attr)result.getNode()).getValue();
|
||||
value = Boolean.valueOf(textContent);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given type if for a valid node type
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
protected boolean isNodeType(XQItemType type) {
|
||||
int itemKind = type.getItemKind();
|
||||
return (
|
||||
itemKind == XQITEMKIND_ATTRIBUTE
|
||||
||
|
||||
itemKind == XQITEMKIND_COMMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_DOCUMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_DOCUMENT_ELEMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_DOCUMENT_SCHEMA_ELEMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_ELEMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_NODE
|
||||
||
|
||||
itemKind == XQITEMKIND_PI
|
||||
||
|
||||
itemKind == XQITEMKIND_SCHEMA_ATTRIBUTE
|
||||
||
|
||||
itemKind == XQITEMKIND_SCHEMA_ELEMENT
|
||||
||
|
||||
itemKind == XQITEMKIND_TEXT
|
||||
);
|
||||
}
|
||||
|
||||
/**Transforms the given {@link Node} to a String
|
||||
* @param n
|
||||
* @return
|
||||
* @throws TransformerConfigurationException
|
||||
* @throws TransformerFactoryConfigurationError
|
||||
* @throws TransformerException
|
||||
*/
|
||||
protected String transformNodeToString(Node n)
|
||||
throws TransformerConfigurationException,
|
||||
TransformerFactoryConfigurationError, TransformerException {
|
||||
String value;
|
||||
StringWriter writer = new StringWriter();
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
if(formatOutput)
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.transform( new DOMSource(n), new StreamResult(writer));
|
||||
value = writer.toString();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the output result is an xml, the value of this parameter will determine
|
||||
* if the output xml is to be formatted or not. By default, the output will
|
||||
* not be formatted
|
||||
*
|
||||
* @param formatOutput
|
||||
*/
|
||||
public void setFormatOutput(boolean formatOutput) {
|
||||
this.formatOutput = formatOutput;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQItemType;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Result mapper implementation that maps the {@link XQResultSequence} to {@link Boolean}
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class BooleanResultMapper extends AbstractXQueryResultMapper<Boolean> {
|
||||
|
||||
public List<Boolean> mapResults(XQResultSequence result) {
|
||||
List<Boolean> results = new ArrayList<Boolean>();
|
||||
try {
|
||||
//check for boolean or string type and convert it accordingly, if a node then get it's text
|
||||
//content and convert to boolean
|
||||
while(result.next()) {
|
||||
XQItemType type = result.getItemType();
|
||||
Boolean value = convertToBoolean(type, result);
|
||||
if(value == null) {
|
||||
if(isNodeType(type)) {
|
||||
Node n = result.getNode();
|
||||
value = Boolean.valueOf(transformNodeToString(n));
|
||||
}
|
||||
}
|
||||
results.add(value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Caught Exception while mapping the result sequence to string",e);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQItemType;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Result mapper implementation that maps the {@link XQResultSequence} to {@link Node}
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class NodeResultMapper extends AbstractXQueryResultMapper<Node> {
|
||||
|
||||
public List<Node> mapResults(XQResultSequence result) {
|
||||
List<Node> results = new ArrayList<Node>();
|
||||
try {
|
||||
while(result.next()) {
|
||||
XQItemType type = result.getItemType();
|
||||
if(isNodeType(type)) {
|
||||
Node n = result.getNode();
|
||||
results.add(n);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Caught Exception while mapping the result sequence to string",e);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQItemType;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Result mapper implementation that maps the {@link XQResultSequence} to {@link Number}
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class NumberResultMapper extends AbstractXQueryResultMapper<Number> {
|
||||
|
||||
public List<Number> mapResults(XQResultSequence result) {
|
||||
List<Number> results = new ArrayList<Number>();
|
||||
try {
|
||||
while(result.next()) {
|
||||
|
||||
XQItemType type = result.getItemType();
|
||||
Number value = convertToNumber(type, result);
|
||||
if(value == null) {
|
||||
if(isNodeType(type)) {
|
||||
Node n = result.getNode();
|
||||
String strValue = transformNodeToString(n);
|
||||
if(StringUtils.hasText(strValue)) {
|
||||
if(strValue.indexOf(".") > 0) {
|
||||
value = Double.valueOf(strValue);
|
||||
}
|
||||
else {
|
||||
value = Long.valueOf(strValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
results.add(value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Caught Exception while mapping the result sequence to string",e);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQItemType;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Result mapper implementation that maps the {@link XQResultSequence} to {@link String}
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class StringResultMapper extends AbstractXQueryResultMapper<String> {
|
||||
|
||||
public List<String> mapResults(XQResultSequence result) {
|
||||
List<String> results = new ArrayList<String>();
|
||||
try {
|
||||
while(result.next()) {
|
||||
XQItemType type = result.getItemType();
|
||||
String value = convertToString(type, result);
|
||||
if(value == null) {
|
||||
Number number = convertToNumber(type, result);
|
||||
if(number == null) {
|
||||
Boolean boolValue = convertToBoolean(type, result);
|
||||
if(boolValue == null) {
|
||||
if(isNodeType(type)) {
|
||||
Node n = result.getNode();
|
||||
value = transformNodeToString(n);
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = boolValue.toString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = number.toString();
|
||||
}
|
||||
}
|
||||
results.add(value);
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException("Caught Exception while mapping the result sequence to string",e);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The class that represents the XQuery parameter provided. It is also responsible
|
||||
* for the evaluation and returning the corresponding value against the given {@link Message}
|
||||
* instance
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryParameter {
|
||||
|
||||
private final String parameterName;
|
||||
private volatile Object parameterValue;
|
||||
private volatile String expression;
|
||||
private volatile boolean isValueSet;
|
||||
//Will be used only when an expression is set
|
||||
private volatile ExpressionEvaluatingMessageProcessor<Object> messageProcessor;
|
||||
|
||||
/**
|
||||
* The default no argument constructor
|
||||
*/
|
||||
public XQueryParameter(String parameterName) {
|
||||
Assert.hasText(parameterName, "Non null non empty String value expected for parameter name");
|
||||
this.parameterName = parameterName;
|
||||
}
|
||||
/**
|
||||
* The constructor that takes the parameter name and a static parameter value
|
||||
*
|
||||
* @param parameterName
|
||||
* @param parameterValue
|
||||
*/
|
||||
public XQueryParameter(String parameterName, Object parameterValue) {
|
||||
this(parameterName);
|
||||
Assert.notNull(parameterValue, "Parameter value provided is null");
|
||||
this.parameterValue = parameterValue;
|
||||
isValueSet = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor that takes the parameter name and the expression that would
|
||||
* be evaluated to get the value of the parameter
|
||||
* @param parameterName
|
||||
* @param expression
|
||||
*/
|
||||
public XQueryParameter(String parameterName, String expression) {
|
||||
this(parameterName);
|
||||
Assert.isTrue(StringUtils.hasText(expression), "Non null non empty String value expected for expression");
|
||||
setExpression(expression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the parameter name of this instance
|
||||
* @return
|
||||
*/
|
||||
public String getParameterName() {
|
||||
return parameterName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the parameter value, this is mutually exclusive with the expression
|
||||
* @param parameterValue
|
||||
*/
|
||||
public void setParameterValue(Object parameterValue) {
|
||||
Assert.isTrue(!StringUtils.hasText(expression), "The parameter value and expression are mutually " +
|
||||
"exclusive, parameter expression already set");
|
||||
Assert.notNull(parameterValue, "Null parameter value provided");
|
||||
this.parameterValue = parameterValue;
|
||||
isValueSet = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the expression that would be evaluated to get the parameter value
|
||||
* @param expression
|
||||
*/
|
||||
public void setExpression(String expression) {
|
||||
Assert.isTrue(parameterValue == null, "The parameter value and expression are mutually exclusive" +
|
||||
", parameter value already set");
|
||||
Assert.isTrue(!StringUtils.hasText(this.expression), "Expression string is already set once, cannot reset it");
|
||||
Assert.hasText(expression, "Please provide a non null, non empty expression string");
|
||||
this.expression = expression;
|
||||
isValueSet = false;
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
messageProcessor = new ExpressionEvaluatingMessageProcessor<Object>(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the given message against the provided expression if one is set
|
||||
* else, returns the static value provided. If none of the static value or
|
||||
* expression are provided. The value returned is null.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public Object evaluate(Message<?> message) {
|
||||
if(isValueSet) {
|
||||
return parameterValue;
|
||||
}
|
||||
else {
|
||||
if(messageProcessor != null) {
|
||||
return messageProcessor.processMessage(message);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
/**
|
||||
* The strategy interface that will be used to map the {@link XQResultSequence}
|
||||
* returned by XQuery execution to a List of the specified type
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface XQueryResultMapper<T> {
|
||||
|
||||
/**
|
||||
* Maps the results from the {@link XQResultSequence} to a {@link List} of a specific type
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
List<T> mapResults(XQResultSequence result);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The common utility class that is used to perform all common operations
|
||||
* amongst XQuery modules. To contain all common operations that would be used
|
||||
* by the router, transformer etc along with all the parsers for these components
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryUtils {
|
||||
|
||||
/**
|
||||
* Reads the XQuery string from the resource file specified
|
||||
*
|
||||
* @param resource the {@link Resource} instance of the file that contains the XQuery
|
||||
* currently only classpath and file resources are supported
|
||||
*
|
||||
* @return the XQuery string from the resource specified
|
||||
*/
|
||||
public static String readXQueryFromResource(Resource resource) {
|
||||
Assert.notNull(resource, "null resource provided");
|
||||
Assert.isTrue(resource.exists(), "Provided XQuery resource does not exist");
|
||||
Assert.isTrue(resource.isReadable(), "Provided XQuery resource is not readable");
|
||||
try {
|
||||
URL url = resource.getURL();
|
||||
InputStream inStream = url.openStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
|
||||
String line = reader.readLine();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
while(line != null) {
|
||||
builder.append(line).append("\n");
|
||||
line = reader.readLine();
|
||||
}
|
||||
String xQuery = builder.toString();
|
||||
reader.close();
|
||||
return xQuery;
|
||||
} catch (IOException e) {
|
||||
throw new MessagingException("Error while reading the xQuery resource", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.transformer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.transformer.AbstractTransformer;
|
||||
import org.springframework.integration.xquery.core.XQueryExecutor;
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
|
||||
/**
|
||||
* Transform the incoming message payload to the type specified in the {@link #resultType}
|
||||
* attribute. Currently {@link #resultType} supports only the following values out of the box
|
||||
*
|
||||
* 1. {@link String}
|
||||
* 2. {@link Boolean}
|
||||
* 3. {@link Number}
|
||||
* 4. {@link Node}
|
||||
*
|
||||
* For any other custom conversion, provide an instance of {@link XQueryResultMapper} in the
|
||||
* {@link #resultMapper} attribute. The {@link #resultMapper} and {@link #resultType} attribute
|
||||
* values are mutually exclusive to each other. If none of the above two attributes are
|
||||
* provided then the value of the {@link #resultType} defaults to {@link String}.
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class XQueryTransformer extends AbstractTransformer {
|
||||
|
||||
private XQueryExecutor executor;
|
||||
|
||||
private Class<?> resultType;
|
||||
|
||||
private XQueryResultMapper resultMapper;
|
||||
|
||||
@Override
|
||||
public void onInit() {
|
||||
Assert.notNull(executor,"No XQueryExecutor instance provided");
|
||||
if(resultMapper == null && resultType == null) {
|
||||
resultType = String.class;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.transformer.AbstractTransformer#doTransform(org.springframework.integration.Message)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Object doTransform(Message<?> message) throws Exception {
|
||||
Object transformed;
|
||||
List<Object> queryResult;
|
||||
if(resultType != null) {
|
||||
queryResult = (List<Object>) executor.execute(message, resultType);
|
||||
}
|
||||
else {
|
||||
queryResult = executor.execute(message, resultMapper);
|
||||
}
|
||||
|
||||
if(queryResult != null && queryResult.size() == 1) {
|
||||
transformed = queryResult.get(0);
|
||||
}
|
||||
else {
|
||||
transformed = queryResult;
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the XQuery executor instance to be used by the {@link XQueryTransformer}
|
||||
* @param executor
|
||||
*/
|
||||
public void setExecutor(XQueryExecutor executor) {
|
||||
Assert.notNull(executor,"Provide a non null XQueryExecutor instance");
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Type of the result, if none specified and if a {@link XQueryResultMapper} instance is
|
||||
* not provided, String is assumed by default.
|
||||
* The permitted value of the class is one of the
|
||||
* String.class, Boolean.class, Number.class or Node.class. For any other type of class
|
||||
* Provide an instance of {@link XQueryResultMapper}
|
||||
*
|
||||
* @param resultType
|
||||
*/
|
||||
public void setResultType(Class<?> resultType) {
|
||||
Assert.notNull(resultType,"Provide a non null value for the result type");
|
||||
Assert.isTrue(resultMapper == null,"Only one of the result mapper of the resultType can be set");
|
||||
Assert.isTrue(String.class == resultType || Boolean.class == resultType
|
||||
|| Number.class == resultType || Node.class == resultType,
|
||||
"Valid values for the result type class is String, Boolean, Number or Node, " +
|
||||
"for any other type, provide a custom implementation of XQueryResultMapper");
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ResultMapper to be used for mapping the result of the XQuery Object to
|
||||
* an appropriate object.
|
||||
* @param resultMapper
|
||||
*/
|
||||
public void setResultMapper(XQueryResultMapper resultMapper) {
|
||||
Assert.notNull(resultMapper,"Provide a non null value for the result mapper");
|
||||
Assert.isTrue(resultType == null,"Only one of the result mapper of the resultType can be set");
|
||||
this.resultMapper = resultMapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/integration/xquery=org.springframework.integration.xquery.config.xml.IntegrationXQueryNamespaceHandler
|
||||
@@ -0,0 +1,2 @@
|
||||
http\://www.springframework.org/schema/integration/xquery/spring-integration-xquery-2.2.xsd=org/springframework/integration/xquery/config/spring-integration-xquery-2.2.xsd
|
||||
http\://www.springframework.org/schema/integration/xquery/spring-integration-xquery.xsd=org/springframework/integration/xquery/config/spring-integration-xquery-2.2.xsd
|
||||
@@ -0,0 +1,318 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration/xquery"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:integration="http://www.springframework.org/schema/integration"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/xquery"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/integration"
|
||||
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-2.2.xsd" />
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines the configuration elements for Spring
|
||||
Integration's Xquery support.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:complexType name="inputOutputEndpoint">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0"
|
||||
maxOccurs="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
<xsd:attribute name="input-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="output-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:attributeGroup name="xquery-executor-common-attributes">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The common attributes that would be used for all
|
||||
the xquery components
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="xq-datasource" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to the XQDataSource that will be
|
||||
provided by the user to
|
||||
execute the provided XQuery. If none is
|
||||
provided, then the default
|
||||
implementation will be used.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="xquery-file-resource" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The classpath or the file system resource path to
|
||||
the file containing
|
||||
the
|
||||
xquery, typically .xq file. This attribute is
|
||||
mutually exclusive with the
|
||||
xquery attribute and the xquery
|
||||
subelement
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="xquery" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The String representing the XQuery that needs to
|
||||
be executed. Either
|
||||
this attribute or the xquery sub element needs
|
||||
to be provided.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="converter" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify the Converter to use when converting
|
||||
payloads prior to evaluation.
|
||||
The DefaultXmlPayloadConverter is used
|
||||
if this reference is not
|
||||
provided, and it
|
||||
should be sufficient in
|
||||
most cases since it can convert from Node,
|
||||
Document, Source,
|
||||
File,
|
||||
and String typed payloads. If you need to extend beyond the
|
||||
capabilities of
|
||||
that default implementation, then an upstream
|
||||
Transformer is probably a
|
||||
better option
|
||||
than providing a reference to
|
||||
a custom implementation of this strategy
|
||||
here.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.xml.XmlPayloadConverter" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
|
||||
|
||||
<xsd:complexType name="XQueryParameterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The subelement of the xquery based component that
|
||||
will be used to
|
||||
specify the
|
||||
parameters for the xquery
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The mandatory attribute that will be used to
|
||||
specify the name of the
|
||||
XQuery parameter
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="value" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The attribute that will be used to specify the
|
||||
static value to be used
|
||||
for the named
|
||||
parameter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ref" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
This attribute, mutually exclusive with value and
|
||||
expression that is
|
||||
used to specify
|
||||
reference to some other bean in
|
||||
the application context.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expression" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The attribute mutually exclusive with ref and
|
||||
value attribute, this
|
||||
will be
|
||||
used to provide the expression that
|
||||
would be evaluated on the incoming
|
||||
message
|
||||
to derive the value of the
|
||||
header.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="xquery" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The element that will be the sub element of all
|
||||
the XQuery components.
|
||||
It will be used to provide the XQuery string
|
||||
to these XQuery
|
||||
components.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="xquery-parameter" type="XQueryParameterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
One or more xquery-parameter elements will be used
|
||||
to specify the
|
||||
names and one of the three attributes used to derive
|
||||
the
|
||||
value of the parameter
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="mapping" type="integration:mappingValueChannelType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
If the values returned by the XQuery Expression
|
||||
do not represent the channel names themselves, additional
|
||||
mappings can be specified using the "mapping" sub-element.
|
||||
|
||||
For example if the '/request/responders' expression
|
||||
results in two values: 'responderA' and 'responderB',
|
||||
but you don't want to couple the responder names
|
||||
to channel names you may provide additional mappings
|
||||
such as:
|
||||
|
||||
<int-xml:mapping value="responderA" channel="channelA"/>
|
||||
<int-xml:mapping value="responderB" channel="channelB"/>
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="XQueryRouterType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="integration:abstractRouterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0"
|
||||
maxOccurs="1" />
|
||||
<xsd:element ref="xquery" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element ref="xquery-parameter" minOccurs="0"
|
||||
maxOccurs="unbounded" />
|
||||
<xsd:element ref="mapping" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="integration:topLevelRouterAttributeGroup" />
|
||||
<xsd:attributeGroup ref="xquery-executor-common-attributes" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="XQueryTransformerType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The type definition for the XQuery router
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="inputOutputEndpoint">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="xquery" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element ref="xquery-parameter" minOccurs="0"
|
||||
maxOccurs="unbounded" />
|
||||
<xsd:element ref="mapping" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="xquery-executor-common-attributes" />
|
||||
<xsd:attribute name="format-output" type="xsd:boolean"
|
||||
default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
This attribute, only valid for a transformer is
|
||||
used to configure the
|
||||
property that instructs the component to
|
||||
format the output xml if
|
||||
one is produced by the transformer after
|
||||
XQuery transformation. By default
|
||||
the output is not formatted.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="result-type" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The expected type of the result after
|
||||
transformation of the
|
||||
input payload. The value is the fully
|
||||
qualified name of the class
|
||||
The default value assumed in
|
||||
java.lang.String.
|
||||
If a class is provided using this attribute
|
||||
which is other than
|
||||
java.lang.String, java.lang.Number,
|
||||
java.lang.Boolean or
|
||||
org.w3c.dom.Node,
|
||||
then you need to have a
|
||||
mapper registered using the mapping child
|
||||
element.
|
||||
If a
|
||||
transformation to any other type is needed and you
|
||||
dont want to
|
||||
provide
|
||||
the mapping child element, then provide a
|
||||
reference to the
|
||||
xquery-result-mapper attribute.
|
||||
This attribute is
|
||||
mutually
|
||||
exclusive to the xquery-result-mapper attribute.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute name="xquery-result-mapper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
This attribute allows the user to provide
|
||||
mapper instance that would be
|
||||
used to map the result of the XQuery
|
||||
executed to a desired target type of the transformer.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="xquery-router" type="XQueryRouterType" />
|
||||
<xsd:element name="xquery-transformer" type="XQueryTransformerType" />
|
||||
|
||||
</xsd:schema>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 579 B |
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import org.springframework.integration.xml.XmlPayloadConverter;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Dummy Xml payload converter class that would be used for parser tests
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class DummyXmlPayloadConverter implements XmlPayloadConverter {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.xml.XmlPayloadConverter#convertToDocument(java.lang.Object)
|
||||
*/
|
||||
public Document convertToDocument(Object object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.xml.XmlPayloadConverter#convertToNode(java.lang.Object)
|
||||
*/
|
||||
public Node convertToNode(Object object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.xml.XmlPayloadConverter#convertToSource(java.lang.Object)
|
||||
*/
|
||||
public Source convertToSource(Object object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.xquery.XQDataSource;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import net.sf.saxon.xqj.SaxonXQDataSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.xml.XmlPayloadConverter;
|
||||
import org.springframework.integration.xquery.DummyXmlPayloadConverter;
|
||||
import org.springframework.integration.xquery.router.XQueryRouter;
|
||||
import org.springframework.integration.xquery.support.XQueryParameter;
|
||||
|
||||
|
||||
/**
|
||||
* The test case for the XQuery router parser
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryRouterParserTests {
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
private EventDrivenConsumer consumer;
|
||||
|
||||
|
||||
@Test
|
||||
public void routerOne() {
|
||||
setUp("xqueryRouterOne");
|
||||
XQueryRouter router = TestUtils.getPropertyValue(consumer, "handler", XQueryRouter.class);
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(router, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(SaxonXQDataSource.class,
|
||||
TestUtils.getPropertyValue(router, "executor.xqDataSource", XQDataSource.class).getClass());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, XQueryParameter> params =
|
||||
TestUtils.getPropertyValue(router, "executor.xQueryParameterMap",Map.class);
|
||||
Assert.assertEquals(2, params.size());
|
||||
Assert.assertTrue(params.containsKey("name"));
|
||||
Assert.assertTrue(params.containsKey("class"));
|
||||
XQueryParameter param = params.get("name");
|
||||
Assert.assertEquals("name", param.getParameterName());
|
||||
Assert.assertEquals("headers['name']",
|
||||
TestUtils.getPropertyValue(param, "messageProcessor.expression.expression",String.class));
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routerTwo() {
|
||||
setUp("xqueryRouterTwo");
|
||||
XQueryRouter router = TestUtils.getPropertyValue(consumer, "handler", XQueryRouter.class);
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(router, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(DummyXQDataSource.class,
|
||||
TestUtils.getPropertyValue(router, "executor.xqDataSource", XQDataSource.class).getClass());
|
||||
Assert.assertEquals(DummyXmlPayloadConverter.class,
|
||||
TestUtils.getPropertyValue(router,"executor.converter",XmlPayloadConverter.class).getClass());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, XQueryParameter> params =
|
||||
TestUtils.getPropertyValue(router, "executor.xQueryParameterMap",Map.class);
|
||||
Assert.assertEquals(1, params.size());
|
||||
Assert.assertTrue(params.containsKey("name"));
|
||||
XQueryParameter param = params.get("name");
|
||||
Assert.assertEquals("name", param.getParameterName());
|
||||
Assert.assertEquals("name",
|
||||
TestUtils.getPropertyValue(param, "parameterValue",String.class));
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routerThree() {
|
||||
setUp("xqueryRouterThree");
|
||||
XQueryRouter router = TestUtils.getPropertyValue(consumer, "handler", XQueryRouter.class);
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(router, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(ClassPathResource.class, TestUtils.getPropertyValue(router, "executor.xQueryFileResource",Resource.class).getClass());
|
||||
destroy();
|
||||
}
|
||||
|
||||
private void setUp(String beanName) {
|
||||
ctx = new ClassPathXmlApplicationContext("XQueryRouterParserTests-context.xml",XQueryRouterParserTests.class);
|
||||
consumer = ctx.getBean(beanName, EventDrivenConsumer.class);
|
||||
}
|
||||
|
||||
|
||||
public void destroy() {
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
public static class DummyXQDataSource extends SaxonXQDataSource {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.xquery.XQDataSource;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import net.sf.saxon.xqj.SaxonXQDataSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.transformer.Transformer;
|
||||
import org.springframework.integration.xml.XmlPayloadConverter;
|
||||
import org.springframework.integration.xquery.DummyXmlPayloadConverter;
|
||||
import org.springframework.integration.xquery.support.XQueryParameter;
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.springframework.integration.xquery.transformer.XQueryTransformer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* The test class for XQuery Transformer parser
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class XQueryTransformerParserTests {
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
private EventDrivenConsumer consumer;
|
||||
|
||||
@Test
|
||||
public void transformerOne() {
|
||||
setUp("xqueryTransformerOne");
|
||||
Transformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", Transformer.class);
|
||||
Assert.assertEquals(XQueryTransformer.class, transformer.getClass());
|
||||
Assert.assertEquals(String.class, TestUtils.getPropertyValue(transformer, "resultType", Class.class));
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(transformer, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(SaxonXQDataSource.class,
|
||||
TestUtils.getPropertyValue(transformer, "executor.xqDataSource", XQDataSource.class).getClass());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, XQueryParameter> params =
|
||||
TestUtils.getPropertyValue(transformer, "executor.xQueryParameterMap",Map.class);
|
||||
Assert.assertEquals(2, params.size());
|
||||
Assert.assertTrue(params.containsKey("name"));
|
||||
Assert.assertTrue(params.containsKey("class"));
|
||||
XQueryParameter param = params.get("name");
|
||||
Assert.assertEquals("name", param.getParameterName());
|
||||
Assert.assertEquals("headers['name']",
|
||||
TestUtils.getPropertyValue(param, "messageProcessor.expression.expression",String.class));
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transformerTwo() {
|
||||
setUp("xqueryTransformerTwo");
|
||||
XQueryTransformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", XQueryTransformer.class);
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(transformer, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(DummyXQDataSource.class,
|
||||
TestUtils.getPropertyValue(transformer, "executor.xqDataSource", XQDataSource.class).getClass());
|
||||
Assert.assertEquals(DummyXmlPayloadConverter.class,
|
||||
TestUtils.getPropertyValue(transformer,"executor.converter",XmlPayloadConverter.class).getClass());
|
||||
Assert.assertEquals(true, TestUtils.getPropertyValue(transformer, "executor.formatOutput",Boolean.class).booleanValue());
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void transformerThree() {
|
||||
setUp("xqueryTransformerThree");
|
||||
XQueryTransformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", XQueryTransformer.class);
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(transformer, "executor.xQuery", String.class));
|
||||
Assert.assertEquals(ClassPathResource.class, TestUtils.getPropertyValue(transformer, "executor.xQueryFileResource",Resource.class).getClass());
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void booleanTypeResult() {
|
||||
setUp("booleanResultTypeTransformer");
|
||||
XQueryTransformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", XQueryTransformer.class);
|
||||
Assert.assertEquals(Boolean.class, TestUtils.getPropertyValue(transformer, "resultType", Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringTypeResult() {
|
||||
setUp("stringResultTypeTransformer");
|
||||
XQueryTransformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", XQueryTransformer.class);
|
||||
Assert.assertEquals(String.class, TestUtils.getPropertyValue(transformer, "resultType", Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resultMapperProvided() {
|
||||
setUp("customXQueryResultMapper");
|
||||
XQueryTransformer transformer = TestUtils.getPropertyValue(consumer, "handler.transformer", XQueryTransformer.class);
|
||||
Assert.assertEquals(DummyXQueryResultMapper.class, TestUtils.getPropertyValue(transformer, "resultMapper", XQueryResultMapper.class).getClass());
|
||||
}
|
||||
|
||||
|
||||
private void setUp(String beanName) {
|
||||
ctx = new ClassPathXmlApplicationContext("XQueryTransformerParserTests-context.xml",XQueryTransformerParserTests.class);
|
||||
consumer = ctx.getBean(beanName, EventDrivenConsumer.class);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
public static class DummyXQDataSource extends SaxonXQDataSource {
|
||||
|
||||
}
|
||||
|
||||
public static class DummyXQueryResultMapper implements XQueryResultMapper<String> {
|
||||
|
||||
public List<String> mapResults(XQResultSequence result) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.xquery.XQDataSource;
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.xquery.support.AbstractXQueryResultMapper;
|
||||
import org.springframework.integration.xquery.support.BooleanResultMapper;
|
||||
import org.springframework.integration.xquery.support.NodeResultMapper;
|
||||
import org.springframework.integration.xquery.support.NumberResultMapper;
|
||||
import org.springframework.integration.xquery.support.StringResultMapper;
|
||||
import org.springframework.integration.xquery.support.XQueryParameter;
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The base test class for the XQueryExecutor tests
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractXQueryExecutorTests {
|
||||
|
||||
|
||||
private final static String EXT_VARIABLE_XQUERY =
|
||||
"declare variable $name as xs:string external;" +
|
||||
"declare variable $class as xs:int external;" +
|
||||
" for $student in /mappings/students/student," +
|
||||
" $subject in /mappings/subjects/subject " +
|
||||
"where $student/@id = $subject/students/studentId " +
|
||||
"and $student/name = $name " +
|
||||
"and $student/class = $class " +
|
||||
"return $subject/name/text()";
|
||||
|
||||
private final String xmlString = "<person active=\"true\">" +
|
||||
"<name>Mike</name>" +
|
||||
"<age>29</age>" +
|
||||
"</person>";
|
||||
|
||||
|
||||
/**
|
||||
* Test if default created result mappers are appropriately instantiated
|
||||
*/
|
||||
@Test
|
||||
public void initializeDefaultMappers() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map executorMap = TestUtils.getPropertyValue(executor, "resultMappers", Map.class);
|
||||
Assert.assertNotNull(executorMap);
|
||||
Assert.assertEquals(4, executorMap.size());
|
||||
Assert.assertEquals(StringResultMapper.class, executorMap.get(String.class).getClass());
|
||||
Assert.assertEquals(BooleanResultMapper.class, executorMap.get(Boolean.class).getClass());
|
||||
Assert.assertEquals(NumberResultMapper.class, executorMap.get(Number.class).getClass());
|
||||
Assert.assertEquals(NodeResultMapper.class, executorMap.get(Node.class).getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests of the registered mappers take priority over the defaults
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Test
|
||||
public void registerCustomMappers() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello'");
|
||||
Map map = new HashMap();
|
||||
map.put(MyCustomClass.class, new XQueryResultMapper<MyCustomClass>() {
|
||||
public List<MyCustomClass> mapResults(XQResultSequence result) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
});
|
||||
map.put(Node.class, new CustomNodeMapper());
|
||||
executor.setResultMappers(map);
|
||||
executor.afterPropertiesSet();
|
||||
Map executorMap = TestUtils.getPropertyValue(executor, "resultMappers", Map.class);
|
||||
Assert.assertNotNull(executorMap);
|
||||
Assert.assertEquals(5, executorMap.size());
|
||||
Assert.assertEquals(StringResultMapper.class, executorMap.get(String.class).getClass());
|
||||
Assert.assertEquals(BooleanResultMapper.class, executorMap.get(Boolean.class).getClass());
|
||||
Assert.assertEquals(NumberResultMapper.class, executorMap.get(Number.class).getClass());
|
||||
Assert.assertEquals(CustomNodeMapper.class, executorMap.get(Node.class).getClass());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to execute the result passing an unmapped class
|
||||
*/
|
||||
@Test
|
||||
public void executeForUnknownClassType() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
try {
|
||||
executor.execute(MessageBuilder.withPayload("").build(), MyCustomClass.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("No Result mapper found for the type org.springframework.integration.xquery.core.AbstractXQueryExecutorTests$MyCustomClass",
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
protected abstract XQueryExecutor getExecutor();
|
||||
|
||||
/**
|
||||
* Test with null message
|
||||
*/
|
||||
@Test
|
||||
public void withNullMessage() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
try {
|
||||
executor.execute(null, String.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Non null message expected", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeWithStringForNonLeaf() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery(".//person");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> names = executor.executeForString(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executeWithBooleanForNonLeaf() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//person");
|
||||
executor.afterPropertiesSet();
|
||||
List<Boolean> names = executor.executeForBoolean(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
Assert.assertTrue(names.contains(Boolean.FALSE));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void executeWithNumberForNonLeaf() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//person");
|
||||
executor.afterPropertiesSet();
|
||||
@SuppressWarnings("unused")
|
||||
List<Number> names;
|
||||
try {
|
||||
names = executor.executeForNumber(MessageBuilder.withPayload(xmlString).build());
|
||||
} catch (MessagingException e) {
|
||||
Assert.assertEquals(NumberFormatException.class,e.getCause().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case to execute the XQuery and return a {@link List} of {@link String}
|
||||
*/
|
||||
@Test
|
||||
public void executeWithString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery(".//person/name/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> names = executor.executeForString(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
Assert.assertTrue(names.contains("Mike"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case to execute the XQuery and return a {@link List} of {@link Boolean}
|
||||
*/
|
||||
@Test
|
||||
public void executeWithBoolean() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//person/@active");
|
||||
executor.afterPropertiesSet();
|
||||
List<Boolean> names = executor.executeForBoolean(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
Assert.assertTrue(names.contains(Boolean.TRUE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case to execute the XQuery and return a {@link List} of {@link Number}
|
||||
*/
|
||||
@Test
|
||||
public void executeWithNumber() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//person/age/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> names = executor.executeForNumber(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
Assert.assertTrue(names.contains(Long.valueOf(29)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test case to execute the XQuery and return a {@link List} of {@link Node}
|
||||
*/
|
||||
@Test
|
||||
public void executeWithNode() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//person");
|
||||
executor.afterPropertiesSet();
|
||||
List<Node> names = executor.executeForNode(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertNotNull(names);
|
||||
Assert.assertEquals(1, names.size());
|
||||
Assert.assertEquals("person",names.get(0).getLocalName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test with null message
|
||||
*/
|
||||
@Test
|
||||
public void withNullType() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
try {
|
||||
executor.execute(MessageBuilder.withPayload("").build(),(Class<?>) null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Non null type expected", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes the case where the router has no parameters but the query expects parameters
|
||||
*/
|
||||
@Test
|
||||
public void noParametersProvided() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery(EXT_VARIABLE_XQUERY);
|
||||
try {
|
||||
executor.afterPropertiesSet();
|
||||
} catch (MessagingException e) {
|
||||
Assert.assertEquals("Expecting 2 parameters in the xquery, but none provided to the router", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the case where parameters are provided, but some or all of the parameters are missing
|
||||
*/
|
||||
@Test
|
||||
public void fewParametersProvided() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery(EXT_VARIABLE_XQUERY);
|
||||
executor.addXQueryParameter(new XQueryParameter("class",Integer.valueOf(3)));
|
||||
try {
|
||||
executor.afterPropertiesSet();
|
||||
} catch (MessagingException e) {
|
||||
Assert.assertEquals("Missing parameter(s) [$name]", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets null XQuery, should get an exception
|
||||
*/
|
||||
@Test
|
||||
public void setNullXQuery() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
try {
|
||||
executor.setXQuery(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null XQuery", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the XQuery file resource and then the xquery
|
||||
*/
|
||||
@Test
|
||||
public void setResourceAndXQuery() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
Resource res = new ClassPathResource("/org/springframework/integration/xquery/XQuery.xq");
|
||||
Assert.assertTrue(res.exists());
|
||||
executor.setXQueryFileResource(res);
|
||||
try {
|
||||
executor.setXQuery("'Hello World'");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Only one of XQuery resource file or XQuery may be specified", e.getMessage());
|
||||
}
|
||||
Assert.assertNull(TestUtils.getPropertyValue(executor, "xQuery"));
|
||||
executor.addXQueryParameter(new XQueryParameter("name", "headers['studentName']"));
|
||||
executor.addXQueryParameter(new XQueryParameter("class", Integer.valueOf(1)));
|
||||
executor.afterPropertiesSet();
|
||||
Assert.assertNotNull(TestUtils.getPropertyValue(executor, "xQuery",String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the router without setting the xquery
|
||||
*/
|
||||
@Test
|
||||
public void withoutXQuery() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
try {
|
||||
executor.afterPropertiesSet();
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("One of XQuery or the XQuery resource is mandatory", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Sets the XQuery and then the resource
|
||||
*/
|
||||
@Test
|
||||
public void setXQueryAndResource() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
Resource res = new ClassPathResource("org/springframework/integration/xquery/XQuery.xq");
|
||||
Assert.assertTrue(res.exists());
|
||||
executor.setXQuery("'Hello World'");
|
||||
try {
|
||||
executor.setXQueryFileResource(res);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Only one of XQuery resource file or XQuery may be specified", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Sets a null {@link XQDataSource} instance
|
||||
*/
|
||||
@Test
|
||||
public void setNullXQataSource() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
try {
|
||||
executor.setXQDataSource(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null instance of the XQDatasource", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the router with valid xml payload. The values returned will be the
|
||||
* text content of the node, if the node is a text or attribute type
|
||||
*/
|
||||
@Test
|
||||
public void withValidPayload() {
|
||||
withValidPayloadInternal(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the router with valid xml payload. The values returned will be the
|
||||
* {@link Node}, irrespective of the type of the node
|
||||
*/
|
||||
@Test
|
||||
public void withValidPayload2() {
|
||||
withValidPayloadInternal(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void withValidPayloadInternal(boolean extractNodeText) {
|
||||
File file = new File("./src/test/resources/org/springframework/integration/xquery/SubjectMapping.xml");
|
||||
Message<File> message = MessageBuilder.withPayload(file)
|
||||
.setHeader("studentName", "Jughead")
|
||||
.build();
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery(EXT_VARIABLE_XQUERY);
|
||||
executor.addXQueryParameter(new XQueryParameter("name", "headers['studentName']"));
|
||||
executor.addXQueryParameter(new XQueryParameter("class", Integer.valueOf(1)));
|
||||
executor.afterPropertiesSet();
|
||||
List<Object> subjects;
|
||||
if(extractNodeText) {
|
||||
subjects = new ArrayList<Object>(executor.executeForString(message));
|
||||
}
|
||||
else {
|
||||
subjects = new ArrayList<Object>(executor.executeForNode(message));
|
||||
}
|
||||
Assert.assertNotNull(subjects);
|
||||
Assert.assertEquals(2, subjects.size());
|
||||
if(extractNodeText) {
|
||||
Assert.assertEquals(String.class, subjects.get(0).getClass());
|
||||
Assert.assertTrue(subjects.contains("Cooking"));
|
||||
Assert.assertTrue(subjects.contains("Math"));
|
||||
}
|
||||
else {
|
||||
Assert.assertTrue(Node.class.isAssignableFrom(subjects.get(0).getClass()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with a query that will generate a numeric value and we get the result as {@link Number}
|
||||
*/
|
||||
@Test
|
||||
public void withNumericExpression() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("2 + 2");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.get(0).intValue() == 4);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*Tests a query that will generate a decimal value and we get the result as a {@link Number}
|
||||
*/
|
||||
@Test
|
||||
public void withDecimalExpression() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("2.0 + 2.1");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Double.valueOf(4.1)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the XQuery that gives a boolean value and get the value as a Boolean
|
||||
*/
|
||||
@Test
|
||||
public void withBooleanResult() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("1 = 1");
|
||||
executor.afterPropertiesSet();
|
||||
List<Boolean> result = executor.executeForBoolean(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Boolean.TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a string value and we want the result to be a string value
|
||||
*/
|
||||
@Test
|
||||
public void getTextString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> result = executor.executeForString(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains("Hello World"));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a boolean value and we want the result to be a string value
|
||||
*/
|
||||
@Test
|
||||
public void getBooleanAsTextString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("1 = 2");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> result = executor.executeForString(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains("false"));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a text value in the node and we want the result to be a string value
|
||||
*/
|
||||
@Test
|
||||
public void getTextNodeAsString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//test/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> result = executor.executeForString(MessageBuilder.withPayload("<test>Some Value</test>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains("Some Value"));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a text value in the node and we want the result to be a Boolean
|
||||
*/
|
||||
@Test
|
||||
public void getTextNodeAsBoolean() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//test/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<Boolean> result = executor.executeForBoolean(MessageBuilder.withPayload("<test>Some Value</test>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Boolean.FALSE));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a text value in the node and we want the result to be a Long
|
||||
*/
|
||||
@Test
|
||||
public void getTextNodeAsLong() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//number/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<number>1</number>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Long.valueOf(1)));
|
||||
}
|
||||
|
||||
/**
|
||||
*The XQuery gives a text value in the node and we want the result to be a Long
|
||||
*/
|
||||
@Test
|
||||
public void getTextNodeAsDouble() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("//number/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<number>1.1</number>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Double.valueOf(1.1)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests by using a String that is a non decimal number and we get the value as a {@link Number}
|
||||
*/
|
||||
@Test
|
||||
public void withNonDecimalStringExpression() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setResultMappers(Collections.singletonMap(Number.class,
|
||||
(XQueryResultMapper<Number>)new NumberResultMapper()));
|
||||
executor.setXQuery("'4'");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Long.valueOf(4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests by using a String that is a decimal number and we get the value as a {@link Number}
|
||||
*/
|
||||
@Test
|
||||
public void withDecimalStringExpression() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setResultMappers(Collections.singletonMap(Number.class,
|
||||
(XQueryResultMapper<Number>)new NumberResultMapper()));
|
||||
executor.setXQuery("'4.1'");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Double.valueOf(4.1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests by getting the Integer value and getting the result as {@link String}
|
||||
*/
|
||||
@Test
|
||||
public void getIntegerAsString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("4");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> result = executor.executeForString(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains("4"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Uses a decimal value and gets the result as {@link String}
|
||||
*/
|
||||
@Test
|
||||
public void getDecimalAsString() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setXQuery("4.1");
|
||||
executor.afterPropertiesSet();
|
||||
List<String> result = executor.executeForString(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains("4.1"));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void getCurrentDate() {
|
||||
// XQueryExecutor executor = new XQueryExecutor();
|
||||
// executor.setXQuery("current-date()");
|
||||
// executor.afterPropertiesSet();
|
||||
// executor.executeForString(MessageBuilder.withPayload("<test/>").build());
|
||||
// }
|
||||
|
||||
|
||||
@Test
|
||||
public void withStringExpression2() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setResultMappers(Collections.singletonMap(Number.class,
|
||||
(XQueryResultMapper<Number>)new NumberResultMapper()));
|
||||
executor.setXQuery("/person/age/text()");
|
||||
executor.afterPropertiesSet();
|
||||
List<Number> result = executor.executeForNumber(MessageBuilder.withPayload(xmlString).build());
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(Long.valueOf(29)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withFormatingFlag() {
|
||||
XQueryExecutor executor = getExecutor();
|
||||
executor.setFormatOutput(true);
|
||||
executor.setXQuery("'Hello World'");
|
||||
executor.afterPropertiesSet();
|
||||
//should not fail
|
||||
executor.executeForString(MessageBuilder.withPayload("<dummy/>").build());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class<Object>, XQueryResultMapper<Object>> mappers = TestUtils.getPropertyValue(executor, "resultMappers", Map.class);
|
||||
for(Object val:mappers.values()) {
|
||||
if(val instanceof AbstractXQueryResultMapper) {
|
||||
Assert.assertEquals(true,
|
||||
TestUtils.getPropertyValue(val, "formatOutput", Boolean.class).booleanValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class MyCustomClass {}
|
||||
private class CustomNodeMapper implements XQueryResultMapper<Node> {
|
||||
public List<Node> mapResults(XQResultSequence result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.core;
|
||||
|
||||
|
||||
/**
|
||||
* The test class that uses the saxon's implementation in {@link XQueryExecutor}
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class SaxonXQueryExecutorTests extends AbstractXQueryExecutorTests {
|
||||
|
||||
|
||||
@Override
|
||||
protected XQueryExecutor getExecutor() {
|
||||
//use the default one that uses Saxon's implementation
|
||||
XQueryExecutor executor = new XQueryExecutor();
|
||||
return executor;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.core;
|
||||
|
||||
import javax.xml.xquery.XQDataSource;
|
||||
import javax.xml.xquery.XQException;
|
||||
|
||||
import net.xqj.sedna.SednaXQDataSource;
|
||||
|
||||
/**
|
||||
* The Test class that uses {@link SednaXQDataSource} in {@link XQueryExecutor}
|
||||
*
|
||||
* This test is intentionally excluded from being executed by surefire as it will
|
||||
* fail if the Sedna database is not up and running
|
||||
*
|
||||
* To run this test we need to have the Sedna XML Database up and running.
|
||||
* Visit {@link http://xqj.net/sedna/} for more details about Sedna.
|
||||
*
|
||||
* Once the Sedna xml database is downloaded and extracted the you will find
|
||||
* various executables in the bin directory, do the following to start it and create
|
||||
* a new database called 'test'
|
||||
*
|
||||
* 1. Start the governer by executing se_gov
|
||||
* 2. Create a new database called 'test' by executing se_cdb test
|
||||
* 3. Start the newly created database by running se_sm test. If the database was already
|
||||
* created, you can skip the step 2 and execute this step directly.
|
||||
*
|
||||
* Once the database is up and running, you can execute the below test case.
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class SednaXQueryExecutorTests extends AbstractXQueryExecutorTests {
|
||||
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Gets an instance of SednaXQDataSource for the tests.
|
||||
*
|
||||
*/
|
||||
protected XQueryExecutor getExecutor() {
|
||||
XQueryExecutor executor = new XQueryExecutor();
|
||||
XQDataSource ds;
|
||||
try {
|
||||
ds = new SednaXQDataSource();
|
||||
ds.setProperty("serverName", "localhost");
|
||||
ds.setProperty("databaseName", "test");
|
||||
} catch (XQException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
executor.setXQDataSource(ds);
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.router;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.xquery.core.XQueryExecutor;
|
||||
|
||||
|
||||
/**
|
||||
* The Test class for the XQuery router
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryRouterTests {
|
||||
|
||||
private static final String STUDENT_XML = "<students>" +
|
||||
"<student>" +
|
||||
"<name>Name1</name>" +
|
||||
"<age>21</age>" +
|
||||
"</student>" +
|
||||
"<student>" +
|
||||
"<name>Name2</name>" +
|
||||
"<age>22</age>" +
|
||||
"</student>" +
|
||||
"</students>";
|
||||
|
||||
/**
|
||||
* Tests the executor without seting the XQueryExecutor's instance
|
||||
*/
|
||||
@Test
|
||||
public void withoutExecutor() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
try {
|
||||
router.afterPropertiesSet();
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("No XQueryExecutor instance provided", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries setting the executor instance of the {@link XQueryRouter} to null.
|
||||
*/
|
||||
@Test
|
||||
public void setNullExecutor() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
try {
|
||||
router.setExecutor(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null implementation of the executor", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel keys for the given XQuery expression
|
||||
*/
|
||||
@Test
|
||||
public void getChannelKeys() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
router.setExecutor(getExecutor("//test/text()"));
|
||||
router.afterPropertiesSet();
|
||||
List<Object> keys=
|
||||
router.getChannelKeys(MessageBuilder.withPayload("<test>Test</test>").build());
|
||||
Assert.assertNotNull(keys);
|
||||
Assert.assertEquals(1, keys.size());
|
||||
Assert.assertTrue(keys.contains("Test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultResultType() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
router.setExecutor(getExecutor("'Hello'"));
|
||||
router.afterPropertiesSet();
|
||||
Assert.assertEquals(String.class,
|
||||
TestUtils.getPropertyValue(router, "resultType", Class.class));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getChannelKeysAsStrings() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
router.setExecutor(getExecutor("/students/student/name/text()"));
|
||||
router.afterPropertiesSet();
|
||||
List<Object> keys = router.getChannelKeys(MessageBuilder.withPayload(STUDENT_XML).build());
|
||||
Assert.assertEquals(2, keys.size());
|
||||
Assert.assertTrue(keys.contains("Name1"));
|
||||
Assert.assertTrue(keys.contains("Name2"));
|
||||
}
|
||||
|
||||
/**
|
||||
* The method demonstrates the conversion of a Numeric type to a String with get
|
||||
* channel keys method.
|
||||
*/
|
||||
@Test
|
||||
public void getChannelKeysAsStrings2() {
|
||||
XQueryRouter router = new XQueryRouter();
|
||||
router.setExecutor(getExecutor("/students/student/age/text()"));
|
||||
router.afterPropertiesSet();
|
||||
List<Object> keys = router.getChannelKeys(MessageBuilder.withPayload(STUDENT_XML).build());
|
||||
Assert.assertEquals(2, keys.size());
|
||||
Assert.assertTrue(keys.contains("21"));
|
||||
Assert.assertTrue(keys.contains("22"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private XQueryExecutor getExecutor(String xQuery) {
|
||||
XQueryExecutor executor = new XQueryExecutor();
|
||||
executor.setXQuery(xQuery);
|
||||
executor.afterPropertiesSet();
|
||||
return executor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
/**
|
||||
* The test class for {@link XQueryParameter} class
|
||||
*
|
||||
* @author Amol Nayak
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryParameterTests {
|
||||
|
||||
/**
|
||||
* Sets a null parameter name, should throw an exception
|
||||
*/
|
||||
@Test
|
||||
public void setNullParameterName() {
|
||||
try {
|
||||
@SuppressWarnings("unused")
|
||||
XQueryParameter param = new XQueryParameter(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Non null non empty String value expected for parameter name", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a null parameter name, should throw an exception
|
||||
*/
|
||||
@Test
|
||||
public void setEmptyParameterName() {
|
||||
try {
|
||||
@SuppressWarnings("unused")
|
||||
XQueryParameter param = new XQueryParameter("");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Non null non empty String value expected for parameter name", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the valid parameter name
|
||||
*/
|
||||
@Test
|
||||
public void setValidParameterName() {
|
||||
XQueryParameter param = new XQueryParameter("testName");
|
||||
Assert.assertEquals("testName", param.getParameterName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets both the expression then the parameter value, should throw an exception
|
||||
*/
|
||||
@Test
|
||||
public void setParameterExpressionThenValue() {
|
||||
XQueryParameter param = new XQueryParameter("testParameter");
|
||||
param.setExpression("headers['someHeader']");
|
||||
try {
|
||||
param.setParameterValue("Some Value");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("The parameter value and expression are mutually " +
|
||||
"exclusive, parameter expression already set", e.getMessage());
|
||||
}
|
||||
Assert.assertEquals(false, TestUtils.getPropertyValue(param,"isValueSet", Boolean.class).booleanValue());
|
||||
Assert.assertEquals("headers['someHeader']",
|
||||
TestUtils.getPropertyValue(param, "messageProcessor.expression.expression",String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both the value then the parameter expression, should throw an exception
|
||||
*/
|
||||
@Test
|
||||
public void setParameterValueThenExpression() {
|
||||
XQueryParameter param = new XQueryParameter("testParameter");
|
||||
param.setParameterValue("Some Value");
|
||||
try {
|
||||
param.setExpression("headers['someHeader']");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("The parameter value and expression are mutually exclusive" +
|
||||
", parameter value already set", e.getMessage());
|
||||
}
|
||||
Assert.assertEquals(true, TestUtils.getPropertyValue(param,"isValueSet", Boolean.class).booleanValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter name and its value from the constructor
|
||||
*/
|
||||
@Test
|
||||
public void setParameterValueInConstructor() {
|
||||
XQueryParameter param = new XQueryParameter("testName", (Object)"testValue");
|
||||
Assert.assertEquals(true, TestUtils.getPropertyValue(param, "isValueSet",Boolean.class).booleanValue());
|
||||
Assert.assertEquals("testName", param.getParameterName());
|
||||
Assert.assertEquals("testValue", TestUtils.getPropertyValue(param, "parameterValue", String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter value from the constructor
|
||||
*/
|
||||
@Test
|
||||
public void setParameterExpressionInConstructor() {
|
||||
XQueryParameter param = new XQueryParameter("testName", "headers['someHeader']");
|
||||
Assert.assertEquals(false, TestUtils.getPropertyValue(param, "isValueSet",Boolean.class).booleanValue());
|
||||
Assert.assertEquals("testName", param.getParameterName());
|
||||
Assert.assertEquals("headers['someHeader']", TestUtils.getPropertyValue(param, "expression", String.class));
|
||||
Assert.assertEquals("headers['someHeader']",
|
||||
TestUtils.getPropertyValue(param, "messageProcessor.expression.expression",String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expression string twice, should throw an exception
|
||||
*/
|
||||
@Test
|
||||
public void setExpressionTwice() {
|
||||
XQueryParameter param = new XQueryParameter("paramName");
|
||||
param.setExpression("headers['headerValue']");
|
||||
try {
|
||||
param.setExpression("headers['headerV']");
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Expression string is already set once, cannot reset it", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the parameter to get the static value set
|
||||
*/
|
||||
@Test
|
||||
public void executeForStaticValue() {
|
||||
XQueryParameter param = new XQueryParameter("paramName", Integer.valueOf(10));
|
||||
Object value = param.evaluate(null);
|
||||
Assert.assertEquals(value, Integer.valueOf(10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an expression to get the return values
|
||||
*/
|
||||
@Test
|
||||
public void executeExpressionValue() {
|
||||
XQueryParameter param = new XQueryParameter("paramName","headers['numbers'].?[#this > 5]");
|
||||
List<Integer> numbers = Arrays.asList(1,3,4,2,5,6,7);
|
||||
Message<String> message = MessageBuilder.withPayload("")
|
||||
.setHeader("numbers", numbers)
|
||||
.build();
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Integer> coll = (Collection<Integer>)param.evaluate(message);
|
||||
Assert.assertEquals(2, coll.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.xquery.transformer;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.xquery.XQResultSequence;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.xquery.core.XQueryExecutor;
|
||||
import org.springframework.integration.xquery.support.XQueryResultMapper;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The Test class for the {@link XQueryTransformer} class
|
||||
*
|
||||
* @author Amol Nayak
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public class XQueryTransformerTests {
|
||||
|
||||
@Test
|
||||
public void withNoExecutor() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.afterPropertiesSet();
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("No XQueryExecutor instance provided", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withNullExecutor() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null XQueryExecutor instance", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNoMapperAndResultType() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.afterPropertiesSet();
|
||||
Assert.assertEquals(String.class, TestUtils.getPropertyValue(transformer, "resultType",Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withStringResultType() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.setResultType(String.class);
|
||||
transformer.afterPropertiesSet();
|
||||
Assert.assertEquals(String.class, TestUtils.getPropertyValue(transformer, "resultType",Class.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withNumberResultType() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.setResultType(Number.class);
|
||||
transformer.afterPropertiesSet();
|
||||
Assert.assertEquals(Number.class, TestUtils.getPropertyValue(transformer, "resultType",Class.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void withBooleanResultType() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.setResultType(Boolean.class);
|
||||
transformer.afterPropertiesSet();
|
||||
Assert.assertEquals(Boolean.class, TestUtils.getPropertyValue(transformer, "resultType",Class.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withNodeResultType() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.setResultType(Node.class);
|
||||
transformer.afterPropertiesSet();
|
||||
Assert.assertEquals(Node.class, TestUtils.getPropertyValue(transformer, "resultType",Class.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withUnknownResultType() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("//hello"));
|
||||
transformer.setResultType(getClass());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Valid values for the result type class is String, Boolean, Number or Node, " +
|
||||
"for any other type, provide a custom implementation of XQueryResultMapper", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFirstTypeThenMapper() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setResultType(String.class);
|
||||
transformer.setResultMapper(new DummyXQueryResultMapper());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Only one of the result mapper of the resultType can be set", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFirstMapperThenType() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setResultMapper(new DummyXQueryResultMapper());
|
||||
transformer.setResultType(String.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Only one of the result mapper of the resultType can be set", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNullMapper() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setResultMapper(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null value for the result mapper", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNullType() {
|
||||
try {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setResultType(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertEquals("Provide a non null value for the result type", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeForString() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("'Hello World!'"));
|
||||
transformer.afterPropertiesSet();
|
||||
try {
|
||||
Object result = transformer.doTransform(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertNotNull(result);
|
||||
Assert.assertEquals("Hello World!", result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.assertTrue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeForInteger() {
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
transformer.setExecutor(getExecutor("10 + 12"));
|
||||
transformer.setResultType(Number.class);
|
||||
transformer.afterPropertiesSet();
|
||||
try {
|
||||
Object result = transformer.doTransform(MessageBuilder.withPayload("<test/>").build());
|
||||
Assert.assertNotNull(result);
|
||||
Assert.assertEquals(BigInteger.valueOf(22), result);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.assertTrue(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void personTransformer() {
|
||||
String inputXml = "<employees>" +
|
||||
"<employee id=\"1\" name=\"Emp1\" dept=\"Dep1\"/>" +
|
||||
"<employee id=\"2\" name=\"Emp2\" dept=\"Dep2\"/>" +
|
||||
"</employees>";
|
||||
|
||||
XQueryTransformer transformer = new XQueryTransformer();
|
||||
XQueryExecutor executor = new XQueryExecutor();
|
||||
executor.setXQueryFileResource(
|
||||
new ClassPathResource("org/springframework/integration/xquery/XQueryTransform.xq"));
|
||||
executor.setFormatOutput(true);
|
||||
executor.afterPropertiesSet();
|
||||
transformer.setExecutor(executor);
|
||||
transformer.afterPropertiesSet();
|
||||
try {
|
||||
Object transformed = transformer.doTransform(MessageBuilder.withPayload(inputXml).build());
|
||||
Assert.assertNotNull(transformed);
|
||||
System.out.println(transformed);
|
||||
} catch (Exception e) {
|
||||
Assert.assertTrue("Caught Exception while transformation, " + e.getMessage(),false);
|
||||
}
|
||||
}
|
||||
|
||||
private class DummyXQueryResultMapper implements XQueryResultMapper<Integer> {
|
||||
|
||||
public List<Integer> mapResults(XQResultSequence result) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO: Refactor, Can have a common superclass for all XQuery components
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private XQueryExecutor getExecutor(String xQuery) {
|
||||
XQueryExecutor executor = new XQueryExecutor();
|
||||
executor.setXQuery(xQuery);
|
||||
executor.afterPropertiesSet();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<mappings>
|
||||
<students>
|
||||
<student id="1">
|
||||
<name>Jughead</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
<student id="2">
|
||||
<name>Archie</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
<student id="3">
|
||||
<name>Reggie</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
<student id="4">
|
||||
<name>Moose</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
<student id="5">
|
||||
<name>Betty</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
<student id="6">
|
||||
<name>Veronica</name>
|
||||
<class>1</class>
|
||||
</student>
|
||||
</students>
|
||||
<subjects>
|
||||
<subject>
|
||||
<name>Math</name>
|
||||
<students>
|
||||
<studentId>1</studentId>
|
||||
<studentId>2</studentId>
|
||||
<studentId>5</studentId>
|
||||
</students>
|
||||
</subject>
|
||||
<subject>
|
||||
<name>Physics</name>
|
||||
<students>
|
||||
<studentId>2</studentId>
|
||||
<studentId>5</studentId>
|
||||
<studentId>6</studentId>
|
||||
</students>
|
||||
</subject>
|
||||
<subject>
|
||||
<name>Chemistry</name>
|
||||
<students>
|
||||
<studentId>3</studentId>
|
||||
<studentId>4</studentId>
|
||||
<studentId>6</studentId>
|
||||
</students>
|
||||
</subject>
|
||||
<subject>
|
||||
<name>Cooking</name>
|
||||
<students>
|
||||
<studentId>1</studentId>
|
||||
<studentId>5</studentId>
|
||||
</students>
|
||||
</subject>
|
||||
</subjects>
|
||||
</mappings>
|
||||
@@ -0,0 +1,8 @@
|
||||
declare variable $name as xs:string external;
|
||||
declare variable $class as xs:int external;
|
||||
for $student in /mappings/students/student,
|
||||
$subject in /mappings/subjects/subject
|
||||
where $student/@id = $subject/students/studentId
|
||||
and $student/name = $name
|
||||
and $student/class = $class
|
||||
return $subject/name/text()
|
||||
@@ -0,0 +1,11 @@
|
||||
<employees>
|
||||
{
|
||||
for $emp in /employees/employee
|
||||
return
|
||||
<employee>
|
||||
<id>{string($emp/@id)}</id>
|
||||
<name>{string($emp/@name)}</name>
|
||||
<department>{string($emp/@name)}</department>
|
||||
</employee>
|
||||
}
|
||||
</employees>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-xquery="http://www.springframework.org/schema/integration/xquery"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/xquery http://www.springframework.org/schema/integration/xquery/spring-integration-xquery.xsd">
|
||||
|
||||
<int-xquery:xquery-router id="xqueryRouterOne" input-channel="xpathRouterOne">
|
||||
<int-xquery:xquery>
|
||||
<![CDATA[
|
||||
declare variable $name as xs:string external;
|
||||
declare variable $class as xs:int external;
|
||||
for $student in /mappings/students/student,
|
||||
$subject in /mappings/subjects/subject
|
||||
where $student/@id = $subject/students/studentId
|
||||
and $student/name = $name
|
||||
and $student/class = $class
|
||||
return $subject/name/text()
|
||||
]]>
|
||||
</int-xquery:xquery>
|
||||
<int-xquery:xquery-parameter name="name" expression="headers['name']"/>
|
||||
<int-xquery:xquery-parameter name="class" value="1"/>
|
||||
</int-xquery:xquery-router>
|
||||
|
||||
<int-xquery:xquery-router id="xqueryRouterTwo"
|
||||
input-channel="xpathRouterOne"
|
||||
xquery="'Hello World'"
|
||||
converter="converter"
|
||||
xq-datasource="xqDs">
|
||||
<int-xquery:xquery-parameter name="name" ref="name"/>
|
||||
</int-xquery:xquery-router>
|
||||
|
||||
<int-xquery:xquery-router id="xqueryRouterThree"
|
||||
input-channel="xpathRouterOne"
|
||||
xquery-file-resource="classpath:org/springframework/integration/xquery/XQuery.xq"
|
||||
converter="converter"
|
||||
xq-datasource="xqDs">
|
||||
<int-xquery:xquery-parameter name="name" expression="headers['name']"/>
|
||||
<int-xquery:xquery-parameter name="class" value="1"/>
|
||||
</int-xquery:xquery-router>
|
||||
|
||||
|
||||
|
||||
<int-xquery:xquery-router id="xqueryRouterFour"
|
||||
input-channel="xpathRouterOne"
|
||||
xquery-file-resource="org/springframework/integration/xquery/XQuery.xq"
|
||||
converter="converter"
|
||||
xq-datasource="xqDs">
|
||||
<int-xquery:xquery-parameter name="name" expression="headers['name']"/>
|
||||
<int-xquery:xquery-parameter name="class" value="1"/>
|
||||
</int-xquery:xquery-router>
|
||||
|
||||
<bean id="converter" class="org.springframework.integration.xquery.DummyXmlPayloadConverter"/>
|
||||
|
||||
<bean id="xqDs" class="org.springframework.integration.xquery.config.xml.XQueryRouterParserTests.DummyXQDataSource"/>
|
||||
|
||||
<bean id="name" class="java.lang.String">
|
||||
<constructor-arg index="0" value="name"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-xquery="http://www.springframework.org/schema/integration/xquery"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/xquery http://www.springframework.org/schema/integration/xquery/spring-integration-xquery.xsd">
|
||||
|
||||
<int:channel id="output"/>
|
||||
|
||||
<int-xquery:xquery-transformer id="xqueryTransformerOne"
|
||||
input-channel="xqueryTransformerInOne"
|
||||
output-channel="output">
|
||||
<int-xquery:xquery>
|
||||
<![CDATA[
|
||||
declare variable $name as xs:string external;
|
||||
declare variable $class as xs:int external;
|
||||
for $student in /mappings/students/student,
|
||||
$subject in /mappings/subjects/subject
|
||||
where $student/@id = $subject/students/studentId
|
||||
and $student/name = $name
|
||||
and $student/class = $class
|
||||
return $subject/name/text()
|
||||
]]>
|
||||
</int-xquery:xquery>
|
||||
<int-xquery:xquery-parameter name="name" expression="headers['name']"/>
|
||||
<int-xquery:xquery-parameter name="class" value="1"/>
|
||||
</int-xquery:xquery-transformer>
|
||||
|
||||
<int-xquery:xquery-transformer id="xqueryTransformerTwo"
|
||||
input-channel="xqueryTransformerOutTwo"
|
||||
output-channel="output"
|
||||
xquery="'Hello World'"
|
||||
converter="converter"
|
||||
xq-datasource="xqDs"
|
||||
format-output="true">
|
||||
</int-xquery:xquery-transformer>
|
||||
|
||||
<int-xquery:xquery-transformer id="xqueryTransformerThree"
|
||||
input-channel="xqueryTransformerIPThree"
|
||||
output-channel="output"
|
||||
xquery-file-resource="classpath:org/springframework/integration/xquery/XQueryTransform.xq"
|
||||
converter="converter"
|
||||
xq-datasource="xqDs">
|
||||
</int-xquery:xquery-transformer>
|
||||
|
||||
<int-xquery:xquery-transformer id="booleanResultTypeTransformer"
|
||||
input-channel="booleanResultTypeTransformerIP"
|
||||
output-channel="output"
|
||||
result-type="java.lang.Boolean"
|
||||
xquery-file-resource="classpath:org/springframework/integration/xquery/XQueryTransform.xq"
|
||||
xq-datasource="xqDs"/>
|
||||
|
||||
<int-xquery:xquery-transformer id="stringResultTypeTransformer"
|
||||
input-channel="stringResultTypeTransformerIP"
|
||||
output-channel="output"
|
||||
result-type="string"
|
||||
xquery-file-resource="classpath:org/springframework/integration/xquery/XQueryTransform.xq"
|
||||
xq-datasource="xqDs"/>
|
||||
|
||||
<int-xquery:xquery-transformer id="customXQueryResultMapper"
|
||||
input-channel="stringResultTypeTransformerIP"
|
||||
output-channel="output"
|
||||
xquery-result-mapper="xqueryResultMapper"
|
||||
xquery-file-resource="classpath:org/springframework/integration/xquery/XQueryTransform.xq"
|
||||
xq-datasource="xqDs"/>
|
||||
|
||||
<bean id="converter" class="org.springframework.integration.xquery.DummyXmlPayloadConverter"/>
|
||||
|
||||
<bean id="xqDs" class="org.springframework.integration.xquery.config.xml.XQueryTransformerParserTests.DummyXQDataSource"/>
|
||||
|
||||
<bean id="xqueryResultMapper" class="org.springframework.integration.xquery.config.xml.XQueryTransformerParserTests.DummyXQueryResultMapper"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user