in dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/GenerateYamlDeserializersMojo.java [369:662]
private TypeSpecHolder generateParser(ClassInfo info) {
final ClassName targetType = ClassName.get(info.name().prefix().toString(), info.name().withoutPackagePrefix());
final TypeSpec.Builder builder = TypeSpec.classBuilder(info.simpleName() + "Deserializer");
final Map<String, Set<String>> attributes = new HashMap<>();
final List<AnnotationSpec> properties = new ArrayList<>();
final AnnotationSpec.Builder yamlTypeAnnotation = AnnotationSpec.builder(CN_YAML_TYPE);
builder.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
if (extendsType(info, SEND_DEFINITION_CLASS) || extendsType(info, TO_DYNAMIC_DEFINITION_CLASS)
|| extendsType(info, POLL_DEFINITION_CLASS)) {
builder.superclass(ParameterizedTypeName.get(CN_ENDPOINT_AWARE_DESERIALIZER_BASE, targetType));
} else {
builder.superclass(ParameterizedTypeName.get(CN_DESERIALIZER_BASE, targetType));
}
TypeSpecHolder.put(attributes, "type", info.name().toString());
//TODO: add an option on Camel's definitions to distinguish between IN/OUT types
if (info.name().toString().equals("org.apache.camel.model.InterceptDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.InterceptFromDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.InterceptSendToEndpointDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.OnExceptionDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.OnCompletionDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.rest.RestDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
if (info.name().toString().equals("org.apache.camel.model.rest.RestConfigurationDefinition")) {
builder.addAnnotation(CN_YAML_IN);
}
final AtomicReference<String> modelName = new AtomicReference<>();
annotationValue(info, XML_ROOT_ELEMENT_ANNOTATION_CLASS, "name")
.map(AnnotationValue::asString)
.filter(value -> !"##default".equals(value))
.ifPresent(value -> {
// generate the kebab case variant for backward compatibility
// https://issues.apache.org/jira/browse/CAMEL-17097
if (!Objects.equals(value, StringHelper.camelCaseToDash(value))) {
yamlTypeAnnotation.addMember("nodes", "$S", StringHelper.camelCaseToDash(value));
TypeSpecHolder.put(attributes, "node", StringHelper.camelCaseToDash(value));
}
yamlTypeAnnotation.addMember("nodes", "$S", value);
modelName.set(value);
TypeSpecHolder.put(attributes, "node", value);
});
//
// Constructors
//
builder.addMethod(MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addStatement("super($L.class)", info.simpleName())
.build());
//
// T handledTypeInstance();
//
builder.addMethod(MethodSpec.methodBuilder("newInstance")
.addAnnotation(AnnotationSpec.builder(Override.class).build())
.addModifiers(Modifier.PROTECTED)
.returns(targetType)
.addCode(
CodeBlock.builder()
.addStatement("return new $L()", info.simpleName())
.build())
.build());
//
// T handledTypeInstance(String value);
//
for (MethodInfo ctor : info.constructors()) {
// do not generate inline for error handlers (only ref error handler is allowed)
boolean eh = implementType(info, ERROR_HANDLER_DEFINITION_CLASS);
boolean ref = eh && implementType(info, REF_ERROR_HANDLER_DEFINITION_CLASS);
if (eh && !ref) {
break;
}
if (ctor.parameterTypes().size() == 1 && ctor.parameterTypes().get(0).name().equals(STRING_CLASS)) {
if ((ctor.flags() & java.lang.reflect.Modifier.PUBLIC) == 0) {
break;
}
yamlTypeAnnotation.addMember("inline", "true");
builder
.addMethod(MethodSpec.methodBuilder("newInstance")
.addAnnotation(AnnotationSpec.builder(Override.class).build())
.addModifiers(Modifier.PROTECTED)
.addParameter(String.class, "value")
.returns(targetType)
.addCode(
CodeBlock.builder()
.addStatement("return new $L(value)", info.simpleName())
.build())
.build());
break;
}
}
//
// Generate setProperty body
//
boolean caseAdded = false;
CodeBlock.Builder setProperty = CodeBlock.builder();
setProperty.addStatement("propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey)");
setProperty.beginControlFlow("switch(propertyKey)");
final Schema descriptor = schemes.computeIfAbsent(
info.name().toString(),
k -> new Schema(MAPPER.createObjectNode(), MAPPER.createObjectNode()));
for (FieldInfo field : fields(info)) {
if (generateSetValue(descriptor, modelName.get(), setProperty, field, properties)) {
caseAdded = true;
}
}
if (implementType(info, ID_AWARE_CLASS)) {
setProperty.beginControlFlow("case $S:", "id");
setProperty.addStatement("String val = asText(node)");
setProperty.addStatement("target.setId(val)");
setProperty.addStatement("break");
setProperty.endControlFlow();
setProperty.beginControlFlow("case $S:", "description");
setProperty.addStatement("String val = asText(node)");
setProperty.addStatement("target.setDescription(val)");
setProperty.addStatement("break");
setProperty.endControlFlow();
properties.add(
YamlProperties.annotation("id", "string")
.withDescription(descriptor.description("id"))
.withDisplayName(descriptor.displayName("id"))
.build());
properties.add(
YamlProperties.annotation("description", "string")
.withDescription(descriptor.description("description"))
.withDisplayName(descriptor.displayName("description"))
.build());
}
if (shouldHaveSteps(info)) {
caseAdded = true;
setProperty.beginControlFlow("case \"steps\":");
setProperty.addStatement("setSteps(target, node)");
setProperty.addStatement("break");
setProperty.endControlFlow();
properties.add(
yamlProperty(
"steps",
"array:org.apache.camel.model.ProcessorDefinition"));
}
if (extendsType(info, SEND_DEFINITION_CLASS) || extendsType(info, TO_DYNAMIC_DEFINITION_CLASS)
|| extendsType(info, POLL_DEFINITION_CLASS)) {
setProperty.beginControlFlow("default:");
setProperty.addStatement("return false");
setProperty.endControlFlow();
properties.add(
yamlProperty(
"parameters",
"object"));
builder.addMethod(MethodSpec.methodBuilder("setEndpointUri")
.addAnnotation(AnnotationSpec.builder(Override.class).build())
.addModifiers(Modifier.PROTECTED)
.addParameter(CamelContext.class, "camelContext")
.addParameter(Node.class, "node")
.addParameter(targetType, "target")
.addParameter(
ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ClassName.get(Object.class)),
"parameters")
.addCode(
CodeBlock.builder()
.addStatement(
"target.setUri(org.apache.camel.dsl.yaml.common.YamlSupport.createEndpointUri(camelContext, node, target.getUri(), parameters))")
.build())
.build());
} else if (implementType(info, HAS_EXPRESSION_TYPE_CLASS)) {
setProperty.beginControlFlow("default:");
setProperty.addStatement("$T ed = target.getExpressionType()", CN_EXPRESSION_DEFINITION);
setProperty.beginControlFlow("if (ed != null)");
setProperty.addStatement(
"throw new org.apache.camel.dsl.yaml.common.exception.DuplicateFieldException(node, propertyName, \"as an expression\")");
setProperty.endControlFlow();
setProperty.addStatement("ed = ExpressionDeserializers.constructExpressionType(propertyKey, node)");
setProperty.beginControlFlow("if (ed != null)");
setProperty.addStatement("target.setExpressionType(ed)");
setProperty.nextControlFlow("else");
setProperty.addStatement("return false");
setProperty.endControlFlow();
setProperty.endControlFlow();
if (!extendsType(info, EXPRESSION_DEFINITION_CLASS)) {
properties.add(
yamlProperty(
"__extends",
"object:org.apache.camel.model.language.ExpressionDefinition",
"expression"));
}
} else {
setProperty.beginControlFlow("default:");
setProperty.addStatement("return false");
setProperty.endControlFlow();
}
setProperty.endControlFlow();
if (caseAdded) {
setProperty.addStatement("return true");
}
//
// setProperty(T target, String propertyKey, String propertyName, Node value) throws Exception
//
builder
.addMethod(MethodSpec.methodBuilder("setProperty")
.addAnnotation(AnnotationSpec.builder(Override.class).build())
.addModifiers(Modifier.PROTECTED)
.addParameter(targetType, "target")
.addParameter(String.class, "propertyKey")
.addParameter(String.class, "propertyName")
.addParameter(Node.class, "node")
.returns(boolean.class)
.addCode(setProperty.build())
.build());
//
// YamlType
//
yamlTypeAnnotation.addMember(
"types",
"$L.class",
info.name().toString());
yamlTypeAnnotation.addMember(
"order",
"org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1",
info.name().toString());
JsonNode yamlTypeDisplayName = descriptor.meta.at("/title");
if (!yamlTypeDisplayName.isMissingNode() && yamlTypeDisplayName.isTextual()) {
yamlTypeAnnotation.addMember(
"displayName",
"$S",
yamlTypeDisplayName.textValue());
}
JsonNode yamlTypeDescription = descriptor.meta.at("/description");
if (!yamlTypeDescription.isMissingNode() && yamlTypeDescription.isTextual()) {
yamlTypeAnnotation.addMember(
"description",
"$S",
yamlTypeDescription.textValue());
}
JsonNode yamlTypeDeprecated = descriptor.meta.at("/deprecated");
if (!yamlTypeDeprecated.isMissingNode() && yamlTypeDeprecated.isBoolean()) {
yamlTypeAnnotation.addMember(
"deprecated",
"$L",
yamlTypeDeprecated.booleanValue());
}
properties.stream().sorted(Comparator.comparing(a -> a.members.get("name").toString())).forEach(spec -> {
yamlTypeAnnotation.addMember("properties", "$L", spec);
});
builder.addAnnotation(yamlTypeAnnotation.build());
return new TypeSpecHolder(builder.build(), attributes);
}