use of org.apache.ignite.internal.configuration.tree.NamedListNode in project ignite-3 by apache.
the class ConfigurationUtil method findEx.
/**
* Finds a node or a leaf by the given path.
*
* @param path Path.
* @param rootNode Root node.
* @param <T> Arbitrary result type.
* @return Node or leaf.
*/
@Nullable
public static <T> T findEx(List<KeyPathNode> path, InnerNode rootNode) {
try {
var visitor = new ConfigurationVisitor<T>() {
private final int pathSize = path.size();
/**
* Current index of the key in the {@code path}.
*/
private int idx;
/**
* {@inheritDoc}
*/
@Override
public T visitLeafNode(String key, Serializable val) {
if (idx != pathSize) {
throw new KeyNotFoundException("Configuration value '" + joinPath(path.subList(0, idx)) + "' is a leaf");
} else {
return (T) val;
}
}
/**
* {@inheritDoc}
*/
@Override
public T visitInnerNode(String key, InnerNode node) {
if (node == null) {
throw new KeyNotFoundException("Configuration node '" + joinPath(path.subList(0, idx)) + "' is null");
} else if (idx == pathSize) {
return (T) node;
} else {
try {
KeyPathNode pathNode = path.get(idx++);
assert !pathNode.unresolvedName;
if (INTERNAL_ID.equals(pathNode.key)) {
// It's impossible to get this value with a regular traversal. Just call a method.
return (T) node.internalId();
} else if (INJECTED_NAME.equals(pathNode.key)) {
// It's impossible to get this value with a regular traversal. Just call a method.
return (T) node.getInjectedNameFieldValue();
}
return node.traverseChild(pathNode.key, this, true);
} catch (NoSuchElementException e) {
throw new KeyNotFoundException("Configuration value '" + joinPath(path.subList(0, idx)) + "' has not been found");
} catch (ConfigurationWrongPolymorphicTypeIdException e) {
assert false : e;
return null;
}
}
}
/**
* {@inheritDoc}
*/
@Override
public T visitNamedListNode(String key, NamedListNode<?> node) {
if (idx == pathSize) {
return (T) node;
} else {
KeyPathNode pathNode = path.get(idx++);
assert pathNode.namedListEntry;
String name = pathNode.unresolvedName ? pathNode.key : node.keyByInternalId(UUID.fromString(pathNode.key));
return visitInnerNode(name, node.getInnerNode(name));
}
}
};
return rootNode.accept(null, visitor);
} catch (KeyNotFoundException e) {
throw new NoSuchElementException(joinPath(path));
}
}
use of org.apache.ignite.internal.configuration.tree.NamedListNode in project ignite-3 by apache.
the class ConfigurationUtilTest method testFlattenedMapPolymorphicNamedConfig.
@Test
void testFlattenedMapPolymorphicNamedConfig() {
InnerNode polymorphicRootInnerNode = newNodeInstance(PolymorphicRootConfigurationSchema.class);
PolymorphicRootChange polymorphicRootChange = ((PolymorphicRootChange) polymorphicRootInnerNode);
polymorphicRootChange.changePolymorphicNamedCfg(c -> c.create("0", c1 -> {
}));
addDefaults(polymorphicRootInnerNode);
RootKey<?, ?> rootKey = PolymorphicRootConfiguration.KEY;
SuperRoot superRoot = new SuperRoot(key -> null, Map.of(rootKey, polymorphicRootInnerNode));
final Map<String, Serializable> act = flattenedMap(superRoot, rootKey, node -> ((PolymorphicRootChange) node).changePolymorphicNamedCfg(c -> c.createOrUpdate("0", c1 -> c1.convert(SecondPolymorphicInstanceChange.class))));
NamedListNode<?> polymorphicNamedCfgListNode = (NamedListNode<?>) polymorphicRootChange.polymorphicNamedCfg();
UUID internalId = polymorphicNamedCfgListNode.internalId("0");
Map<String, Serializable> exp = new HashMap<>();
exp.put("rootPolymorphic.polymorphicNamedCfg." + internalId + ".typeId", "second");
exp.put("rootPolymorphic.polymorphicNamedCfg." + internalId + ".longVal", 0L);
exp.put("rootPolymorphic.polymorphicNamedCfg." + internalId + ".strVal", null);
exp.put("rootPolymorphic.polymorphicNamedCfg." + internalId + ".intVal", 0);
assertEquals(exp, act);
}
use of org.apache.ignite.internal.configuration.tree.NamedListNode in project ignite-3 by apache.
the class HoconListConfigurationSource method descend.
/**
* {@inheritDoc}
*/
@Override
public void descend(ConstructableTreeNode node) {
if (!(node instanceof NamedListNode)) {
throw new IllegalArgumentException(format("'%s' configuration is expected to be a composite configuration node, not a list", join(path)));
}
String syntheticKeyName = ((NamedListNode<?>) node).syntheticKeyName();
int idx = 0;
for (Iterator<ConfigValue> iterator = hoconCfgList.iterator(); iterator.hasNext(); idx++) {
ConfigValue next = iterator.next();
if (next.valueType() != ConfigValueType.OBJECT) {
throw new IllegalArgumentException(format("'%s' is expected to be a composite configuration node, not a single value", formatArrayPath(path, idx)));
}
ConfigObject hoconCfg = (ConfigObject) next;
ConfigValue keyValue = hoconCfg.get(syntheticKeyName);
if (keyValue == null || keyValue.valueType() != ConfigValueType.STRING) {
throw new IllegalArgumentException(format("'%s' configuration value is mandatory and must be a String", formatArrayPath(path, idx) + KEY_SEPARATOR + syntheticKeyName));
}
String key = (String) keyValue.unwrapped();
List<String> path = appendKey(this.path, syntheticKeyName);
node.construct(key, new HoconObjectConfigurationSource(syntheticKeyName, path, hoconCfg), false);
}
}
use of org.apache.ignite.internal.configuration.tree.NamedListNode in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addNodeChangePolymorphicTypeIdMethod.
/**
* Adds a {@code Node#changeTypeId} for the polymorphic configuration case.
*
* @param classDef Definition of a polymorphic configuration class (parent).
* @param fieldDefs Definitions for all fields in {@code classDef}.
* @param polymorphicExtensions Polymorphic configuration instance schemas (children).
* @param polymorphicFields Fields of polymorphic extensions.
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
* @return Method definition.
*/
private MethodDefinition addNodeChangePolymorphicTypeIdMethod(ClassDefinition classDef, Map<String, FieldDefinition> fieldDefs, Set<Class<?>> polymorphicExtensions, Collection<Field> polymorphicFields, FieldDefinition polymorphicTypeIdFieldDef) {
MethodDefinition changePolymorphicTypeIdMtd = classDef.declareMethod(of(PUBLIC), changeMethodName(polymorphicTypeIdFieldDef.getName()), type(void.class), arg("typeId", String.class));
Variable typeIdVar = changePolymorphicTypeIdMtd.getScope().getVariable("typeId");
StringSwitchBuilder switchBuilder = new StringSwitchBuilder(changePolymorphicTypeIdMtd.getScope()).expression(typeIdVar).defaultCase(throwException(ConfigurationWrongPolymorphicTypeIdException.class, typeIdVar));
for (Class<?> polymorphicExtension : polymorphicExtensions) {
// Fields that need to be cleared when changing the type of the polymorphic configuration instance.
Collection<Field> resetFields = polymorphicFields.stream().filter(f -> !polymorphicExtension.equals(f.getDeclaringClass())).collect(toList());
// this.typeId = typeId;
BytecodeBlock codeBlock = new BytecodeBlock().append(setThisFieldCode(changePolymorphicTypeIdMtd, typeIdVar, polymorphicTypeIdFieldDef));
// Reset fields.
for (Field resetField : resetFields) {
FieldDefinition fieldDef = fieldDefs.get(fieldName(resetField));
if (isValue(resetField) || isConfigValue(resetField)) {
// this.field = null;
codeBlock.append(setThisFieldCode(changePolymorphicTypeIdMtd, constantNull(fieldDef.getType()), fieldDef));
} else {
// this.field = new NamedListNode<>(key, ValueNode::new, "polymorphicIdFieldName");
codeBlock.append(setThisFieldCode(changePolymorphicTypeIdMtd, newNamedListNode(resetField), fieldDef));
}
}
// ConfigurationUtil.addDefaults(this);
codeBlock.append(changePolymorphicTypeIdMtd.getThis()).invokeStatic(ADD_DEFAULTS_MTD);
switchBuilder.addCase(polymorphicInstanceId(polymorphicExtension), codeBlock);
}
// if(typeId.equals(this.typeId)) return;
// else switch(typeId)...
changePolymorphicTypeIdMtd.getBody().append(typeIdVar).append(getThisFieldCode(changePolymorphicTypeIdMtd, polymorphicTypeIdFieldDef)).append(new IfStatement().condition(new BytecodeBlock().invokeVirtual(STRING_EQUALS_MTD)).ifTrue(new BytecodeBlock().ret()).ifFalse(switchBuilder.build().ret()));
return changePolymorphicTypeIdMtd;
}
use of org.apache.ignite.internal.configuration.tree.NamedListNode in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addNodeField.
/**
* Declares field that corresponds to configuration value. Depending on the schema, 5 options possible:
* <ul>
* <li>
* {@code @Value public type fieldName}<br/>becomes<br/>
* {@code public BoxedType fieldName}
* </li>
* <li>
* {@code @ConfigValue public MyConfigurationSchema fieldName}<br/>becomes<br/>
* {@code public MyNode fieldName}
* </li>
* <li>
* {@code @NamedConfigValue public type fieldName}<br/>becomes<br/>
* {@code public NamedListNode fieldName}
* </li>
* <li>
* {@code @PolymorphicId public String fieldName}<br/>becomes<br/>
* {@code public String fieldName}
* </li>
* <li>
* {@code @InjectedName public String fieldName}<br/>becomes<br/>
* {@code public String fieldName}
* </li>
* </ul>
*
* @param classDef Node class definition.
* @param schemaField Configuration Schema class field.
* @param fieldName Field name.
* @return Declared field definition.
* @throws IllegalArgumentException If an unsupported {@code schemaField} was passed.
*/
private FieldDefinition addNodeField(ClassDefinition classDef, Field schemaField, String fieldName) {
Class<?> schemaFieldClass = schemaField.getType();
ParameterizedType nodeFieldType;
if (isValue(schemaField) || isPolymorphicId(schemaField) || isInjectedName(schemaField)) {
nodeFieldType = type(box(schemaFieldClass));
} else if (isConfigValue(schemaField)) {
nodeFieldType = typeFromJavaClassName(schemasInfo.get(schemaFieldClass).nodeClassName);
} else if (isNamedConfigValue(schemaField)) {
nodeFieldType = type(NamedListNode.class);
} else {
throw new IllegalArgumentException("Unsupported field: " + schemaField);
}
return classDef.declareField(of(PUBLIC), fieldName, nodeFieldType);
}
Aggregations