INT-776 Refactored Transformer, Splitter, and Router parsers to avoid duplication while adding support for EL-based handlers.

This commit is contained in:
Mark Fisher
2009-08-28 19:39:45 +00:00
parent 56196bffe8
commit d1352a03b8
4 changed files with 123 additions and 111 deletions

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2002-2009 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.config.xml;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Base parser class for endpoints that delegate to a method invoker or
* expression evaluator when handling consumed Messages. These classes
* use a FactoryBean implementation to construct the actual endpoint
* instance.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
abstract class AbstractDelegatingConsumerEndpointParser extends AbstractConsumerEndpointParser {
@Override
protected final BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getFactoryBeanClassName());
BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
String ref = element.getAttribute(REF_ATTRIBUTE);
String expression = element.getAttribute(EXPRESSION_ATTRIBUTE);
boolean hasRef = StringUtils.hasText(ref);
boolean hasExpression = StringUtils.hasText(expression);
if (innerDefinition != null) {
if (hasRef || hasExpression) {
parserContext.getReaderContext().error(
"Neither 'ref' nor 'expression' are permitted when an inner bean (<bean/>) is configured.", element);
return null;
}
builder.addPropertyValue("targetObject", innerDefinition);
}
else if (hasRef) {
builder.addPropertyReference("targetObject", ref);
}
else if (hasExpression) {
builder.addPropertyValue("expression", expression);
}
else if (!this.hasDefaultOption()) {
parserContext.getReaderContext().error("Exactly one of the 'ref' attribute, 'expression' attribute, " +
"or inner bean (<bean/>) definition is required for this '" + element.getLocalName() + "' endpoint.",
element);
return null;
}
String method = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(method)) {
if (hasExpression) {
parserContext.getReaderContext().error(
"A 'method' attribute is not permitted when configuring an 'expression'.", element);
}
if (hasRef || innerDefinition != null) {
builder.addPropertyValue("targetMethodName", method);
}
else {
parserContext.getReaderContext().error("A 'method' attribute is only permitted when either " +
"a 'ref' or inner-bean definition is provided.", element);
}
}
this.postProcess(builder, element, parserContext);
return builder;
}
/**
* Subclasses may override this no-op method to provide additional configuration.
*/
void postProcess(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
}
abstract boolean hasDefaultOption();
abstract String getFactoryBeanClassName();
}

View File

@@ -18,7 +18,6 @@ package org.springframework.integration.config.xml;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
@@ -28,27 +27,21 @@ import org.springframework.util.StringUtils;
* Parser for the &lt;router/&gt; element.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class DefaultRouterParser extends AbstractRouterParser {
public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParser {
@Override
protected void parseRouter(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) {
BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
if (innerDefinition != null){
builder.addPropertyValue("targetObject", innerDefinition);
} else {
String ref = element.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(ref)) {
parserContext.getReaderContext().error("The '" + REF_ATTRIBUTE + "' attribute is required.", element);
}
builder.addPropertyReference("targetObject", ref);
}
if (StringUtils.hasText(element.getAttribute(METHOD_ATTRIBUTE))) {
String method = element.getAttribute(METHOD_ATTRIBUTE);
builder.addPropertyValue("targetMethodName", method);
}
String getFactoryBeanClassName() {
return IntegrationNamespaceUtils.BASE_PACKAGE + ".config.RouterFactoryBean";
}
@Override
boolean hasDefaultOption() {
return false;
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
String resolverBeanName = element.getAttribute("channel-resolver");
if (!StringUtils.hasText(resolverBeanName)) {
BeanDefinitionBuilder resolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(
@@ -57,6 +50,10 @@ public class DefaultRouterParser extends AbstractRouterParser {
resolverBuilder.getBeanDefinition(), parserContext.getRegistry());
}
builder.addPropertyReference("channelResolver", resolverBeanName);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "default-output-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "timeout");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "resolution-required");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-channel-name-resolution-failures");
}
}

View File

@@ -16,60 +16,21 @@
package org.springframework.integration.config.xml;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;splitter/&gt; element.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class SplitterParser extends AbstractConsumerEndpointParser {
public class SplitterParser extends AbstractDelegatingConsumerEndpointParser {
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".config.SplitterFactoryBean");
String getFactoryBeanClassName() {
return IntegrationNamespaceUtils.BASE_PACKAGE + ".config.SplitterFactoryBean";
}
BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
String ref = element.getAttribute(REF_ATTRIBUTE);
String expression = element.getAttribute(EXPRESSION_ATTRIBUTE);
boolean hasRef = StringUtils.hasText(ref);
boolean hasExpression = StringUtils.hasText(expression);
if (innerDefinition != null) {
if (hasRef || hasExpression) {
parserContext.getReaderContext().error(
"Neither 'ref' nor 'expression' are permitted when an inner bean (<bean/>) is configured.", element);
return null;
}
builder.addPropertyValue("targetObject", innerDefinition);
}
else if (hasRef) {
builder.addPropertyReference("targetObject", ref);
}
else if (hasExpression) {
builder.addPropertyValue("expression", expression);
}
else {
// will create a DefaultSplitter
return builder;
}
String method = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(method)) {
if (hasExpression) {
parserContext.getReaderContext().error(
"A 'method' attribute is not permitted when configuring an 'expression'.", element);
}
builder.addPropertyValue("targetMethodName", method);
}
return builder;
@Override
boolean hasDefaultOption() {
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -16,59 +16,21 @@
package org.springframework.integration.config.xml;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for the &lt;transformer/&gt; element.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class TransformerParser extends AbstractConsumerEndpointParser {
public class TransformerParser extends AbstractDelegatingConsumerEndpointParser {
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".config.TransformerFactoryBean");
String getFactoryBeanClassName() {
return IntegrationNamespaceUtils.BASE_PACKAGE + ".config.TransformerFactoryBean";
}
BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
String ref = element.getAttribute(REF_ATTRIBUTE);
String expression = element.getAttribute(EXPRESSION_ATTRIBUTE);
boolean hasRef = StringUtils.hasText(ref);
boolean hasExpression = StringUtils.hasText(expression);
if (innerDefinition != null) {
if (hasRef || hasExpression) {
parserContext.getReaderContext().error(
"Neither 'ref' nor 'expression' are permitted when an inner bean (<bean/>) is configured.", element);
return null;
}
builder.addPropertyValue("targetObject", innerDefinition);
}
else if (hasRef) {
builder.addPropertyReference("targetObject", ref);
}
else if (hasExpression) {
builder.addPropertyValue("expression", expression);
}
else {
parserContext.getReaderContext().error("Exactly one of the 'ref' attribute, 'expression' attribute, " +
"or inner bean (<bean/>) definition for this Transformer is required.", element);
return null;
}
String method = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(method)) {
if (hasExpression) {
parserContext.getReaderContext().error(
"A 'method' attribute is not permitted when configuring an 'expression'.", element);
}
builder.addPropertyValue("targetMethodName", method);
}
return builder;
@Override
boolean hasDefaultOption() {
return false;
}
}