This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 35d1e9f6144 CAMEL-20127: Add messageAs function to simple language (#12081) 35d1e9f6144 is described below commit 35d1e9f61442d899a6e361ff47815fe427105f13 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sun Nov 19 14:02:41 2023 +0100 CAMEL-20127: Add messageAs function to simple language (#12081) --- .../modules/languages/pages/csimple-language.adoc | 3 ++ .../modules/languages/pages/simple-language.adoc | 7 ++++ .../camel/language/csimple/CSimpleHelper.java | 4 ++ .../language/simple/SimpleExpressionBuilder.java | 46 ++++++++++++++++++++++ .../simple/ast/SimpleFunctionExpression.java | 32 ++++++++++++++- .../camel/language/simple/MyAttachmentMessage.java | 40 +++++++++++++++++++ .../apache/camel/language/simple/SimpleTest.java | 16 ++++++++ .../camel/support/builder/ExpressionBuilder.java | 39 ++++++++++++++++++ 8 files changed, 186 insertions(+), 1 deletion(-) diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/csimple-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/csimple-language.adoc index 35722af2c4e..aa704512956 100644 --- a/core/camel-core-languages/src/main/docs/modules/languages/pages/csimple-language.adoc +++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/csimple-language.adoc @@ -60,6 +60,9 @@ and then converting the exchange property to the given type determined by its cl |mandatoryExchangePropertyAsIndex(_key_, _type_, _index_) |Type | To be used for collecting an exchange property from an existing `Collection`, `Map` or array (lookup by the index) and then converting the exchange property to the given type determined by its classname. Expects the exchange property to be not null. +|messageAs(_type_) |Type |Converts the message to the given type determined by its +classname. The converted message can be null. + |======================================================================= For example given the following simple expression: diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc index c24d453eec4..b4825370a24 100644 --- a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc +++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc @@ -134,6 +134,13 @@ classname |exchangeProperty.foo.*OGNL* |Object |refer to the foo property on the exchange and invoke its value using a Camel OGNL expression. +|messageAs(_type_) |Type |Converts the message to the given type determined by its +classname. The converted message can be null. + +|messageAs(_type_).*OGNL* |Object |Converts the message to the given type determined by its +classname and then invoke methods using a Camel OGNL expression. The +converted message can be null. + |sys.foo |String |refer to the JVM system property |sysenv.foo |String |refer to the system environment variable diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java index 4b5c4cd81cb..4bf6cdd5f09 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/csimple/CSimpleHelper.java @@ -66,6 +66,10 @@ public final class CSimpleHelper { private CSimpleHelper() { } + public static <T> T messageAs(Exchange exchange, Class<T> type) { + return exchange.getMessage(type); + } + public static <T> T bodyAs(Message message, Class<T> type) { return message.getBody(type); } diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java index 020d6209fec..b39e822adee 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java @@ -697,6 +697,52 @@ public final class SimpleExpressionBuilder { }; } + /** + * Returns the expression for the message converted to the given type and invoking methods on the converted message + * defined in a simple OGNL notation + */ + public static Expression messageOgnlExpression(final String name, final String ognl) { + return new ExpressionAdapter() { + private ClassResolver classResolver; + private Expression exp; + private Language bean; + + @Override + public Object evaluate(Exchange exchange) { + String text = exp.evaluate(exchange, String.class); + Class<?> type; + try { + type = classResolver.resolveMandatoryClass(text); + } catch (ClassNotFoundException e) { + throw CamelExecutionException.wrapCamelExecutionException(exchange, e); + } + Object msg = exchange.getMessage(type); + if (msg != null) { + // ognl is able to evaluate method name if it contains nested functions + // so we should not eager evaluate ognl as a string + Expression ognlExp = bean.createExpression(null, new Object[] { msg, ognl }); + ognlExp.init(exchange.getContext()); + return ognlExp.evaluate(exchange, Object.class); + } else { + return null; + } + } + + @Override + public void init(CamelContext context) { + classResolver = context.getClassResolver(); + exp = ExpressionBuilder.simpleExpression(name); + exp.init(context); + bean = context.resolveLanguage("bean"); + } + + @Override + public String toString() { + return "messageOgnlAs[" + name + "](" + ognl + ")"; + } + }; + } + /** * Returns the expression for the exchanges inbound message body converted to the given type and invoking methods on * the converted body defined in a simple OGNL notation diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java index 20995e04116..f6b659fb725 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java @@ -77,6 +77,12 @@ public class SimpleFunctionExpression extends LiteralExpression { return answer; } + // message first + answer = createSimpleExpressionMessage(camelContext, function, strict); + if (answer != null) { + return answer; + } + // body and headers first answer = createSimpleExpressionBodyOrHeader(function, strict); if (answer != null) { @@ -303,6 +309,31 @@ public class SimpleFunctionExpression extends LiteralExpression { } } + private Expression createSimpleExpressionMessage(CamelContext camelContext, String function, boolean strict) { + // messageAs + String remainder = ifStartsWithReturnRemainder("messageAs(", function); + if (remainder != null) { + String type = StringHelper.before(remainder, ")"); + if (type == null) { + throw new SimpleParserException("Valid syntax: ${messageAs(type)} was: " + function, token.getIndex()); + } + type = StringHelper.removeQuotes(type); + remainder = StringHelper.after(remainder, ")"); + + if (ObjectHelper.isNotEmpty(remainder)) { + boolean invalid = OgnlHelper.isInvalidValidOgnlExpression(remainder); + if (invalid) { + throw new SimpleParserException("Valid syntax: ${messageAs(type).OGNL} was: " + function, token.getIndex()); + } + return SimpleExpressionBuilder.messageOgnlExpression(type, remainder); + } else { + return ExpressionBuilder.messageExpression(type); + } + } + + return null; + } + private Expression createSimpleExpressionBodyOrHeader(String function, boolean strict) { // bodyAs String remainder = ifStartsWithReturnRemainder("bodyAs(", function); @@ -322,7 +353,6 @@ public class SimpleFunctionExpression extends LiteralExpression { } else { return ExpressionBuilder.bodyExpression(type); } - } // mandatoryBodyAs remainder = ifStartsWithReturnRemainder("mandatoryBodyAs(", function); diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/MyAttachmentMessage.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/MyAttachmentMessage.java new file mode 100644 index 00000000000..3e5096daff3 --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/MyAttachmentMessage.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.language.simple; + +import org.apache.camel.Exchange; +import org.apache.camel.support.DefaultMessage; + +public class MyAttachmentMessage extends DefaultMessage { + + public MyAttachmentMessage(Exchange exchange) { + super(exchange); + } + + public boolean hasAttachments() { + return true; + } + + public String toString() { + return "MyAttachmentMessage"; + } + + public int size() { + return 42; + } + +} diff --git a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java index b61f2c2e500..63503dc95e1 100644 --- a/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java @@ -748,6 +748,21 @@ public class SimpleTest extends LanguageTestSupport { assertEquals("Just testing", out.getMessage()); } + @Test + public void testMessageAs() throws Exception { + // should be false as message is default + assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments}", false); + assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments}", false); + + MyAttachmentMessage msg = new MyAttachmentMessage(exchange); + msg.setBody("<hello id='m123'>world!</hello>"); + exchange.setMessage(msg); + + assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).hasAttachments}", true); + assertPredicate("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage)?.hasAttachments}", true); + assertExpression("${messageAs(org.apache.camel.language.simple.MyAttachmentMessage).size}", "42"); + } + @Test public void testBodyAs() throws Exception { assertExpression("${bodyAs(String)}", "<hello id='m123'>world!</hello>"); @@ -2254,4 +2269,5 @@ public class SimpleTest extends LanguageTestSupport { return new Object[] { "Hallo", "World", "!" }; } } + } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java index 115199271c5..f83b25ad901 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/builder/ExpressionBuilder.java @@ -1168,6 +1168,45 @@ public class ExpressionBuilder { return inMessageExpression(); } + /** + * Returns the expression for the message converted to the given type + */ + public static Expression messageExpression(final String name) { + return messageExpression(simpleExpression(name)); + } + + /** + * Returns the expression for the message converted to the given type + */ + public static Expression messageExpression(final Expression name) { + return new ExpressionAdapter() { + private ClassResolver classResolver; + + @Override + public Object evaluate(Exchange exchange) { + Class<?> type; + try { + String text = name.evaluate(exchange, String.class); + type = classResolver.resolveMandatoryClass(text); + } catch (ClassNotFoundException e) { + throw CamelExecutionException.wrapCamelExecutionException(exchange, e); + } + return exchange.getMessage(type); + } + + @Override + public void init(CamelContext context) { + name.init(context); + classResolver = context.getClassResolver(); + } + + @Override + public String toString() { + return "messageAs[" + name + "]"; + } + }; + } + /** * Returns a functional expression for the IN message */