You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/12/06 12:42:33 UTC

(camel) branch main updated: CAMEL-20197: camel-catalog - Allow to provide options for validateLanguage

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 df19aec0091 CAMEL-20197: camel-catalog - Allow to provide options for validateLanguage
df19aec0091 is described below

commit df19aec009164ba821c60518651dfc5eda3aee7d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Dec 6 13:42:15 2023 +0100

    CAMEL-20197: camel-catalog - Allow to provide options for validateLanguage
---
 .../org/apache/camel/catalog/CamelCatalog.java     |  6 +++
 .../org/apache/camel/catalog/CamelCatalogTest.java |  5 ++
 .../camel/catalog/impl/AbstractCamelCatalog.java   | 24 ++++++++++
 .../org/apache/camel/util/ReflectionHelper.java    | 56 +++++++++++++++++++++-
 4 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
index 673ee0fdc89..3b5fefe5ac3 100644
--- a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
+++ b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
@@ -405,6 +405,9 @@ public interface CamelCatalog {
     /**
      * Parses and validates the language as a predicate
      * <p/>
+     * It is possible to specify language options as query parameters in the language parameter, such as
+     * jsonpath?unpackArray=true&allowEasyPredicate=false
+     *
      * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
      *
      * @param  classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for
@@ -418,6 +421,9 @@ public interface CamelCatalog {
     /**
      * Parses and validates the language as an expression
      * <p/>
+     * It is possible to specify language options as query parameters in the language parameter, such as
+     * jsonpath?unpackArray=true&allowEasyPredicate=false
+     *
      * <b>Important:</b> This requires having <tt>camel-core</tt> and the language dependencies on the classpath
      *
      * @param  classLoader a custom classloader to use for loading the language from the classpath, or <tt>null</tt> for
diff --git a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
index 9ac367295f4..f4725ca3afc 100644
--- a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
+++ b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
@@ -1089,6 +1089,11 @@ public class CamelCatalogTest {
         assertFalse(result.isSuccess());
         assertEquals("$.store.book[?(@.price ^^^ 10)]", result.getText());
         assertEquals("Expected character: )", result.getError());
+
+        // just to call via a configuration option
+        result = catalog.validateLanguageExpression(null, "jsonpath?unpackArray=true", "$.store.book[?(@.price < 10)]");
+        assertTrue(result.isSuccess());
+        assertEquals("$.store.book[?(@.price < 10)]", result.getText());
     }
 
     @Test
diff --git a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
index e9a316cfc81..5f4584431a7 100644
--- a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
+++ b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
@@ -54,6 +54,7 @@ import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.tooling.model.MainModel;
 import org.apache.camel.tooling.model.OtherModel;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ReflectionHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.URISupport;
 
@@ -1400,6 +1401,18 @@ public abstract class AbstractCamelCatalog {
 
         LanguageValidationResult answer = new LanguageValidationResult(text);
 
+        Map<String, Object> options = null;
+        if (language.contains("?")) {
+            String query = URISupport.extractQuery(language);
+            language = StringHelper.before(language, "?");
+            try {
+                options = URISupport.parseQuery(query);
+            } catch (Exception e) {
+                answer.setError("Cannot parse language options: " + query);
+                return answer;
+            }
+        }
+
         LanguageModel model = languageModel(language);
         if (model == null) {
             answer.setError("Unknown language " + language);
@@ -1419,6 +1432,17 @@ public abstract class AbstractCamelCatalog {
         } catch (Exception e) {
             // ignore
         }
+        // set options on the language
+        if (options != null) {
+            final Map<String, Object> fOptions = options;
+            final Object fInstance = instance;
+            ReflectionHelper.doWithFields(clazz, field -> {
+                Object value = fOptions.get(field.getName());
+                if (value != null) {
+                    ReflectionHelper.setField(field, fInstance, value);
+                }
+            });
+        }
 
         if (clazz != null && instance != null) {
             Throwable cause = null;
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java b/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java
index 719663f3f6f..649fca93bf2 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/ReflectionHelper.java
@@ -21,6 +21,8 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
 
+import javax.swing.text.Document;
+
 /**
  * Helper for working with reflection on classes.
  * <p/>
@@ -182,7 +184,59 @@ public final class ReflectionHelper {
             if (!Modifier.isPublic(f.getModifiers()) && !f.canAccess(instance)) {
                 f.setAccessible(true);
             }
-            f.set(instance, value);
+            // must use fine-grained for the correct type when setting a field value via reflection
+            Class<?> type = f.getType();
+            if (boolean.class == type || Boolean.class == type) {
+                boolean val;
+                if (value instanceof Boolean) {
+                    val = (boolean) value;
+                } else {
+                    val = Boolean.parseBoolean(value.toString());
+                }
+                f.setBoolean(instance, val);
+            } else if (byte.class == type || Byte.class == type) {
+                byte val;
+                if (value instanceof Byte) {
+                    val = (byte) value;
+                } else {
+                    val = Byte.parseByte(value.toString());
+                }
+                f.setByte(instance, val);
+            } else if (int.class == type || Integer.class == type) {
+                int val;
+                if (value instanceof Integer) {
+                    val = (int) value;
+                } else {
+                    val = Integer.parseInt(value.toString());
+                }
+                f.setInt(instance, val);
+            } else if (long.class == type || Long.class == type) {
+                long val;
+                if (value instanceof Long) {
+                    val = (long) value;
+                } else {
+                    val = Long.parseLong(value.toString());
+                }
+                f.setLong(instance, val);
+            } else if (float.class == type || Float.class == type) {
+                float val;
+                if (value instanceof Float) {
+                    val = (float) value;
+                } else {
+                    val = Float.parseFloat(value.toString());
+                }
+                f.setFloat(instance, val);
+            } else if (double.class == type || Double.class == type) {
+                double val;
+                if (value instanceof Document) {
+                    val = (double) value;
+                } else {
+                    val = Double.parseDouble(value.toString());
+                }
+                f.setDouble(instance, val);
+            } else {
+                f.set(instance, value);
+            }
         } catch (Exception ex) {
             throw new UnsupportedOperationException("Cannot inject value of class: " + value.getClass() + " into: " + f);
         }