diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/enricher/XPathHeaderEnricher.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/enricher/XPathHeaderEnricher.java new file mode 100644 index 0000000000..ea411bc697 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/enricher/XPathHeaderEnricher.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2008 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.enricher; + +import org.springframework.integration.core.Message; +import org.springframework.integration.message.MessageBuilder; +import org.springframework.integration.transformer.Transformer; +import org.springframework.integration.xml.DefaultXmlPayloadConverter; +import org.springframework.integration.xml.XmlPayloadConverter; +import org.springframework.integration.xml.xpath.XPathEvaluationType; +import org.springframework.util.StringUtils; +import org.springframework.xml.xpath.XPathExpression; +import org.w3c.dom.Node; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + + +/** + * Transformer implementation which evaluates XPath expressions against the message payload and inserts the + * result of the evaluation into the messsage header + * + * @author Jonas Partner + */ +public class XPathHeaderEnricher implements Transformer { + + private final Map expressionMap; + + private Map evaluationTypes; + + private XPathEvaluationType defaultEvaluationType = XPathEvaluationType.STRING_RESULT; + + private volatile boolean skipSettingNullResults = true; + + private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter(); + + + /** + * Create an instance of XPathHeaderEnricher using a map of the header name to the XPathExpression to evaluate + * All XpathExpressions are currently evaluated as returning Strings + * + * @param expressionMap + */ + public XPathHeaderEnricher(Map expressionMap) { + this.expressionMap = Collections.unmodifiableMap(expressionMap); + } + + public void setConverter(XmlPayloadConverter converter) { + this.converter = converter; + } + + public void setSkipSettingNullResults(boolean skipSettingNullResults) { + this.skipSettingNullResults = skipSettingNullResults; + } + + public void setEvaluationTypes(Map evaluationTypes) { + this.evaluationTypes = evaluationTypes; + } + + public void setDefaultEvaluationType(XPathEvaluationType defaultEvaluationType) { + this.defaultEvaluationType = defaultEvaluationType; + } + + public Message transform(Message message) { + MessageBuilder builder = MessageBuilder.fromMessage(message); + Node node = this.converter.convertToNode(message.getPayload()); + + Set keys = this.expressionMap.keySet(); + for (String key : keys) { + XPathExpression expression = this.expressionMap.get(key); + XPathEvaluationType evalType = this.defaultEvaluationType; + + if (this.evaluationTypes != null && this.evaluationTypes.containsKey(key)) { + evalType = this.evaluationTypes.get(key); + } + + setHeader(node, key, expression, evalType, builder); + } + return builder.build(); + } + + protected void setHeader(Node node, String headerName, XPathExpression expression, XPathEvaluationType evaluationType, MessageBuilder builder) { + Object result = evaluationType.evaluateXPath(expression, node); + + boolean nullOrEmptyString = (result == null || + (result instanceof String && !StringUtils.hasLength((String)result))); + + if (!nullOrEmptyString || !this.skipSettingNullResults) { + builder.setHeader(headerName, result); + } + } + +} diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java new file mode 100644 index 0000000000..ca3966e4d9 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java @@ -0,0 +1,33 @@ +package org.springframework.integration.xml.xpath; + +import org.springframework.xml.xpath.XPathExpression; +import org.w3c.dom.Node; + + +/** + * Enumeration of different types o XPath evaluation used to indicate the type of evaluation that should be carried out + * using a provided XPath expression + */ +public enum XPathEvaluationType { + + BOOLEAN_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsBoolean(node); + }}, + + STRING_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsString(node); + }}, + NUMBER_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNumber(node); + }}, + + NODE_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNode(node); + }}, + NODE_LIST_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNodeList(node); + }}; + + public abstract Object evaluateXPath(XPathExpression expression, Node node); + +} diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/enricher/XPathHeaderEnricherTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/enricher/XPathHeaderEnricherTests.java new file mode 100644 index 0000000000..4f5614ca9e --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/enricher/XPathHeaderEnricherTests.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2008 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.enricher; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.integration.core.Message; +import org.springframework.integration.core.MessageHeaders; +import org.springframework.integration.message.MessageBuilder; +import org.springframework.integration.xml.xpath.XPathEvaluationType; +import org.springframework.xml.xpath.XPathExpression; +import org.springframework.xml.xpath.XPathExpressionFactory; + +import java.util.HashMap; +import java.util.Map; + + +public class XPathHeaderEnricherTests { + + + + @Test + public void testSimpleStringEvaluation(){ + Map expressionMap = new HashMap(); + expressionMap.put("one", XPathExpressionFactory.createXPathExpression("/root/elementOne")); + expressionMap.put("two", XPathExpressionFactory.createXPathExpression("/root/elementTwo")); + String docAsString = "12"; + + XPathHeaderEnricher enricher = new XPathHeaderEnricher(expressionMap); + Message result = enricher.transform(MessageBuilder.withPayload(docAsString).build()); + + MessageHeaders headers = result.getHeaders(); + + assertEquals("Wrong value for element one expression", "1", headers.get("one")); + assertEquals("Wrong value for element two expression", "2", headers.get("two")); + } + + @Test + public void testDontSetNull(){ + Map expressionMap = new HashMap(); + expressionMap.put("two", XPathExpressionFactory.createXPathExpression("/root/elementTwo")); + String docAsString = "1"; + + XPathHeaderEnricher enricher = new XPathHeaderEnricher(expressionMap); + Message result = enricher.transform(MessageBuilder.withPayload(docAsString).build()); + + MessageHeaders headers = result.getHeaders(); + assertNull("value set for two when result was null",headers.get("two")); + } + + @Test + public void testSetNull(){ + Map expressionMap = new HashMap(); + expressionMap.put("two", XPathExpressionFactory.createXPathExpression("/root/elementTwo")); + String docAsString = "1"; + + XPathHeaderEnricher enricher = new XPathHeaderEnricher(expressionMap); + enricher.setSkipSettingNullResults(false); + Message result = enricher.transform(MessageBuilder.withPayload(docAsString).build()); + + MessageHeaders headers = result.getHeaders(); + assertEquals("no value set for two when result was null and skip null was false","" ,headers.get("two")); + } + + @Test + public void testSetNumberEvaluation(){ + Map expressionMap = new HashMap(); + expressionMap.put("one", XPathExpressionFactory.createXPathExpression("/root/elementOne")); + expressionMap.put("two", XPathExpressionFactory.createXPathExpression("/root/elementTwo")); + + Map evalTypeMap = new HashMap(); + evalTypeMap.put("two", XPathEvaluationType.NUMBER_RESULT); + String docAsString = "12"; + + XPathHeaderEnricher enricher = new XPathHeaderEnricher(expressionMap); + enricher.setEvaluationTypes(evalTypeMap); + Message result = enricher.transform(MessageBuilder.withPayload(docAsString).build()); + + MessageHeaders headers = result.getHeaders(); + + assertEquals("Wrong value for element one expression", "1", headers.get("one")); + assertEquals("Wrong value for element two expression", 2.0, headers.get("two")); + } + + + + + + + + +}