From 21eefa90dcc47d63cb3a4bca51db768f0fb083a0 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 14 Oct 2008 17:39:14 +0000 Subject: [PATCH] Added namespace support for a MessageSelectorChain's Strategy (ALL, ANY, AT_LEAST_HALF, MORE_THAN_HALF), and added support for nesting elements (INT-308). --- .../config/xml/SelectorChainParser.java | 32 +++++++++- .../config/xml/spring-integration-1.0.xsd | 34 ++++++++--- .../config/SelectorChainParserTests.java | 60 +++++++++++++++++-- .../config/StubMessageSelector.java | 14 ++++- .../config/selectorChainParserTests.xml | 23 +++++++ 5 files changed, 145 insertions(+), 18 deletions(-) diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SelectorChainParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SelectorChainParser.java index 43eab36fda..36958793f1 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SelectorChainParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SelectorChainParser.java @@ -22,9 +22,14 @@ import org.w3c.dom.NodeList; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.selector.MessageSelectorChain; +import org.springframework.integration.selector.MessageSelectorChain.Strategy; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Parser for the <selector-chain/> element. @@ -38,14 +43,35 @@ public class SelectorChainParser extends AbstractSingleBeanDefinitionParser { return MessageSelectorChain.class; } + public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + Assert.hasText(element.getAttribute("id"), "id is required"); + this.parseSelectorChain(builder, element, parserContext); + } + @SuppressWarnings("unchecked") - public void doParse(Element element, BeanDefinitionBuilder builder) { + private void parseSelectorChain(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) { + String strategy = element.getAttribute("strategy"); + if (StringUtils.hasText(strategy)) { + builder.addPropertyValue("strategy", Strategy.valueOf(strategy)); + } ManagedList selectors = new ManagedList(); NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node child = childNodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE && "selector".equals(child.getLocalName())) { - selectors.add(new RuntimeBeanReference(((Element) child).getAttribute("ref"))); + if (child.getNodeType() == Node.ELEMENT_NODE) { + String nodeName = child.getLocalName(); + if ("selector".equals(nodeName)) { + String ref = ((Element) child).getAttribute("ref"); + selectors.add(new RuntimeBeanReference(ref)); + } + else if ("selector-chain".equals(nodeName)) { + BeanDefinitionBuilder nestedBuilder = + BeanDefinitionBuilder.genericBeanDefinition(MessageSelectorChain.class); + this.parseSelectorChain(nestedBuilder, (Element) child, parserContext); + String nestedBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName( + nestedBuilder.getBeanDefinition(), parserContext.getRegistry()); + selectors.add(new RuntimeBeanReference(nestedBeanName)); + } } } builder.addPropertyValue("selectors", selectors); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd index 6e4a854aa8..01192c72f1 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd @@ -146,7 +146,7 @@ - + @@ -192,8 +192,8 @@ - Base type for handler endpoint elements that accept Messages from an input-channel - and also produce Messages to be sent to an output-channel. + Base type for Message Endpoint elements that accept Messages from an input-channel + and also may produce reply Messages to be sent to an output-channel. @@ -206,7 +206,7 @@ - Base type for handler endpoint elements that accept Messages from an input-channel. + Base type for Message Endpoint elements that accept Messages from an input-channel. @@ -214,7 +214,7 @@ - + @@ -290,10 +290,26 @@ Defines a MessageSelector chain. - - - - + + + + + + + + + + + + + + + + + + diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/SelectorChainParserTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/config/SelectorChainParserTests.java index ed42b2e96d..e41cc02e53 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/SelectorChainParserTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/SelectorChainParserTests.java @@ -17,6 +17,7 @@ package org.springframework.integration.config; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.List; @@ -24,8 +25,10 @@ import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.message.StringMessage; import org.springframework.integration.selector.MessageSelector; import org.springframework.integration.selector.MessageSelectorChain; +import org.springframework.integration.selector.MessageSelectorChain.Strategy; /** * @author Mark Fisher @@ -33,18 +36,65 @@ import org.springframework.integration.selector.MessageSelectorChain; public class SelectorChainParserTests { @Test - @SuppressWarnings("unchecked") - public void testSelectorChain() { + public void selectorChain() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "selectorChainParserTests.xml", this.getClass()); MessageSelector selector1 = (MessageSelector) context.getBean("selector1"); MessageSelector selector2 = (MessageSelector) context.getBean("selector2"); MessageSelectorChain chain = (MessageSelectorChain) context.getBean("selectorChain"); - DirectFieldAccessor accessor = new DirectFieldAccessor(chain); - List selectors = (List) - accessor.getPropertyValue("selectors"); + List selectors = this.getSelectors(chain); + assertEquals(Strategy.ALL, this.getStrategy(chain)); assertEquals(selector1, selectors.get(0)); assertEquals(selector2, selectors.get(1)); + assertTrue(chain.accept(new StringMessage("test"))); + } + + @Test + public void nestedSelectorChain() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "selectorChainParserTests.xml", this.getClass()); + MessageSelector selector1 = (MessageSelector) context.getBean("selector1"); + MessageSelector selector2 = (MessageSelector) context.getBean("selector2"); + MessageSelector selector3 = (MessageSelector) context.getBean("selector3"); + MessageSelector selector4 = (MessageSelector) context.getBean("selector4"); + MessageSelector selector5 = (MessageSelector) context.getBean("selector5"); + MessageSelector selector6 = (MessageSelector) context.getBean("selector6"); + MessageSelectorChain chain1 = (MessageSelectorChain) context.getBean("nestedSelectorChain"); + assertEquals(Strategy.MORE_THAN_HALF, this.getStrategy(chain1)); + List selectorList1 = this.getSelectors(chain1); + assertEquals(selector1, selectorList1.get(0)); + assertTrue(selectorList1.get(1) instanceof MessageSelectorChain); + MessageSelectorChain chain2 = (MessageSelectorChain) selectorList1.get(1); + assertEquals(Strategy.ALL, this.getStrategy(chain2)); + List selectorList2 = this.getSelectors(chain2); + assertEquals(selector2, selectorList2.get(0)); + assertTrue(selectorList2.get(1) instanceof MessageSelectorChain); + MessageSelectorChain chain3 = (MessageSelectorChain) selectorList2.get(1); + assertEquals(Strategy.ANY, this.getStrategy(chain3)); + List selectorList3 = this.getSelectors(chain3); + assertEquals(selector3, selectorList3.get(0)); + assertEquals(selector4, selectorList3.get(1)); + assertEquals(selector5, selectorList2.get(2)); + assertTrue(selectorList1.get(2) instanceof MessageSelectorChain); + MessageSelectorChain chain4 = (MessageSelectorChain) selectorList1.get(2); + assertEquals(Strategy.AT_LEAST_HALF, this.getStrategy(chain4)); + List selectorList4 = this.getSelectors(chain4); + assertEquals(selector6, selectorList4.get(0)); + assertTrue(chain1.accept(new StringMessage("test1"))); + assertTrue(chain2.accept(new StringMessage("test2"))); + assertTrue(chain3.accept(new StringMessage("test3"))); + assertTrue(chain4.accept(new StringMessage("test4"))); + } + + + @SuppressWarnings("unchecked") + private List getSelectors(MessageSelectorChain chain) { + DirectFieldAccessor accessor = new DirectFieldAccessor(chain); + return (List) accessor.getPropertyValue("selectors"); + } + + private Strategy getStrategy(MessageSelectorChain chain) { + return (Strategy) new DirectFieldAccessor(chain).getPropertyValue("strategy"); } } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/StubMessageSelector.java b/org.springframework.integration/src/test/java/org/springframework/integration/config/StubMessageSelector.java index 9d005858da..7aec818886 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/StubMessageSelector.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/StubMessageSelector.java @@ -16,16 +16,28 @@ package org.springframework.integration.config; +import org.springframework.beans.factory.BeanNameAware; import org.springframework.integration.message.Message; import org.springframework.integration.selector.MessageSelector; /** * @author Mark Fisher */ -public class StubMessageSelector implements MessageSelector { +public class StubMessageSelector implements MessageSelector, BeanNameAware { + + private String beanName; + + + public void setBeanName(String beanName) { + this.beanName = beanName; + } public boolean accept(Message message) { return true; } + public String toString() { + return this.beanName; + } + } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/selectorChainParserTests.xml b/org.springframework.integration/src/test/java/org/springframework/integration/config/selectorChainParserTests.xml index 769e40f09c..2fed90c6e9 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/selectorChainParserTests.xml +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/selectorChainParserTests.xml @@ -12,8 +12,31 @@ + + + + + + + + + + + + + + + + + + + + + + +