davsclaus commented on code in PR #27367:
URL: https://github.com/apache/camel/pull/27367#discussion_r4181852575


##########
dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java:
##########
@@ -0,0 +1,476 @@
+/*
+ * 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.dsl.yaml.validator;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.networknt.schema.Error;
+import com.networknt.schema.path.NodePath;
+import org.apache.camel.util.MimeTypeHelper;
+
+import static org.apache.camel.dsl.yaml.validator.RouteGraph.endpointOf;
+import static org.apache.camel.dsl.yaml.validator.RouteGraph.normalize;
+import static org.apache.camel.dsl.yaml.validator.RouteGraph.scheme;
+
+/**
+ * A field read on a body that is still text.
+ * <p/>
+ * Groovy {@code body.find { it.sku == ... }} or simple {@code ${body[sku]}} 
reads the fields of parsed data: a Map or a
+ * List. When the step before left the payload as text - a {@code setBody} 
with {@code constant}, a {@code marshal}, the
+ * file consumer, or a {@code direct:} route that ends with one of those - the 
read fails at runtime, Groovy with "No
+ * such property: sku for class: java.lang.Byte". The walk follows the steps 
of each route in order, and into the
+ * {@code direct:} and {@code seda:} routes it calls, and reports only where 
it is certain the body is text: anything it
+ * does not know makes it say nothing (CAMEL-24844).
+ */
+final class TextBodyFlow {
+
+    /** The Groovy methods that iterate a collection with a closure; on text 
they iterate the characters or bytes. */
+    private static final Set<String> ITERATES = Set.of("find", "findAll", 
"each", "eachWithIndex", "collect",
+            "collectEntries", "any", "every", "grep", "count", "sum", 
"findResult", "groupBy", "sort", "max", "min");
+
+    /** The methods of a Map, which text does not have. */
+    private static final Set<String> MAP_METHODS = Set.of("get", "getAt", 
"containsKey", "keySet", "values",
+            "entrySet");
+
+    /** What can be read from text without parsing it: a property of String, 
or a Groovy property of text. */
+    private static final Set<String> TEXT_PROPERTIES = Set.of("bytes", "text", 
"class", "empty", "blank", "length",
+            "size", "toString", "trim", "lines", "chars", "hashCode");
+
+    /** What the file consumer's GenericFile has besides: ${body.fileName} 
reads the file, not its content. */
+    private static final Set<String> FILE_PROPERTIES = Set.of("file", 
"fileName", "fileNameOnly", "fileLength",
+            "lastModified", "charset", "extendedAttributes", "body", "parent", 
"absoluteFilePath", "relativeFilePath",
+            "absolute", "endpointPath", "directory", 
"copyFromAbsoluteFilePath", "lastOffsetValue", "fileSeparator",
+            "binding");
+
+    /** body.x, body?.x, message.body.x, followed by what comes after the 
name. */
+    private static final Pattern GROOVY_PROPERTY = 
Pattern.compile("(?<![\\w$])body\\s*\\??\\.\\s*([A-Za-z_]\\w*)\\s*([{(])?");
+
+    /** body['x'] or body["x"]. */
+    private static final Pattern GROOVY_KEY = 
Pattern.compile("(?<![\\w$])body\\s*\\[\\s*['\"]");
+
+    /** ${body.x} or ${body?.x}, not a method call. */
+    private static final Pattern SIMPLE_PROPERTY = 
Pattern.compile("\\$\\{body\\??\\.([A-Za-z_]\\w*)(?!\\w|\\s*\\()");
+
+    /** ${body[x]} where x is a key, not an index. */
+    private static final Pattern SIMPLE_KEY = 
Pattern.compile("\\$\\{body\\[\\s*['\"]?[A-Za-z_]");

Review Comment:
   Fixed in 1d0506a52fab: the Groovy key read now guards the index the way 
`simpleRead` does, and an unclosed `body['sku` is reported with `body['`. 
`testAnUnclosedKeyIsStillReported` covers both readers.
   
   _Claude Code on behalf of davsclaus_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to