Skip to content

Commit

Permalink
feat(catalog): Sort Processor's properties
Browse files Browse the repository at this point in the history
Currently, since the component's schema is generated from the Camel's components catalog,
iterating over the properties dictionary, the output is written using the same sorting as well.

Ths is not the case for processors, which are extracted from the Camel
YAML DSL schema first, and then decorated with elements from the Camel's
catalog.

This commit change the iteration to be performed from the Camel's
processor catalog instead.

Changes:
* Move the `class:xxx` information from `$comment` to `format`
* Move the `duration` information from `$comment` to `format`
* Add `format: password` for `secret: true` fields

fix: #51
  • Loading branch information
lordrip committed Feb 28, 2024
1 parent 804d88f commit cad22d7
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@

import java.io.InputStream;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* Customize Camel Catalog for Kaoto.
Expand Down Expand Up @@ -113,11 +110,14 @@ private void generatePropertiesSchema(ObjectNode parent) throws Exception {
propertyType = property.get("type").asText();
if ("duration".equals(propertyType)) {
propertyType = "string";
propertySchema.put("$comment", "duration");
propertySchema.put("format", "duration");
}
propertySchema.put("type", propertyType);
}
if (property.has("deprecated")) propertySchema.put("deprecated", property.get("deprecated").asBoolean());
if (property.has("secret") && property.get("secret").asBoolean()) {
propertySchema.put("format", "password");
}
if (property.has("required") && property.get("required").asBoolean()) {
required.add(propertyName);
}
Expand Down Expand Up @@ -235,24 +235,33 @@ public String getPatternCatalog() throws Exception {
var modelCatalog = (EipModel) api.model(Kind.eip, name);
catalogMap.put(modelCatalog.getJavaType(), modelCatalog);
}

for (var entry : processors.entrySet()) {
var sortedSchemaProperties = jsonMapper.createObjectNode();
var processorFQCN = entry.getKey();
var processorSchema = entry.getValue();
var processorCatalog = catalogMap.get(processorFQCN);
for (var property : processorSchema.withObject("/properties").properties()) {
var propertyName = property.getKey();
var propertySchema = (ObjectNode) property.getValue();

var camelYamlDslProperties = processorSchema.withObject("/properties").properties().stream().map(Map.Entry::getKey).sorted(
new CamelYamlDSLKeysComparator(processorCatalog.getOptions())
).toList();

for (var propertyName : camelYamlDslProperties) {
var propertySchema = processorSchema.withObject("/properties").withObject("/" + propertyName);
if (TO_DYNAMIC_DEFINITION.equals(processorFQCN) && "parameters".equals(propertyName)) {
// "parameters" as a common property is omitted in the catalog, but we need this for "toD"
propertySchema.put("title", "Parameters");
propertySchema.put("description", "URI parameters");
sortedSchemaProperties.set(propertyName, propertySchema);
continue;
}
if (SET_HEADERS_DEFINITION.equals((processorFQCN)) && "headers".equals(propertyName)) {
propertySchema.put("title", "Headers");
propertySchema.put("description", "Headers to set");
sortedSchemaProperties.set(propertyName, propertySchema);
continue;
}

var catalogOpOptional = processorCatalog.getOptions().stream().filter(op -> op.getName().equals(propertyName)).findFirst();
if (catalogOpOptional.isEmpty()) {
throw new Exception(String.format("Option '%s' not found for processor '%s'", propertyName, processorFQCN));
Expand All @@ -262,12 +271,17 @@ public String getPatternCatalog() throws Exception {
&& !propertySchema.has("$comment")) {
propertySchema.put("$comment", "class:" + catalogOp.getJavaType());
}

sortedSchemaProperties.set(propertyName, propertySchema);
}

var json = JsonMapper.asJsonObject(processorCatalog).toJson();
var catalogTree = (ObjectNode) jsonMapper.readTree(json);
catalogTree.set("propertiesSchema", processorSchema);
processorSchema.set("properties", sortedSchemaProperties);
answer.set(processorCatalog.getName(), catalogTree);
}

StringWriter writer = new StringWriter();
var jsonGenerator = new JsonFactory().createGenerator(writer).useDefaultPrettyPrinter();
jsonMapper.writeTree(jsonGenerator, answer);
Expand Down Expand Up @@ -522,7 +536,7 @@ private void addMoreBeans(ObjectNode answer, Map<String, EipModel> catalogMap) t
json = JsonMapper.asJsonObject(templatedRouteBeanCatalog).toJson();
catalogTree = (ObjectNode) jsonMapper.readTree(json);
propertiesSchema = schemaProcessor.getTemplatedRouteBean();
processEntityParameters( "templatedRouteBean", propertiesSchema, templatedRouteBeanCatalog);
processEntityParameters("templatedRouteBean", propertiesSchema, templatedRouteBeanCatalog);
catalogTree.set("propertiesSchema", propertiesSchema);
answer.set("templatedRouteBean", catalogTree);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.kaoto.camelcatalog;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;

import org.apache.camel.tooling.model.EipModel.EipOptionModel;

public class CamelYamlDSLKeysComparator implements Comparator<String> {

private final List<EipOptionModel> eipOptions;

CamelYamlDSLKeysComparator(List<EipOptionModel> eipOptions) {
this.eipOptions = eipOptions;
}

@Override
public int compare(String firstKey, String secondKey) {
Optional<EipOptionModel> firstOption = eipOptions.stream().filter(e -> e.getName().equals(firstKey)).findFirst();
Optional<EipOptionModel> secondOption = eipOptions.stream().filter(e -> e.getName().equals(secondKey)).findFirst();

var firstIndex = firstOption.isPresent() ? firstOption.get().getIndex() : Integer.MAX_VALUE;
var secondIndex = secondOption.isPresent() ? secondOption.get().getIndex() : Integer.MAX_VALUE;

return Integer.compare(firstIndex, secondIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ public void testGetComponentCatalog() throws Exception {
.withObject("/propertiesSchema");
var etcdEProperty = etcdSchema.withObject("/properties").withObject("/endpoints");
assertEquals("Etcd3Constants.ETCD_DEFAULT_ENDPOINTS", etcdEProperty.withArray("/default").get(0).asText());

var smbSchema = componentCatalog
.withObject("/smb")
.withObject("/propertiesSchema");
var smbUsernameProperty = smbSchema.withObject("/properties").withObject("/username");
assertEquals("password", smbUsernameProperty.get("format").asText());
var smbPasswordProperty = smbSchema.withObject("/properties").withObject("/password");
assertEquals("password", smbPasswordProperty.get("format").asText());

var cxfSchema = componentCatalog
.withObject("/cxf")
.withObject("/propertiesSchema");
var cxfContinuationTimeout = cxfSchema.withObject("/properties").withObject("/continuationTimeout");
assertEquals("duration", cxfContinuationTimeout.get("format").asText());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.kaoto.camelcatalog;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Comparator;
import java.util.List;

import org.apache.camel.catalog.DefaultCamelCatalog;
import org.apache.camel.catalog.Kind;
import org.apache.camel.tooling.model.EipModel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class CamelYamlDSLKeysComparatorTest {
private DefaultCamelCatalog api;

@BeforeEach
public void setUp() {
this.api = new DefaultCamelCatalog();
}

@Test
public void sort_keys_using_the_catalog_index() throws Exception {
var aggregateCatalogModel = (EipModel) api.model(Kind.eip, "aggregate");

List<String> aggregateKeysFromCamelYAMLDsl = List.of("aggregateController", "aggregationRepository",
"aggregationStrategy", "aggregationStrategyMethodAllowNull", "aggregationStrategyMethodName",
"closeCorrelationKeyOnCompletion", "completeAllOnStop", "completionFromBatchConsumer",
"completionInterval", "completionOnNewCorrelationGroup", "completionPredicate", "completionSize",
"completionSizeExpression", "completionTimeout", "completionTimeoutCheckerInterval",
"completionTimeoutExpression", "correlationExpression", "description", "disabled",
"discardOnAggregationFailure", "discardOnCompletionTimeout", "eagerCheckCompletion", "executorService",
"forceCompletionOnStop", "id", "ignoreInvalidCorrelationKeys", "optimisticLockRetryPolicy",
"optimisticLocking", "parallelProcessing", "steps", "timeoutCheckerExecutorService");

List<String> expected = List.of("id", "description", "disabled", "correlationExpression", "completionPredicate",
"completionTimeoutExpression", "completionSizeExpression", "optimisticLockRetryPolicy",
"parallelProcessing", "optimisticLocking", "executorService", "timeoutCheckerExecutorService",
"aggregateController", "aggregationRepository", "aggregationStrategy", "aggregationStrategyMethodName",
"aggregationStrategyMethodAllowNull", "completionSize", "completionInterval", "completionTimeout",
"completionTimeoutCheckerInterval", "completionFromBatchConsumer", "completionOnNewCorrelationGroup",
"eagerCheckCompletion", "ignoreInvalidCorrelationKeys", "closeCorrelationKeyOnCompletion",
"discardOnCompletionTimeout", "discardOnAggregationFailure", "forceCompletionOnStop",
"completeAllOnStop", "steps");

Comparator<String> comparator = new CamelYamlDSLKeysComparator(aggregateCatalogModel.getOptions());

List<String> result = aggregateKeysFromCamelYAMLDsl.stream().sorted(comparator).toList();

assertEquals(result, expected);
}

}

0 comments on commit cad22d7

Please sign in to comment.