tkalkirill commented on a change in pull request #366:
URL: https://github.com/apache/ignite-3/pull/366#discussion_r738494253
##########
File path:
modules/configuration/src/main/java/org/apache/ignite/internal/configuration/asm/ConfigurationAsmGenerator.java
##########
@@ -1244,196 +1780,959 @@ private static String capitalize(String name) {
}
/**
- * Create bytecode blocks that invokes of {@link ConfigurationVisitor}'s
methods for
- * {@link InnerNode#traverseChildren(ConfigurationVisitor, boolean)}.
+ * Get interfaces for {@link InnerNode} definition for a configuration
schema.
*
- * @param schemaFields Fields of the schema.
- * @param fieldDefs Definitions for all fields in {@code schemaFields}.
- * @param traverseChildrenMtd Method definition {@link
InnerNode#traverseChildren(ConfigurationVisitor, boolean)}
- * defined in {@code *Node} class.
- * @return Created bytecode blocks that invokes of {@link
ConfigurationVisitor}'s methods for fields.
+ * @param schemaClass Configuration schema class.
+ * @param schemaExtensions Internal extensions of the configuration schema.
+ * @return Interfaces for {@link InnerNode} definition for a configuration
schema.
+ */
+ private static ParameterizedType[] nodeClassInterfaces(Class<?>
schemaClass, Set<Class<?>> schemaExtensions) {
+ Collection<ParameterizedType> res = new ArrayList<>();
+
+ for (Class<?> cls : concat(List.of(schemaClass), schemaExtensions)) {
+ res.add(typeFromJavaClassName(viewClassName(cls)));
+ res.add(typeFromJavaClassName(changeClassName(cls)));
+ }
+
+ if (isPolymorphicConfigInstance(schemaClass))
+ res.add(type(PolymorphicInstance.class));
+
+ return res.toArray(ParameterizedType[]::new);
+ }
+
+ /**
+ * Get interfaces for {@link DynamicConfiguration} definition for a
configuration schema.
+ *
+ * @param schemaClass Configuration schema class.
+ * @param schemaExtensions Internal extensions of the configuration schema.
+ * @return Interfaces for {@link DynamicConfiguration} definition for a
configuration schema.
+ */
+ private ParameterizedType[] configClassInterfaces(Class<?> schemaClass,
Set<Class<?>> schemaExtensions) {
+ var result = new ArrayList<ParameterizedType>();
+
+ Stream.concat(Stream.of(schemaClass), schemaExtensions.stream())
+ .map(cls -> typeFromJavaClassName(configurationClassName(cls)))
+ .forEach(result::add);
+
+ if (schemasInfo.get(schemaClass).direct)
+ result.add(type(DirectConfigurationProperty.class));
+
+ return result.toArray(new ParameterizedType[0]);
+ }
+
+ /**
+ * Add {@link DynamicConfiguration#configType} method implementation to
the class. It looks like the following code:
+ * <pre><code>
+ * public Class configType() {
+ * return RootConfiguration.class;
+ * }
+ * </code></pre>
+ * @param classDef Class definition.
+ * @param clazz Definition of the configuration interface, for example
{@code RootConfiguration}.
+ */
+ private static void addCfgImplConfigTypeMethod(ClassDefinition classDef,
ParameterizedType clazz) {
+ classDef.declareMethod(of(PUBLIC), "configType", type(Class.class))
+ .getBody()
+ .append(constantClass(clazz))
+ .retObject();
+ }
+
+ /**
+ * Create a {@code *Node} for the polymorphic configuration instance
schema.
+ *
+ * @param schemaClass Polymorphic configuration schema (parent).
+ * @param polymorphicExtension Polymorphic configuration instance schema
(child).
+ * @param schemaInnerNodeClassDef {@link InnerNode} definition for the
polymorphic configuration schema {@code schemaClass}.
+ * @param schemaFields Schema fields of polymorphic configuration {@code
schemaClass}.
+ * @param polymorphicFields Schema fields of a polymorphic configuration
instance {@code polymorphicExtension}.
+ */
+ private ClassDefinition createPolymorphicExtensionNodeClass(
+ Class<?> schemaClass,
+ Class<?> polymorphicExtension,
+ ClassDefinition schemaInnerNodeClassDef,
+ Collection<Field> schemaFields,
+ Collection<Field> polymorphicFields
+ ) {
+ SchemaClassesInfo schemaClassInfo = schemasInfo.get(schemaClass);
+ SchemaClassesInfo polymorphicExtensionClassInfo =
schemasInfo.get(polymorphicExtension);
+
+ // Node class definition.
+ ClassDefinition classDef = new ClassDefinition(
+ of(PUBLIC, FINAL),
+ internalName(polymorphicExtensionClassInfo.nodeClassName),
+ type(Object.class),
+ nodeClassInterfaces(polymorphicExtension, Set.of())
+ );
+
+ // private final ParentNode parent#innerNode;
+ FieldDefinition parentInnerNodeFieldDef = classDef.declareField(
+ of(PRIVATE, FINAL),
+ "parent#innerNode",
+ typeFromJavaClassName(schemaClassInfo.nodeClassName)
+ );
+
+ // Constructor.
+ MethodDefinition constructorMtd = classDef.declareConstructor(
+ of(PUBLIC),
+ arg("parent", typeFromJavaClassName(schemaClassInfo.nodeClassName))
+ );
+
+ Variable parentVar = constructorMtd.getScope().getVariable("parent");
+
+ // Constructor body.
+ constructorMtd.getBody()
+ .append(constructorMtd.getThis())
+ .append(constructorMtd.getThis().setField(
+ parentInnerNodeFieldDef,
+ parentVar
+ ))
+ .invokeConstructor(Object.class)
+ .ret();
+
+ Map<String, FieldDefinition> fieldDefs =
schemaInnerNodeClassDef.getFields().stream()
+ .collect(toMap(FieldDefinition::getName, identity()));
+
+ // Creates view and change methods for parent schema.
+ for (Field schemaField : schemaFields) {
+ // Must be skipped, this is an internal special field.
+ if (isPolymorphicId(schemaField))
+ continue;
+
+ FieldDefinition schemaFieldDef =
fieldDefs.get(fieldName(schemaField));
+
+ addNodeViewMethod(classDef, schemaField, parentInnerNodeFieldDef,
schemaFieldDef);
+
+ MethodDefinition changeMtd = addNodeChangeMethod(
+ classDef,
+ schemaField,
+ polymorphicExtensionClassInfo.nodeClassName,
+ parentInnerNodeFieldDef,
+ schemaFieldDef
+ );
+
+ addNodeChangeBridgeMethod(classDef,
schemaClassInfo.changeClassName, changeMtd);
+ }
+
+ // Creates view and change methods for specific polymorphic instance
schema.
+ for (Field polymorphicField : polymorphicFields) {
+ FieldDefinition polymorphicFieldDef =
fieldDefs.get(fieldName(polymorphicField));
+
+ addNodeViewMethod(classDef, polymorphicField,
parentInnerNodeFieldDef, polymorphicFieldDef);
+
+ MethodDefinition changeMtd = addNodeChangeMethod(
+ classDef,
+ polymorphicField,
+ polymorphicExtensionClassInfo.nodeClassName,
+ parentInnerNodeFieldDef,
+ polymorphicFieldDef
+ );
+
+ addNodeChangeBridgeMethod(classDef,
polymorphicExtensionClassInfo.changeClassName, changeMtd);
+ }
+
+ ParameterizedType returnType =
typeFromJavaClassName(schemaClassInfo.changeClassName);
+
+ // Creates {@code Node#convert}.
+ MethodDefinition convertMtd = classDef.declareMethod(
+ of(PUBLIC),
+ CONVERT_MTD_NAME,
+ returnType,
+ arg("changeClass", Class.class)
+ );
+
+ // Find parent {@code Node#convert}.
+ MethodDefinition parentConvertMtd =
schemaInnerNodeClassDef.getMethods().stream()
+ .filter(mtd -> CONVERT_MTD_NAME.equals(mtd.getName()))
+ .findAny()
+ .orElse(null);
+
+ assert parentConvertMtd != null : schemaInnerNodeClassDef.getName();
+
+ // return this.parent#innerNode.convert(changeClass);
+ convertMtd.getBody()
+ .append(getThisFieldCode(convertMtd, parentInnerNodeFieldDef))
+ .append(convertMtd.getScope().getVariable("changeClass"))
+ .invokeVirtual(parentConvertMtd)
+ .retObject();
+
+ return classDef;
+ }
+
+ /**
+ * Create a {@code *CfgImpl} for the polymorphic configuration instance
schema.
+ *
+ * @param schemaClass Polymorphic configuration schema (parent).
+ * @param polymorphicExtension Polymorphic configuration instance schema
(child).
+ * @param schemaCfgImplClassDef {@link DynamicConfiguration} definition
for the polymorphic configuration schema {@code schemaClass}.
+ * @param schemaFields Schema fields of polymorphic configuration {@code
schemaClass}.
+ * @param polymorphicFields Schema fields of a polymorphic configuration
instance {@code polymorphicExtension}.
*/
- private static Collection<BytecodeNode> invokeVisitForTraverseChildren(
+ private ClassDefinition createPolymorphicExtensionCfgImplClass(
+ Class<?> schemaClass,
+ Class<?> polymorphicExtension,
+ ClassDefinition schemaCfgImplClassDef,
Collection<Field> schemaFields,
+ Collection<Field> polymorphicFields
+ ) {
+ SchemaClassesInfo schemaClassInfo = schemasInfo.get(schemaClass);
+ SchemaClassesInfo polymorphicExtensionClassInfo =
schemasInfo.get(polymorphicExtension);
+
+ Class<?> superClass = schemaClassInfo.direct ||
polymorphicExtensionClassInfo.direct
+ ? DirectConfigurationTreeWrapper.class :
ConfigurationTreeWrapper.class;
+
+ // Configuration impl class definition.
+ ClassDefinition classDef = new ClassDefinition(
+ of(PUBLIC, FINAL),
+ internalName(polymorphicExtensionClassInfo.cfgImplClassName),
+ type(superClass),
+ configClassInterfaces(polymorphicExtension, Set.of())
+ );
+
+ // private final ParentCfgImpl parent#cfgImpl;
+ FieldDefinition parentCfgImplFieldDef = classDef.declareField(
+ of(PRIVATE, FINAL),
+ "parent#cfgImpl",
+ typeFromJavaClassName(schemaClassInfo.cfgImplClassName)
+ );
+
+ // Constructor.
+ MethodDefinition constructorMtd = classDef.declareConstructor(
+ of(PUBLIC),
+ arg("parent",
typeFromJavaClassName(schemaClassInfo.cfgImplClassName))
+ );
+
+ Variable parentVar = constructorMtd.getScope().getVariable("parent");
+
+ // Constructor body.
+ // super(parent);
+ // this.parent#cfgImpl = parent;
+ constructorMtd.getBody()
+ .append(constructorMtd.getThis())
+ .append(parentVar)
+ .invokeConstructor(superClass, ConfigurationTree.class)
+ .append(constructorMtd.getThis().setField(
+ parentCfgImplFieldDef,
+ parentVar
+ ))
+ .ret();
+
+ Map<String, FieldDefinition> fieldDefs =
schemaCfgImplClassDef.getFields().stream()
+ .collect(toMap(FieldDefinition::getName, identity()));
+
+ for (Field schemaField : concat(schemaFields, polymorphicFields)) {
+ // Must be skipped, this is an internal special field.
+ if (isPolymorphicId(schemaField))
+ continue;
+
+ addConfigurationImplGetMethod(
+ classDef,
+ schemaField,
+ parentCfgImplFieldDef,
+ fieldDefs.get(fieldName(schemaField))
+ );
+ }
+
+ return classDef;
+ }
+
+ /**
+ * Adds a {@link InnerNode#specificNode} override for the polymorphic
configuration case.
+ *
+ * @param classDef Definition of a polymorphic
configuration class (parent).
+ * @param polymorphicExtensions Polymorphic configuration instance
schemas (children).
+ * @param polymorphicTypeIdFieldDef Identification field for the
polymorphic configuration instance.
+ */
+ private void addNodeSpecificNodeMethod(
+ ClassDefinition classDef,
+ Set<Class<?>> polymorphicExtensions,
+ FieldDefinition polymorphicTypeIdFieldDef
+ ) {
+ MethodDefinition specificNodeMtd = classDef.declareMethod(
+ of(PUBLIC),
+ SPECIFIC_NODE_MTD.getName(),
+ type(Object.class)
+ );
+
+ StringSwitchBuilder switchBuilder =
typeIdSwitchBuilder(specificNodeMtd, polymorphicTypeIdFieldDef);
+
+ for (Class<?> polymorphicExtension : polymorphicExtensions) {
+ SchemaClassesInfo polymorphicExtensionClassInfo =
schemasInfo.get(polymorphicExtension);
+
+ switchBuilder.addCase(
+ polymorphicInstanceId(polymorphicExtension),
+ newInstance(
+
typeFromJavaClassName(polymorphicExtensionClassInfo.nodeClassName),
+ specificNodeMtd.getThis()
+ ).ret()
+ );
+ }
+
+ specificNodeMtd.getBody()
+ .append(switchBuilder.build())
Review comment:
Here i use a **ConfigurationAsmGenerator#typeIdSwitchBuilder** in which
there is a default statement
--
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]