luigidemasi commented on code in PR #27082:
URL: https://github.com/apache/camel/pull/27082#discussion_r4133467679


##########
dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java:
##########
@@ -95,19 +97,50 @@ public void preParseRoute(Resource resource) throws 
Exception {
         if (preparseDone.getOrDefault(resource.getLocation(), false)) {
             return;
         }
-        XmlStreamInfo xmlInfo = xmlInfo(resource);
-        if (xmlInfo.isValid()) {
-            String root = xmlInfo.getRootElementName();
-            if ("beans".equals(root) || "blueprint".equals(root) || 
"camel".equals(root)) {
-                new XmlModelParser(resource, xmlInfo.getRootElementNamespace())
-                        .parseBeansDefinition()
-                        .ifPresent(bd -> {
-                            registerBeans(resource, bd);
-                            camelAppCache.put(resource.getLocation(), bd);
-                        });
+        try {
+            XmlStreamInfo xmlInfo = xmlInfo(resource);
+            if (xmlInfo.isValid()) {
+                String root = xmlInfo.getRootElementName();
+                SemanticDefinition semantic = null;
+                if ("beans".equals(root) || "blueprint".equals(root) || 
"camel".equals(root)) {
+                    new XmlModelParser(resource, 
xmlInfo.getRootElementNamespace())
+                            .parseBeansDefinition()
+                            .ifPresent(bd -> {
+                                registerBeans(resource, bd);
+                                camelAppCache.put(resource.getLocation(), bd);
+                            });
+                    BeansDefinition app = 
camelAppCache.get(resource.getLocation());
+                    if (app != null) {
+                        semantic = app.getSemantic();
+                    }
+                } else if ("routes".equals(root) || "route".equals(root)) {
+                    RoutesDefinition routes = new 
XmlModelParser(resource(resource), xmlInfo.getRootElementNamespace())
+                            .parseRoutesDefinition().orElse(null);
+                    if (routes != null) {
+                        routesCache.put(resource.getLocation(), routes);
+                        semantic = routes.getSemantic();
+                    }
+                }
+                SemanticDefinition.configure(getCamelContext(), resource, 
resource.getLocation(), semantic);
             }
+            preparseDone.put(resource.getLocation(), true);
+        } catch (Exception e) {
+            // A failed batch also prevents builders for earlier resources 
from clearing their cached input.
+            resourceCache.clear();
+            xmlInfoCache.clear();

Review Comment:
   Keeping the cache clearing as implemented. Earlier resources may also be 
corrected before retry, so clearing only the failed resource would reuse stale 
input; failedResourceBatchDoesNotReuseEarlierCachedDeclarationsOnRetry covers 
that case. Successful configure() calls already clear their own resource 
entries, so the remaining caches hold pending input. A transactional rollback 
mechanism would add scope without fixing a demonstrated problem here.
   
   _Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._



##########
dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java:
##########
@@ -95,19 +97,50 @@ public void preParseRoute(Resource resource) throws 
Exception {
         if (preparseDone.getOrDefault(resource.getLocation(), false)) {
             return;
         }
-        XmlStreamInfo xmlInfo = xmlInfo(resource);
-        if (xmlInfo.isValid()) {
-            String root = xmlInfo.getRootElementName();
-            if ("beans".equals(root) || "blueprint".equals(root) || 
"camel".equals(root)) {
-                new XmlModelParser(resource, xmlInfo.getRootElementNamespace())
-                        .parseBeansDefinition()
-                        .ifPresent(bd -> {
-                            registerBeans(resource, bd);
-                            camelAppCache.put(resource.getLocation(), bd);
-                        });
+        try {
+            XmlStreamInfo xmlInfo = xmlInfo(resource);
+            if (xmlInfo.isValid()) {
+                String root = xmlInfo.getRootElementName();
+                SemanticDefinition semantic = null;
+                if ("beans".equals(root) || "blueprint".equals(root) || 
"camel".equals(root)) {
+                    new XmlModelParser(resource, 
xmlInfo.getRootElementNamespace())
+                            .parseBeansDefinition()
+                            .ifPresent(bd -> {
+                                registerBeans(resource, bd);
+                                camelAppCache.put(resource.getLocation(), bd);
+                            });

Review Comment:
   Yes, the parsed RoutesDefinition is cached and reused during configure(), 
while the preparse pass registers shared declarations before any co-loaded 
routes initialize. The cross-resource declaration test covers that ordering. 
The PR description now explains this loader behavior explicitly.
   
   _Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._



##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/DefaultSemanticDefinitionConfigurer.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * 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.semantic;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.model.app.SemanticDefinition;
+import org.apache.camel.model.app.SemanticDefinitionConfigurer;
+import org.apache.camel.model.app.SemanticQuestionDefinition;
+import org.apache.camel.spi.Resource;
+import org.apache.camel.util.StringHelper;
+
+/** Converts Java/XML declarations to the same immutable questions used by 
YAML and programmatic registration. */
+public class DefaultSemanticDefinitionConfigurer implements 
SemanticDefinitionConfigurer {
+    @Override
+    public void configure(CamelContext context, Resource resource, String 
source, SemanticDefinition definition) {
+        Map<String, SemanticQuestion> questions = new LinkedHashMap<>();
+        if (definition != null) {
+            for (SemanticQuestionDefinition question : 
definition.getQuestions()) {
+                String name = question.getName();
+                if (name == null || name.isBlank()) {
+                    throw new IllegalArgumentException("Semantic question 
requires a nonblank name");

Review Comment:
   Added field-specific numeric diagnostics in b6a0e7ed2db9. 
NumberFormatException was already caught by the surrounding 
IllegalArgumentException handler, which supplied the question name; the message 
now also identifies threshold or uncertainty and the invalid value, while 
retaining the original cause. Both non-numeric cases are covered by the 
invalid-reload test, including preservation of prior definitions and recovery 
after corrected input. All 109 semantic tests pass.
   
   _Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._



##########
core/camel-core-model/src/main/java/org/apache/camel/model/app/SemanticQuestionDefinition.java:
##########
@@ -0,0 +1,183 @@
+/*
+ * 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.model.app;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+import org.apache.camel.model.PropertyDefinition;
+import org.apache.camel.spi.Metadata;
+
+/** A semantic question with the same fields and policies as a YAML 
declaration. */
+@Metadata(label = "configuration")
+@XmlType(name = "semanticQuestionDefinition", propOrder = { "instructions", 
"criteria", "levels" })
+@XmlAccessorType(XmlAccessType.FIELD)
+public class SemanticQuestionDefinition {
+    @XmlAttribute(required = true)
+    @Metadata(required = true, description = "The context-wide question name.")
+    private String name;
+    @XmlAttribute(required = true)
+    @Metadata(required = true, enums = "boolean,choice,score", description = 
"The question type.")
+    private String type;
+    @XmlAttribute
+    @Metadata(description = "The Simple expression selecting the message 
state.")
+    private String state;
+    @XmlAttribute
+    @Metadata(description = "The boolean decision threshold.")
+    private String threshold;
+    @XmlAttribute
+    @Metadata(description = "The boolean uncertainty band.")
+    private String uncertainty;
+    @XmlAttribute
+    @Metadata(enums = "fail,non-match", description = "The boolean uncertainty 
policy.")
+    private String uncertaintyPolicy;
+    @XmlElement(required = true)
+    @Metadata(required = true, description = "Instructions describing the 
judgment to make.")
+    private String instructions;
+    @XmlElement(name = "criterion")
+    @Metadata(description = "Named choice criteria, or optional true/false 
boolean criteria.")
+    private List<PropertyDefinition> criteria = new ArrayList<>();
+    @XmlElement(name = "level")

Review Comment:
   Keeping the mutable collections in the declaration model, consistent with 
the existing model-builder convention. Conversion to SemanticQuestion 
defensively copies criteria and levels into immutable runtime collections, so 
evaluation does not retain these mutable model lists.
   
   _Codex on behalf of [luigidemasi](https://github.com/luigidemasi)._



-- 
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