in modules/configuration-annotation-processor/src/main/java/org/apache/ignite/internal/configuration/processor/ConfigurationProcessor.java [388:581]
private void createPojoBindings(
Collection<VariableElement> fields,
ClassName schemaClassName,
TypeSpec.Builder configurationInterfaceBuilder,
boolean extendBaseSchema,
TypeElement realSchemaClass,
boolean isPolymorphicConfig,
boolean isPolymorphicInstanceConfig
) {
ClassName viewClsName = getViewName(schemaClassName);
ClassName changeClsName = getChangeName(schemaClassName);
TypeName configInterfaceType;
@Nullable TypeName viewBaseSchemaInterfaceType;
@Nullable TypeName changeBaseSchemaInterfaceType;
TypeElement superClass = superClass(realSchemaClass);
boolean isSuperClassAbstractConfiguration = !isClass(superClass.asType(), Object.class)
&& superClass.getAnnotation(AbstractConfiguration.class) != null;
if (extendBaseSchema || isSuperClassAbstractConfiguration) {
ClassName superClassSchemaClassName = ClassName.get(superClass);
viewBaseSchemaInterfaceType = getViewName(superClassSchemaClassName);
changeBaseSchemaInterfaceType = getChangeName(superClassSchemaClassName);
if (isSuperClassAbstractConfiguration) {
// Example: ExtendedTableConfig extends TableConfig<ExtendedTableView, ExtendedTableChange>
configInterfaceType = ParameterizedTypeName.get(
getConfigurationInterfaceName(superClassSchemaClassName),
viewClsName,
changeClsName
);
} else {
// Example: ExtendedTableConfig extends TableConfig
configInterfaceType = getConfigurationInterfaceName(superClassSchemaClassName);
}
} else {
ClassName confTreeInterface = ClassName.get("org.apache.ignite.configuration", "ConfigurationTree");
if (realSchemaClass.getAnnotation(AbstractConfiguration.class) != null) {
// Example: TableConfig<VIEWT extends TableView, CHANGET extends TableChange> extends ConfigurationTree<VIEWT, CHANGET>
configurationInterfaceBuilder.addTypeVariables(List.of(
TypeVariableName.get("VIEWT", viewClsName),
TypeVariableName.get("CHANGET", changeClsName)
));
configInterfaceType = ParameterizedTypeName.get(
confTreeInterface,
TypeVariableName.get("VIEWT"),
TypeVariableName.get("CHANGET")
);
} else {
// Example: TableConfig extends ConfigurationTree<TableView, TableChange>
configInterfaceType = ParameterizedTypeName.get(confTreeInterface, viewClsName, changeClsName);
}
viewBaseSchemaInterfaceType = null;
changeBaseSchemaInterfaceType = null;
}
configurationInterfaceBuilder.addSuperinterface(configInterfaceType);
// This code will be refactored in the future. Right now I don't want to entangle it with existing code
// generation. It has only a few considerable problems - hardcode and a lack of proper arrays handling.
// Clone method should be used to guarantee data integrity.
TypeSpec.Builder viewClsBuilder = TypeSpec.interfaceBuilder(viewClsName)
.addModifiers(PUBLIC);
if (viewBaseSchemaInterfaceType != null) {
viewClsBuilder.addSuperinterface(viewBaseSchemaInterfaceType);
}
TypeSpec.Builder changeClsBuilder = TypeSpec.interfaceBuilder(changeClsName)
.addSuperinterface(viewClsName)
.addModifiers(PUBLIC);
if (changeBaseSchemaInterfaceType != null) {
changeClsBuilder.addSuperinterface(changeBaseSchemaInterfaceType);
}
if (isPolymorphicInstanceConfig) {
changeClsBuilder.addSuperinterface(POLYMORPHIC_CHANGE_CLASSNAME);
}
ClassName consumerClsName = ClassName.get(Consumer.class);
for (VariableElement field : fields) {
Value valAnnotation = field.getAnnotation(Value.class);
String fieldName = field.getSimpleName().toString();
TypeMirror schemaFieldType = field.asType();
TypeName schemaFieldTypeName = TypeName.get(schemaFieldType);
boolean leafField = isValidValueAnnotationFieldType(schemaFieldType)
|| !((ClassName) schemaFieldTypeName).simpleName().contains(CONFIGURATION_SCHEMA_POSTFIX);
boolean namedListField = field.getAnnotation(NamedConfigValue.class) != null;
TypeName viewFieldType =
leafField ? schemaFieldTypeName : getViewName((ClassName) schemaFieldTypeName);
TypeName changeFieldType =
leafField ? schemaFieldTypeName : getChangeName((ClassName) schemaFieldTypeName);
if (namedListField) {
changeFieldType = ParameterizedTypeName.get(
ClassName.get(NamedListChange.class),
viewFieldType,
changeFieldType
);
viewFieldType = ParameterizedTypeName.get(
ClassName.get(NamedListView.class),
WildcardTypeName.subtypeOf(viewFieldType)
);
}
MethodSpec.Builder getMtdBuilder = MethodSpec.methodBuilder(fieldName)
.addModifiers(PUBLIC, ABSTRACT)
.returns(viewFieldType);
viewClsBuilder.addMethod(getMtdBuilder.build());
// Read only.
if (field.getAnnotation(PolymorphicId.class) != null || field.getAnnotation(InjectedName.class) != null
|| field.getAnnotation(InternalId.class) != null) {
continue;
}
String changeMtdName = "change" + capitalize(fieldName);
MethodSpec.Builder changeMtdBuilder = MethodSpec.methodBuilder(changeMtdName)
.addModifiers(PUBLIC, ABSTRACT)
.returns(changeClsName);
if (valAnnotation != null) {
if (schemaFieldType.getKind() == TypeKind.ARRAY) {
changeMtdBuilder.varargs(true);
}
changeMtdBuilder.addParameter(changeFieldType, fieldName);
} else {
changeMtdBuilder.addParameter(ParameterizedTypeName.get(consumerClsName, changeFieldType), fieldName);
}
changeClsBuilder.addMethod(changeMtdBuilder.build());
// Create "FooChange changeFoo()" method with no parameters, if it's a config value or named list value.
if (valAnnotation == null) {
MethodSpec.Builder shortChangeMtdBuilder = MethodSpec.methodBuilder(changeMtdName)
.addModifiers(PUBLIC, ABSTRACT)
.returns(changeFieldType);
changeClsBuilder.addMethod(shortChangeMtdBuilder.build());
}
}
if (isPolymorphicConfig) {
// Parameter type: Class<T>.
ParameterizedTypeName parameterType = ParameterizedTypeName.get(
ClassName.get(Class.class),
TypeVariableName.get("T")
);
// Variable type, for example: <T extends SimpleChange & PolymorphicChange>.
TypeVariableName typeVariable = TypeVariableName.get("T", changeClsName, POLYMORPHIC_CHANGE_CLASSNAME);
// Method like: <T extends SimpleChange & PolymorphicChange> T convert(Class<T> changeClass);
MethodSpec.Builder convertByChangeClassMtdBuilder = MethodSpec.methodBuilder("convert")
.addModifiers(PUBLIC, ABSTRACT)
.addTypeVariable(typeVariable)
.addParameter(parameterType, "changeClass")
.returns(TypeVariableName.get("T"));
changeClsBuilder.addMethod(convertByChangeClassMtdBuilder.build());
// Method like: SimpleChange convert(String polymorphicTypeId);
MethodSpec.Builder convertByStringMtdBuilder = MethodSpec.methodBuilder("convert")
.addModifiers(PUBLIC, ABSTRACT)
.addParameter(ClassName.get(String.class), "polymorphicTypeId")
.returns(changeClsName);
changeClsBuilder.addMethod(convertByStringMtdBuilder.build());
}
TypeSpec viewCls = viewClsBuilder.build();
TypeSpec changeCls = changeClsBuilder.build();
buildClass(viewClsName.packageName(), viewCls);
buildClass(changeClsName.packageName(), changeCls);
}