use of org.apache.ignite.internal.configuration.DynamicConfiguration in project ignite-3 by apache.
the class ConfigurationAsmGenerator method compileRootSchema.
/**
* Generates, defines, loads and initializes all dynamic classes required for the given configuration schema.
*
* @param rootSchemaClass Class of the root configuration schema.
* @param internalSchemaExtensions Internal extensions ({@link InternalConfiguration}) of configuration schemas ({@link
* ConfigurationRoot} and {@link Config}). Mapping: original schema -> extensions.
* @param polymorphicSchemaExtensions Polymorphic extensions ({@link PolymorphicConfigInstance}) of configuration schemas ({@link
* PolymorphicConfig}). Mapping: original schema -> extensions.
*/
public synchronized void compileRootSchema(Class<?> rootSchemaClass, Map<Class<?>, Set<Class<?>>> internalSchemaExtensions, Map<Class<?>, Set<Class<?>>> polymorphicSchemaExtensions) {
if (schemasInfo.containsKey(rootSchemaClass)) {
// Already compiled.
return;
}
Queue<Class<?>> compileQueue = new ArrayDeque<>();
compileQueue.add(rootSchemaClass);
schemasInfo.put(rootSchemaClass, new SchemaClassesInfo(rootSchemaClass));
Set<Class<?>> schemas = new HashSet<>();
List<ClassDefinition> classDefs = new ArrayList<>();
while (!compileQueue.isEmpty()) {
Class<?> schemaClass = compileQueue.poll();
assert schemaClass.isAnnotationPresent(ConfigurationRoot.class) || schemaClass.isAnnotationPresent(Config.class) || isPolymorphicConfig(schemaClass) : schemaClass + " is not properly annotated";
assert schemasInfo.containsKey(schemaClass) : schemaClass;
Set<Class<?>> internalExtensions = internalSchemaExtensions.getOrDefault(schemaClass, Set.of());
Set<Class<?>> polymorphicExtensions = polymorphicSchemaExtensions.getOrDefault(schemaClass, Set.of());
assert internalExtensions.isEmpty() || polymorphicExtensions.isEmpty() : "Internal and polymorphic extensions are not allowed at the same time: " + schemaClass;
if (isPolymorphicConfig(schemaClass) && polymorphicExtensions.isEmpty()) {
throw new IllegalArgumentException(schemaClass + " is polymorphic but polymorphic extensions are absent");
}
List<Field> schemaFields = schemaFields(schemaClass);
Collection<Field> internalExtensionsFields = extensionsFields(internalExtensions, true);
Collection<Field> polymorphicExtensionsFields = extensionsFields(polymorphicExtensions, false);
Field internalIdField = internalIdField(schemaClass, internalExtensions);
for (Field schemaField : concat(schemaFields, internalExtensionsFields, polymorphicExtensionsFields)) {
if (isConfigValue(schemaField) || isNamedConfigValue(schemaField)) {
Class<?> subSchemaClass = schemaField.getType();
if (!schemasInfo.containsKey(subSchemaClass)) {
compileQueue.offer(subSchemaClass);
schemasInfo.put(subSchemaClass, new SchemaClassesInfo(subSchemaClass));
}
}
}
for (Class<?> polymorphicExtension : polymorphicExtensions) {
schemasInfo.put(polymorphicExtension, new SchemaClassesInfo(polymorphicExtension));
}
schemas.add(schemaClass);
ClassDefinition innerNodeClassDef = createNodeClass(schemaClass, internalExtensions, polymorphicExtensions, schemaFields, internalExtensionsFields, polymorphicExtensionsFields, internalIdField);
classDefs.add(innerNodeClassDef);
ClassDefinition cfgImplClassDef = createCfgImplClass(schemaClass, internalExtensions, polymorphicExtensions, schemaFields, internalExtensionsFields, polymorphicExtensionsFields, internalIdField);
classDefs.add(cfgImplClassDef);
for (Class<?> polymorphicExtension : polymorphicExtensions) {
// Only the fields of a specific instance of a polymorphic configuration.
Collection<Field> polymorphicFields = polymorphicExtensionsFields.stream().filter(f -> f.getDeclaringClass() == polymorphicExtension).collect(toList());
classDefs.add(createPolymorphicExtensionNodeClass(schemaClass, polymorphicExtension, innerNodeClassDef, schemaFields, polymorphicFields, internalIdField));
classDefs.add(createPolymorphicExtensionCfgImplClass(schemaClass, polymorphicExtension, cfgImplClassDef, schemaFields, polymorphicFields, internalIdField));
}
ClassDefinition directProxyClassDef = new DirectProxyAsmGenerator(this, schemaClass, internalExtensions, schemaFields, internalExtensionsFields, internalIdField).generate();
classDefs.add(directProxyClassDef);
}
Map<String, Class<?>> definedClasses = generator.defineClasses(classDefs);
for (Class<?> schemaClass : schemas) {
SchemaClassesInfo info = schemasInfo.get(schemaClass);
info.nodeClass = (Class<? extends InnerNode>) definedClasses.get(info.nodeClassName);
info.cfgImplClass = (Class<? extends DynamicConfiguration<?, ?>>) definedClasses.get(info.cfgImplClassName);
}
}
use of org.apache.ignite.internal.configuration.DynamicConfiguration in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addCfgAddMembersMethod.
/**
* Adds a {@code DynamicConfiguration#addMembers} override for the polymorphic configuration case.
*
* @param classDef Definition of a polymorphic configuration class (parent).
* @param schemaClass Polymorphic configuration schema (parent).
* @param polymorphicExtensions Polymorphic configuration instance schemas (children).
* @param fieldDefs Field definitions for all fields of {@code classDef}.
* @param polymorphicFields Fields of polymorphic extensions.
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
*/
private void addCfgAddMembersMethod(ClassDefinition classDef, Class<?> schemaClass, Set<Class<?>> polymorphicExtensions, Map<String, FieldDefinition> fieldDefs, Collection<Field> polymorphicFields, FieldDefinition polymorphicTypeIdFieldDef) {
MethodDefinition removeMembersMtd = classDef.declareMethod(of(PUBLIC), "addMembers", type(void.class), arg("newValue", type(Object.class)), arg("members", type(Map.class)));
// InnerNode newValue;
Variable newValueVar = removeMembersMtd.getScope().getVariable("newValue");
// Map members;
Variable membersVar = removeMembersMtd.getScope().getVariable("members");
// String tmpStr;
Variable tmpStrVar = removeMembersMtd.getScope().createTempVariable(String.class);
StringSwitchBuilder switchBuilder = new StringSwitchBuilder(removeMembersMtd.getScope()).expression(tmpStrVar).defaultCase(throwException(ConfigurationWrongPolymorphicTypeIdException.class, tmpStrVar));
for (Class<?> polymorphicExtension : polymorphicExtensions) {
Collection<Field> addFields = polymorphicFields.stream().filter(f -> polymorphicExtension.equals(f.getDeclaringClass())).collect(toList());
BytecodeBlock blockCode = new BytecodeBlock();
for (Field addField : addFields) {
// this.addMember(members, this.field);
blockCode.append(removeMembersMtd.getThis()).append(membersVar).append(getThisFieldCode(removeMembersMtd, fieldDefs.get(fieldName(addField)))).invokeVirtual(ADD_MEMBER_MTD);
}
switchBuilder.addCase(polymorphicInstanceId(polymorphicExtension), blockCode);
}
// ConfigNode
ParameterizedType nodeType = typeFromJavaClassName(schemasInfo.get(schemaClass).nodeClassName);
// tmpStr = ((ConfigNode) newValue).typeId;
// switch(tmpStr) ...
removeMembersMtd.getBody().append(tmpStrVar.set(newValueVar.cast(nodeType).getField(polymorphicTypeIdFieldDef.getName(), String.class))).append(switchBuilder.build()).ret();
}
use of org.apache.ignite.internal.configuration.DynamicConfiguration in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addCfgRemoveMembersMethod.
/**
* Adds a {@code DynamicConfiguration#removeMembers} override for the polymorphic configuration case.
*
* @param classDef Definition of a polymorphic configuration class (parent).
* @param schemaClass Polymorphic configuration schema (parent).
* @param polymorphicExtensions Polymorphic configuration instance schemas (children).
* @param fieldDefs Field definitions for all fields of {@code classDef}.
* @param polymorphicFields Fields of polymorphic extensions.
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
*/
private void addCfgRemoveMembersMethod(ClassDefinition classDef, Class<?> schemaClass, Set<Class<?>> polymorphicExtensions, Map<String, FieldDefinition> fieldDefs, Collection<Field> polymorphicFields, FieldDefinition polymorphicTypeIdFieldDef) {
MethodDefinition removeMembersMtd = classDef.declareMethod(of(PUBLIC), "removeMembers", type(void.class), arg("oldValue", type(Object.class)), arg("members", type(Map.class)));
// InnerNode oldValue;
Variable oldValueVar = removeMembersMtd.getScope().getVariable("oldValue");
// Map members;
Variable membersVar = removeMembersMtd.getScope().getVariable("members");
// String tmpStr;
Variable tmpStrVar = removeMembersMtd.getScope().createTempVariable(String.class);
StringSwitchBuilder switchBuilder = new StringSwitchBuilder(removeMembersMtd.getScope()).expression(tmpStrVar).defaultCase(throwException(ConfigurationWrongPolymorphicTypeIdException.class, tmpStrVar));
for (Class<?> polymorphicExtension : polymorphicExtensions) {
Collection<Field> removeFields = polymorphicFields.stream().filter(f -> !polymorphicExtension.equals(f.getDeclaringClass())).collect(toList());
BytecodeBlock blockCode = new BytecodeBlock();
for (Field removeField : removeFields) {
// this.removeMember(members, this.field);
blockCode.append(removeMembersMtd.getThis()).append(membersVar).append(getThisFieldCode(removeMembersMtd, fieldDefs.get(fieldName(removeField)))).invokeVirtual(REMOVE_MEMBER_MTD);
}
switchBuilder.addCase(polymorphicInstanceId(polymorphicExtension), blockCode);
}
// ConfigNode
ParameterizedType nodeType = typeFromJavaClassName(schemasInfo.get(schemaClass).nodeClassName);
// tmpStr = ((ConfigNode) oldValue).typeId;
// switch(tmpStr) ...
removeMembersMtd.getBody().append(tmpStrVar.set(oldValueVar.cast(nodeType).getField(polymorphicTypeIdFieldDef.getName(), String.class))).append(switchBuilder.build()).ret();
}
use of org.apache.ignite.internal.configuration.DynamicConfiguration in project ignite-3 by apache.
the class ConfigurationAsmGenerator method createCfgImplClass.
/**
* Construct a {@link DynamicConfiguration} definition for a configuration schema.
*
* @param schemaClass Configuration schema class.
* @param internalExtensions Internal extensions of the configuration schema.
* @param schemaFields Fields of the schema class.
* @param internalFields Fields of internal extensions of the configuration schema.
* @param polymorphicFields Fields of polymorphic extensions of the configuration schema.
* @param internalIdField Internal id field or {@code null} if it's not present.
* @return Constructed {@link DynamicConfiguration} definition for the configuration schema.
*/
private ClassDefinition createCfgImplClass(Class<?> schemaClass, Set<Class<?>> internalExtensions, Set<Class<?>> polymorphicExtensions, Collection<Field> schemaFields, Collection<Field> internalFields, Collection<Field> polymorphicFields, @Nullable Field internalIdField) {
SchemaClassesInfo schemaClassInfo = schemasInfo.get(schemaClass);
// Configuration impl class definition.
ClassDefinition classDef = new ClassDefinition(of(PUBLIC, FINAL), internalName(schemaClassInfo.cfgImplClassName), type(DynamicConfiguration.class), configClassInterfaces(schemaClass, internalExtensions));
// Fields.
Map<String, FieldDefinition> fieldDefs = new HashMap<>();
// To store the id of the polymorphic configuration instance.
FieldDefinition polymorphicTypeIdFieldDef = null;
for (Field schemaField : concat(schemaFields, internalFields, polymorphicFields)) {
String fieldName = fieldName(schemaField);
FieldDefinition fieldDef = addConfigurationImplField(classDef, schemaField, fieldName);
fieldDefs.put(fieldName, fieldDef);
if (isPolymorphicId(schemaField)) {
polymorphicTypeIdFieldDef = fieldDef;
}
}
if (internalIdField != null) {
// Internal id dynamic property is stored as a regular field.
String fieldName = internalIdField.getName();
FieldDefinition fieldDef = addConfigurationImplField(classDef, internalIdField, fieldName);
fieldDefs.put(fieldName, fieldDef);
}
FieldDefinition internalConfigTypesFieldDef = null;
if (!internalExtensions.isEmpty()) {
internalConfigTypesFieldDef = classDef.declareField(of(PRIVATE, FINAL), INTERNAL_CONFIG_TYPES_FIELD_NAME, Class[].class);
}
// Constructor
addConfigurationImplConstructor(classDef, schemaClass, internalExtensions, fieldDefs, schemaFields, internalFields, polymorphicFields, internalIdField, internalConfigTypesFieldDef);
// org.apache.ignite.internal.configuration.DynamicProperty#directProxy
addDirectProxyMethod(schemaClassInfo, classDef);
// Getter for the internal id.
if (internalIdField != null) {
addConfigurationImplGetMethod(classDef, internalIdField, fieldDefs.get(internalIdField.getName()));
}
for (Field schemaField : concat(schemaFields, internalFields)) {
addConfigurationImplGetMethod(classDef, schemaField, fieldDefs.get(fieldName(schemaField)));
}
// org.apache.ignite.internal.configuration.DynamicConfiguration#configType
addCfgImplConfigTypeMethod(classDef, typeFromJavaClassName(schemaClassInfo.cfgClassName));
if (internalConfigTypesFieldDef != null) {
addCfgImplInternalConfigTypesMethod(classDef, internalConfigTypesFieldDef);
}
if (!polymorphicExtensions.isEmpty()) {
addCfgSpecificConfigTreeMethod(classDef, schemaClass, polymorphicExtensions, polymorphicTypeIdFieldDef);
addCfgRemoveMembersMethod(classDef, schemaClass, polymorphicExtensions, fieldDefs, polymorphicFields, polymorphicTypeIdFieldDef);
addCfgAddMembersMethod(classDef, schemaClass, polymorphicExtensions, fieldDefs, polymorphicFields, polymorphicTypeIdFieldDef);
addCfgImplPolymorphicInstanceConfigTypeMethod(classDef, schemaClass, polymorphicExtensions, polymorphicTypeIdFieldDef);
}
return classDef;
}
Aggregations