in modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/InnerNodeAsmGenerator.java [288:474]
private ClassDefinition createNodeClass() {
SchemaClassesInfo schemaClassInfo = cgen.schemaInfo(schemaClass);
// Node class definition.
innerNodeClassDef = new ClassDefinition(
EnumSet.of(PUBLIC, FINAL),
internalName(schemaClassInfo.nodeClassName),
type(InnerNode.class),
nodeClassInterfaces(schemaClass, extensions)
);
// Spec fields.
Map<Class<?>, FieldDefinition> specFields = new HashMap<>();
int i = 0;
for (Class<?> clazz : concat(List.of(schemaClass), extensions, polymorphicExtensions)) {
specFields.put(clazz, innerNodeClassDef.declareField(EnumSet.of(PRIVATE, FINAL), "_spec" + i++, clazz));
}
// Define the rest of the fields.
Map<String, FieldDefinition> fieldDefs = new HashMap<>();
// To store the id of the polymorphic configuration instance.
FieldDefinition polymorphicTypeIdFieldDef = null;
// Field with @InjectedName.
FieldDefinition injectedNameFieldDef = null;
// Field with @InjectedValue.
Field injectedValueField = null;
for (Field schemaField : concat(schemaFields, publicExtensionFields, internalExtensionFields, polymorphicFields)) {
FieldDefinition fieldDef = addInnerNodeField(schemaField);
fieldDefs.put(fieldDef.getName(), fieldDef);
if (isPolymorphicId(schemaField)) {
polymorphicTypeIdFieldDef = fieldDef;
} else if (isInjectedName(schemaField)) {
injectedNameFieldDef = fieldDef;
} else if (isInjectedValue(schemaField)) {
injectedValueField = schemaField;
}
}
MethodDefinition classInitializer = innerNodeClassDef.getClassInitializer();
fieldToFieldDefinitionMap.forEach((k, v) -> {
// Get declared field.
BytecodeExpression getDeclaredFieldExp = constantClass(k.getDeclaringClass())
.invoke(GET_DECLARED_FIELD_MTD, constantString(k.getName()));
classInitializer.getBody().append(BytecodeExpressions.setStatic(v, getDeclaredFieldExp));
});
// org.apache.ignite.internal.configuration.tree.InnerNode#schemaType
addNodeSchemaTypeMethod(polymorphicTypeIdFieldDef);
FieldDefinition extensionSchemaTypesFieldDef = null;
if (!extensions.isEmpty()) {
extensionSchemaTypesFieldDef = innerNodeClassDef.declareField(
EnumSet.of(PRIVATE, FINAL),
"_" + EXTENSION_SCHEMA_TYPES_MTD.getName(),
Class[].class
);
}
// Constructor.
addNodeConstructor(
specFields,
fieldDefs,
extensionSchemaTypesFieldDef
);
// Add view method for internal id.
if (internalIdField != null) {
addNodeInternalIdMethod();
}
// VIEW and CHANGE methods.
for (Field schemaField : concat(schemaFields, publicExtensionFields, internalExtensionFields)) {
String fieldName = schemaField.getName();
FieldDefinition fieldDef = fieldDefs.get(fieldName);
addNodeViewMethod(
innerNodeClassDef,
schemaField,
viewMtd -> getThisFieldCode(viewMtd, fieldDef),
null
);
// Read only.
if (isPolymorphicId(schemaField) || isInjectedName(schemaField)) {
continue;
}
// Add change methods.
List<MethodDefinition> changeMethods = addNodeChangeMethod(
innerNodeClassDef,
schemaField,
changeMtd -> getThisFieldCode(changeMtd, fieldDef),
(changeMtd, newValue) -> setThisFieldCode(changeMtd, newValue, fieldDef),
null
);
// Only first element requires a bridge. Please refer to "addNodeChangeMethod" for explanation.
addNodeChangeBridgeMethod(innerNodeClassDef, changeClassName(schemaField.getDeclaringClass()), changeMethods.get(0));
}
Map<Class<?>, List<Field>> polymorphicFieldsByExtension = Map.of();
MethodDefinition changePolymorphicTypeIdMtd = null;
if (!polymorphicExtensions.isEmpty()) {
assert polymorphicTypeIdFieldDef != null : schemaClass.getName();
addNodeSpecificNodeMethod(polymorphicTypeIdFieldDef);
changePolymorphicTypeIdMtd = addNodeChangePolymorphicTypeIdMethod(fieldDefs, polymorphicTypeIdFieldDef);
addNodeConvertMethods(changePolymorphicTypeIdMtd);
polymorphicFieldsByExtension = new LinkedHashMap<>();
for (Class<?> polymorphicExtension : polymorphicExtensions) {
polymorphicFieldsByExtension.put(
polymorphicExtension,
polymorphicFields.stream()
.filter(f -> polymorphicExtension.equals(f.getDeclaringClass()))
.collect(toList())
);
}
}
// traverseChildren
addNodeTraverseChildrenMethod(
fieldDefs,
polymorphicFieldsByExtension,
polymorphicTypeIdFieldDef
);
// traverseChild
addNodeTraverseChildMethod(
fieldDefs,
polymorphicFieldsByExtension,
polymorphicTypeIdFieldDef
);
// construct
addNodeConstructMethod(
fieldDefs,
polymorphicFieldsByExtension,
polymorphicTypeIdFieldDef,
changePolymorphicTypeIdMtd
);
// constructDefault
addNodeConstructDefaultMethod(
specFields,
fieldDefs,
polymorphicFieldsByExtension,
polymorphicTypeIdFieldDef
);
if (injectedNameFieldDef != null) {
addInjectedNameFieldMethods(injectedNameFieldDef);
}
if (injectedValueField != null) {
implementInjectedValueFieldNameMethod(injectedValueField);
}
if (polymorphicTypeIdFieldDef != null) {
addIsPolymorphicMethod();
}
if (extensionSchemaTypesFieldDef != null) {
addExtensionSchemaTypesMethod(extensionSchemaTypesFieldDef);
}
if (schemaClass.getSuperclass().isAnnotationPresent(AbstractConfiguration.class)) {
addIsExtendAbstractConfigurationMethod();
}
return innerNodeClassDef;
}