diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java
index c886582979..377d1b87d1 100644
--- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java
@@ -29,6 +29,7 @@ public class IntegrationXmlNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("marshalling-transformer", new XmlMarshallingTransformerParser());
registerBeanDefinitionParser("unmarshalling-transformer", new XmlUnmarshallingTransformerParser());
registerBeanDefinitionParser("xslt-transformer", new XsltPayloadTransformerParser());
+ registerBeanDefinitionParser("xpath-router", new XPathRouterParser());
}
}
diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java
new file mode 100644
index 0000000000..7c116b7dd8
--- /dev/null
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2002-2007 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.xml.config;
+
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.integration.ConfigurationException;
+import org.springframework.integration.router.MultiChannelRouter;
+import org.springframework.integration.router.SingleChannelRouter;
+import org.springframework.integration.xml.router.XPathMultiChannelNameResolver;
+import org.springframework.integration.xml.router.XPathSingleChannelNameResolver;
+import org.springframework.util.StringUtils;
+import org.springframework.xml.xpath.XPathExpression;
+import org.springframework.xml.xpath.XPathExpressionFactory;
+import org.w3c.dom.Element;
+
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
+public class XPathRouterParser extends AbstractSingleBeanDefinitionParser {
+
+ @Override
+ protected boolean shouldGenerateId() {
+ return false;
+ }
+
+ @Override
+ protected boolean shouldGenerateIdAsFallback() {
+ return true;
+ }
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+
+ boolean multiChannel = Boolean.parseBoolean(element.getAttribute("multi-channel"));
+ boolean resolutionRequired = Boolean.parseBoolean(element.getAttribute("resolution-required"));
+ String xPathExpression = element.getAttribute("xpath-expression");
+ String xPathExpressionRef = element.getAttribute("xpath-expression-ref");
+ if ((StringUtils.hasText(xPathExpression) && StringUtils.hasText(xPathExpressionRef))
+ || (!StringUtils.hasText(xPathExpression) && !StringUtils.hasText(xPathExpressionRef))) {
+ throw new ConfigurationException("Exactl one of xpath-expression or xpath-expression-ref is required");
+ }
+
+ BeanDefinitionBuilder resolverDefinitionBuilder = null;
+ if (multiChannel) {
+ builder.getBeanDefinition().setBeanClass(MultiChannelRouter.class);
+ resolverDefinitionBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(XPathMultiChannelNameResolver.class);
+ }
+ else {
+ builder.getBeanDefinition().setBeanClass(SingleChannelRouter.class);
+ resolverDefinitionBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(XPathSingleChannelNameResolver.class);
+ }
+
+ if (StringUtils.hasText(xPathExpression)) {
+ XPathExpression expression = XPathExpressionFactory.createXPathExpression(xPathExpression);
+ resolverDefinitionBuilder.addConstructorArgValue(expression);
+ }
+ else {
+ resolverDefinitionBuilder.addConstructorArgReference(xPathExpressionRef);
+ }
+
+ builder.getBeanDefinition().getPropertyValues().addPropertyValue("resolutionRequired", resolutionRequired);
+ builder.getBeanDefinition().getPropertyValues().addPropertyValue("channelNameResolver",
+ resolverDefinitionBuilder.getBeanDefinition());
+ }
+
+}
diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd
index 41079bcf8b..1014a9d517 100644
--- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd
@@ -38,7 +38,7 @@
-
+
@@ -51,22 +51,46 @@
use="required" />
-
-
-
+
+
+
- Defines a XML unmarshalling transformer.
+ Defines a XML XSLT transformer.
-
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+ Defines a XPath router.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/AbstractXPathChannelNameResolver.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/AbstractXPathChannelNameResolver.java
index 94fd986c96..4d5ac85121 100644
--- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/AbstractXPathChannelNameResolver.java
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/AbstractXPathChannelNameResolver.java
@@ -20,6 +20,11 @@ import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessagingException;
import org.w3c.dom.Node;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class AbstractXPathChannelNameResolver {
protected Node extractNode(Message> message) {
diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathMultiChannelNameResolver.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathMultiChannelNameResolver.java
index 3f89de077e..3196b481f6 100644
--- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathMultiChannelNameResolver.java
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathMultiChannelNameResolver.java
@@ -26,36 +26,40 @@ import org.springframework.xml.xpath.XPathExpression;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class XPathMultiChannelNameResolver extends AbstractXPathChannelNameResolver implements MultiChannelNameResolver {
private final XPathExpression xPathExpression;
-
+
private NodeMapper nodeMapper = new TextContentNodeMapper();
-
- public XPathMultiChannelNameResolver(XPathExpression xPathExpression){
+
+ public XPathMultiChannelNameResolver(XPathExpression xPathExpression) {
Assert.notNull("XPAthExpression must be provided");
this.xPathExpression = xPathExpression;
}
-
- public void setNodeMapper(NodeMapper nodeMapper){
- Assert.notNull(nodeMapper,"NodeMapper can not be null");
+
+ public void setNodeMapper(NodeMapper nodeMapper) {
+ Assert.notNull(nodeMapper, "NodeMapper can not be null");
this.nodeMapper = nodeMapper;
}
-
+
@SuppressWarnings("unchecked")
public String[] resolve(Message> message) {
- Node node =extractNode(message);
+ Node node = extractNode(message);
List channelNamesList = xPathExpression.evaluate(node, nodeMapper);
- return (String[])channelNamesList.toArray(new String[channelNamesList.size()]);
+ return (String[]) channelNamesList.toArray(new String[channelNamesList.size()]);
}
-
- private static class TextContentNodeMapper implements NodeMapper{
+
+ private static class TextContentNodeMapper implements NodeMapper {
public Object mapNode(Node node, int nodeNum) throws DOMException {
return node.getTextContent();
}
-
+
}
-
}
diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathSingleChannelNameResolver.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathSingleChannelNameResolver.java
index 58eefb6f0c..29c449e703 100644
--- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathSingleChannelNameResolver.java
+++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/router/XPathSingleChannelNameResolver.java
@@ -17,27 +17,29 @@
package org.springframework.integration.xml.router;
import org.springframework.integration.message.Message;
-import org.springframework.integration.message.MessagingException;
import org.springframework.integration.router.ChannelNameResolver;
import org.springframework.util.Assert;
import org.springframework.xml.xpath.XPathExpression;
import org.w3c.dom.Node;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class XPathSingleChannelNameResolver extends AbstractXPathChannelNameResolver implements ChannelNameResolver {
private final XPathExpression xPathExpression;
-
-
- public XPathSingleChannelNameResolver(XPathExpression xPathExpression){
- Assert.notNull("XPAthExpression must be provided");
+
+ public XPathSingleChannelNameResolver(XPathExpression xPathExpression) {
+ Assert.notNull("XPathExpression must be provided");
this.xPathExpression = xPathExpression;
}
-
public String resolve(Message> message) {
Node node = extractNode(message);
+ System.out.println(xPathExpression.evaluateAsString(node));
return xPathExpression.evaluateAsString(node);
}
-
-
+
}
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathMultiChannelNameResolverTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathMultiChannelNameResolverTests.java
index 1a59697442..220e1a62bc 100644
--- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathMultiChannelNameResolverTests.java
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathMultiChannelNameResolverTests.java
@@ -28,38 +28,41 @@ import org.springframework.xml.xpath.XPathExpression;
import org.springframework.xml.xpath.XPathExpressionFactory;
import org.w3c.dom.Document;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class XPathMultiChannelNameResolverTests {
+ @SuppressWarnings("unchecked")
@Test
public void testSimpleSingleeAttribute() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
String[] channelNames = resolver.resolve(new GenericMessage(doc));
- assertEquals("Wrong number of channels returend",1,channelNames.length);
- assertEquals("Wrong channel name","one",channelNames[0]);
+ assertEquals("Wrong number of channels returend", 1, channelNames.length);
+ assertEquals("Wrong channel name", "one", channelNames[0]);
}
-
+
+ @SuppressWarnings("unchecked")
@Test
public void testMultipleNodeValues() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("bOnebTwo");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/book");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
String[] channelNames = resolver.resolve(new GenericMessage(doc));
- assertEquals("Wrong number of channels returend",2,channelNames.length);
- assertEquals("Wrong channel name","bOne",channelNames[0]);
- assertEquals("Wrong channel name","bTwo",channelNames[1]);
+ assertEquals("Wrong number of channels returend", 2, channelNames.length);
+ assertEquals("Wrong channel name", "bOne", channelNames[0]);
+ assertEquals("Wrong channel name", "bTwo", channelNames[1]);
}
-
- @Test(expected=MessagingException.class)
+ @Test(expected = MessagingException.class)
public void testNonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
resolver.resolve(new StringMessage("test"));
}
-
-
-
}
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathSingleChannelNameResolverTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathSingleChannelNameResolverTests.java
index fffd7b9d23..f121d9aaf7 100644
--- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathSingleChannelNameResolverTests.java
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/router/XPathSingleChannelNameResolverTests.java
@@ -28,26 +28,28 @@ import org.springframework.xml.xpath.XPathExpression;
import org.springframework.xml.xpath.XPathExpressionFactory;
import org.w3c.dom.Document;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class XPathSingleChannelNameResolverTests {
+ @SuppressWarnings("unchecked")
@Test
public void testSimpleDocType() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathSingleChannelNameResolver resolver = new XPathSingleChannelNameResolver(expression);
String channelName = resolver.resolve(new GenericMessage(doc));
- assertEquals("Wrong channel name","one",channelName);
+ assertEquals("Wrong channel name", "one", channelName);
}
-
- @Test(expected=MessagingException.class)
+ @Test(expected = MessagingException.class)
public void testNonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathSingleChannelNameResolver resolver = new XPathSingleChannelNameResolver(expression);
resolver.resolve(new StringMessage("test"));
}
-
-
-
}
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubMarshaller.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubMarshaller.java
index f6ca049357..580a812c0d 100644
--- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubMarshaller.java
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubMarshaller.java
@@ -26,6 +26,11 @@ import org.springframework.oxm.Marshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.xml.transform.StringSource;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class StubMarshaller implements Marshaller {
public void marshal(Object graph, Result result) throws XmlMappingException, IOException {
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubUnmarshaller.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubUnmarshaller.java
index a51c728280..9a5ee85d1f 100644
--- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubUnmarshaller.java
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/StubUnmarshaller.java
@@ -24,6 +24,11 @@ import javax.xml.transform.Source;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.XmlMappingException;
+/**
+ *
+ * @author Jonas Partner
+ *
+ */
public class StubUnmarshaller implements Unmarshaller {
public LinkedList sourcesPassed = new LinkedList();
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests-context.xml b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests-context.xml
new file mode 100644
index 0000000000..a85aacf7bb
--- /dev/null
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests-context.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests.java
new file mode 100644
index 0000000000..e2c9bd2faf
--- /dev/null
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XPathRouterParserTests.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2002-2007 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.xml.config;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.channel.MessageChannel;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.integration.xml.util.XmlTestUtil;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
+import org.w3c.dom.Document;
+
+
+@ContextConfiguration
+public class XPathRouterParserTests extends AbstractJUnit4SpringContextTests{
+
+ @Autowired @Qualifier("inputOne")
+ MessageChannel inputOne;
+
+ @Autowired @Qualifier("inputTwo")
+ MessageChannel inputTwo;
+
+
+ @Autowired @Qualifier("outputOne")
+ MessageChannel outputOne;
+
+
+ @Autowired @Qualifier("outputTwo")
+ MessageChannel outputTwo;
+
+ @Autowired @Qualifier("errors")
+ MessageChannel errors;
+
+
+
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputOne() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputOne");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputOne.send(docMessage);
+ GenericMessage received = (GenericMessage)outputOne.receive(1000);
+ assertNotNull("Did not recevie message from outputOne", received);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputTwo() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputTwo");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputOne.send(docMessage);
+ GenericMessage received = (GenericMessage)outputTwo.receive(1000);
+ assertNotNull("Did not recevie message from two", received);
+ }
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputThree() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputThree");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputOne.send(docMessage);
+ GenericMessage received = (GenericMessage)errors.receive(1000);
+ assertNotNull("Did not recevie message on errors", received);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputOneMulti() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputOne");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputTwo.send(docMessage);
+ GenericMessage received = (GenericMessage)outputOne.receive(1000);
+ assertNotNull("Did not recevie message from outputOne", received);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputOneAndTwoMulti() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputOneoutputTwo");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputTwo.send(docMessage);
+ GenericMessage received = (GenericMessage)outputTwo.receive(1000);
+ assertNotNull("Did not recevie message from two", received);
+ }
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testOutputThreeMulti() throws Exception{
+ Document doc =XmlTestUtil.getDocumentForString("outputThree");
+ GenericMessage docMessage = new GenericMessage(doc);
+ inputTwo.send(docMessage);
+ GenericMessage received = (GenericMessage) errors.receive(1000);
+ assertNotNull("Did not recevie message on errors", received);
+
+ }
+
+
+}
diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml
index 925c482e44..35c5d2968c 100644
--- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml
+++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml
@@ -5,12 +5,14 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration-xml http://www.springframework.org/schema/integration/spring-integration-xml-1.0.xsd">
-
-
-
-
-
-
-
+
+
+
+
+
+
+