oscerd commented on code in PR #27421:
URL: https://github.com/apache/camel/pull/27421#discussion_r4193663895
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java:
##########
@@ -345,12 +345,45 @@ private static JsonObject eipDoc(
String matchedTerm) {
String doc = includeDoc ? catalog.asciiDoc(model.getName() + "-eip") :
null;
JsonObject result = eipDoc(model, filter, scope, doc);
+ if (filter != null && scope != OptionScope.NONE &&
result.getIntegerOrDefault("matchedOptions", 0) == 0) {
+ putNestedOptions(catalog, model, filter, result);
+ }
if (matchedTerm != null) {
result.put("matchedTerm", matchedTerm);
}
return result;
}
+ /**
+ * The options of the elements of an EIP that match the filter, when none
of its own do: logStackTrace is an option
+ * of the redeliveryPolicy of onException, and a filter on onException
found nothing (CAMEL-25370).
+ */
+ private static void putNestedOptions(CamelCatalog catalog, EipModel model,
String filter, JsonObject result) {
+ JsonArray nested = new JsonArray();
+ for (BaseOptionModel opt : model.getOptions()) {
+ if (!"element".equals(opt.getKind())) {
+ continue;
+ }
+ EipModel element = catalog.eipModel(opt.getName());
Review Comment:
**The nested search finds the element's model by option name, so name
collisions pick an unrelated model**
`catalog.eipModel(opt.getName())` assumes the option is named after its
model. That holds for `onException.redeliveryPolicy`, but resolves to an
unrelated model for e.g. `templatedRoute.bean`
(`List<BeanFactoryDefinition<...>>`, resolved to the `bean` EIP's
`BeanDefinition`, so `templatedRoute optionsFilter=method` answers `bean:
{method: ...}`, while a templated route bean has
`initMethod`/`factoryMethod`/`builderMethod` and its YAML key is `beans:`),
`responseMessage.header` (→ the `header` language) and `beanFactory.script` (a
`String`, → the `script` EIP). Checking that the option's javaType (inside
`List<...>`, without generics) equals `element.getJavaType()` would skip
exactly these and keep the intended matches.
Two smaller points: `under` is the catalog element name and the hint always
shows a map, so `routeTemplate.templateParameter` (YAML `parameters:`, a list)
and `choice.when` (a list) get shapes the schema does not accept; and
`errorHandler` itself gets no `nestedOptions`, because `errorHandlerType` has
no model of that name (`camel_catalog_doc errorHandler
optionsFilter=deadLetterUri` still finds nothing).
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java:
##########
@@ -1535,6 +1568,15 @@ public static JsonObject optionToJson(BaseOptionModel
opt, String scope) {
enums.addAll(opt.getEnums());
o.put("enumValues", enums);
}
+ if ("element".equals(opt.getKind()) && opt.getOneOfs() != null &&
!opt.getOneOfs().isEmpty()) {
Review Comment:
**The oneOf hint fires for every element with a oneOf list, including
`outputs` (27 EIPs), where it is wrong**
This condition matches every `element` option with a `oneOf` list, not only
the ones written as one of their kinds. It is right for
`errorHandler.errorHandlerType`, `marshal`/`unmarshal`'s `dataFormatType`,
`loadBalance.loadBalancerType`, `resequence.resequencerConfig`,
`tokenizer.tokenizerImplementation` and `route.input`, but wrong for the rest:
- `outputs` (kind element, type array, required, oneOf of ~72 processors) is
an option of 27 EIP models (filter, split, loop, multicast, doTry, onException,
aggregate, when, otherwise, route, ...). Their default `camel_catalog_doc`
answer now says `write one of oneOf as the key, not 'outputs': for example
a2aSubTask: {...}`, while in the YAML DSL these go under `steps:`.
`FilterDefinition` has `steps` and no `to`/`log` (`additionalProperties:
false`), so following the hint fails validation; for `route` the steps go under
`from:`.
- `setHeaders.headers` / `setVariables.variables` (oneOf `[setHeader]` /
`[setVariable]`): the hint says to write `setHeader:` instead of `headers:`,
but the YAML is `setHeaders: {headers: [...]}`.
- `choice.when`, `choice.otherwise` and `doTry.doCatch` have their own name
as their only oneOf entry, so the hint contradicts itself (`not 'when': for
example when: {...}`).
The 72-name list also makes those 27 answers noticeably larger, which works
against the small-model goal. Limiting the hint to single-valued elements
written as one of their kinds keeps every correct case:
```suggestion
if ("element".equals(opt.getKind()) &&
"object".equals(opt.getType()) && opt.getOneOfs() != null
&& !opt.getOneOfs().isEmpty() &&
!opt.getOneOfs().contains(opt.getName())) {
```
A negative assertion in `CatalogDocsTest` (no `oneOf`/`yaml` on `filter`'s
`outputs` or `setHeaders`'s `headers`) would keep it from coming back.
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamples.java:
##########
@@ -90,6 +90,10 @@ public final class CatalogSamples {
Map.entry("redeliveryPolicy", "onException"),
Map.entry("deadLetterChannel", "errorHandler"),
Map.entry("defaultErrorHandler", "errorHandler"),
+ Map.entry("noErrorHandler", "errorHandler"),
+ Map.entry("jtaTransactionErrorHandler", "errorHandler"),
+ Map.entry("springTransactionErrorHandler", "errorHandler"),
+ Map.entry("refErrorHandler", "errorHandler"),
Review Comment:
**"the sample shows it in place" is not true for the four kinds the samples
do not show**
With these entries, `resolveExact` maps `defaultErrorHandler`,
`jtaTransactionErrorHandler`, `springTransactionErrorHandler` and
`refErrorHandler` to `errorHandler`, and `eipAnswer` adds `<name> is a part of
errorHandler; the sample shows it in place`. The two shipped `errorHandler`
samples only contain `deadLetterChannel` and `noErrorHandler`, so the note is
not true for those four. That matters most for `refErrorHandler`, whose shape
(`refErrorHandler: myHandler` or `{ref: ...}`) cannot be inferred from a
deadLetterChannel example. A note for these kinds could say the samples show
deadLetterChannel and noErrorHandler, that `<kind>` goes in the same place, and
that `camel_catalog_doc <kind>` gives its options.
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java:
##########
@@ -345,12 +345,45 @@ private static JsonObject eipDoc(
String matchedTerm) {
String doc = includeDoc ? catalog.asciiDoc(model.getName() + "-eip") :
null;
JsonObject result = eipDoc(model, filter, scope, doc);
+ if (filter != null && scope != OptionScope.NONE &&
result.getIntegerOrDefault("matchedOptions", 0) == 0) {
Review Comment:
**With includeOptions=required, the fallback runs although the EIP's own
options matched, and ignores the scope**
`matchedOptions` counts the options the scope kept, not the ones the filter
matched. With `includeOptions=required`, `camel_catalog_doc onException
optionsFilter=redelivery` matches six of the EIP's own options (none required),
so `matchedOptions: 0` / `omittedOptions: 6`, and the fallback still runs and
adds `redeliveryPolicy` options, none of them required either, because
`putNestedOptions` never applies the scope. That contradicts the javadoc ("when
none of its own do"). Also requiring `omittedOptions == 0` here and passing the
scope into `putNestedOptions` would keep them consistent.
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamples.java:
##########
@@ -648,7 +652,17 @@ static String normalizeKind(String kind) {
return k;
}
+ /** The kinds of error handler, each the one key under errorHandler:. */
+ static final Set<String> ERROR_HANDLERS = Set.of("errorHandler",
"deadLetterChannel", "defaultErrorHandler",
+ "noErrorHandler", "jtaTransactionErrorHandler",
"springTransactionErrorHandler", "refErrorHandler");
+
static String placement(String key) {
+ if (ERROR_HANDLERS.contains(key)) {
+ // a step it is not, and it has two places (CAMEL-25370)
+ return "errorHandler: with the kind (deadLetterChannel,
defaultErrorHandler, noErrorHandler) as its one key,"
+ + " either as a top-level list item - errorHandler: for
every route, or under one route, next to from:,"
+ + " for that route only; never a step";
Review Comment:
**The placement leaves out routeConfiguration**
`routeConfiguration` is a third place for the error handler
(`RouteConfigurationDefinition` has `errorHandler`, and
route-configuration.adoc has a "Route Configuration with Error Handler"
section), and it is the usual way to share one handler among a group of routes
without making it global:
```suggestion
+ " for that route only, or inside a routeConfiguration
for the routes that use it; never a step";
```
--
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]