use of org.apache.ignite.internal.configuration.tree.ConfigurationVisitor 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.ConfigurationVisitor in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addNodeTraverseChildMethod.
/**
* Implements {@link InnerNode#traverseChild(String, ConfigurationVisitor, boolean)} method.
*
* @param classDef Class definition.
* @param fieldDefs Definitions for all fields in {@code schemaFields}.
* @param schemaFields Fields of the schema class.
* @param internalFields Fields of internal extensions of the configuration schema.
* @param polymorphicFieldsByExtension Fields of polymorphic configuration instances grouped by them.
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
*/
private static void addNodeTraverseChildMethod(ClassDefinition classDef, Map<String, FieldDefinition> fieldDefs, Collection<Field> schemaFields, Collection<Field> internalFields, Map<Class<?>, List<Field>> polymorphicFieldsByExtension, @Nullable FieldDefinition polymorphicTypeIdFieldDef) {
MethodDefinition traverseChildMtd = classDef.declareMethod(of(PUBLIC), "traverseChild", type(Object.class), arg("key", type(String.class)), arg("visitor", type(ConfigurationVisitor.class)), arg("includeInternal", type(boolean.class))).addException(NoSuchElementException.class);
Variable keyVar = traverseChildMtd.getScope().getVariable("key");
// Create switch for public (common in case polymorphic config) fields only.
StringSwitchBuilder switchBuilder = new StringSwitchBuilder(traverseChildMtd.getScope()).expression(keyVar);
for (Field schemaField : schemaFields) {
if (isInjectedName(schemaField)) {
continue;
}
String fieldName = fieldName(schemaField);
switchBuilder.addCase(fieldName, invokeVisit(traverseChildMtd, schemaField, fieldDefs.get(fieldName)).retObject());
}
if (!internalFields.isEmpty()) {
// Create switch for public + internal fields.
StringSwitchBuilder switchBuilderAllFields = new StringSwitchBuilder(traverseChildMtd.getScope()).expression(keyVar).defaultCase(throwException(NoSuchElementException.class, keyVar));
for (Field schemaField : union(schemaFields, internalFields)) {
if (isInjectedName(schemaField)) {
continue;
}
String fieldName = fieldName(schemaField);
switchBuilderAllFields.addCase(fieldName, invokeVisit(traverseChildMtd, schemaField, fieldDefs.get(fieldName)).retObject());
}
// if (includeInternal) switch_by_all_fields
// else switch_only_public_fields
traverseChildMtd.getBody().append(new IfStatement().condition(traverseChildMtd.getScope().getVariable("includeInternal")).ifTrue(switchBuilderAllFields.build()).ifFalse(switchBuilder.defaultCase(throwException(NoSuchElementException.class, keyVar)).build()));
} else if (!polymorphicFieldsByExtension.isEmpty()) {
assert polymorphicTypeIdFieldDef != null : classDef.getName();
// Create switch by polymorphicTypeIdField.
StringSwitchBuilder switchBuilderTypeId = typeIdSwitchBuilder(traverseChildMtd, polymorphicTypeIdFieldDef);
for (Map.Entry<Class<?>, List<Field>> e : polymorphicFieldsByExtension.entrySet()) {
// Create switch for specific polymorphic instance.
StringSwitchBuilder switchBuilderPolymorphicExtension = new StringSwitchBuilder(traverseChildMtd.getScope()).expression(keyVar).defaultCase(throwException(NoSuchElementException.class, keyVar));
for (Field polymorphicField : e.getValue()) {
String fieldName = fieldName(polymorphicField);
switchBuilderPolymorphicExtension.addCase(polymorphicField.getName(), invokeVisit(traverseChildMtd, polymorphicField, fieldDefs.get(fieldName)).retObject());
}
switchBuilderTypeId.addCase(polymorphicInstanceId(e.getKey()), switchBuilderPolymorphicExtension.build());
}
// switch_by_common_fields
// switch_by_polymorphicTypeIdField
// switch_by_polymorphic_0_fields
// switch_by_polymorphic_1_fields
// ...
traverseChildMtd.getBody().append(switchBuilder.defaultCase(new BytecodeBlock()).build()).append(switchBuilderTypeId.build());
} else {
traverseChildMtd.getBody().append(switchBuilder.defaultCase(throwException(NoSuchElementException.class, keyVar)).build());
}
}
use of org.apache.ignite.internal.configuration.tree.ConfigurationVisitor in project ignite-3 by apache.
the class ConfigurationAsmGenerator method addNodeTraverseChildrenMethod.
/**
* Implements {@link InnerNode#traverseChildren(ConfigurationVisitor, boolean)} method.
*
* @param classDef Class definition.
* @param schemaClass Configuration schema class.
* @param fieldDefs Definitions for all fields in {@code schemaFields}.
* @param schemaFields Fields of the schema class.
* @param internalFields Fields of internal extensions of the configuration schema.
* @param polymorphicFieldsByExtension Fields of polymorphic configuration instances grouped by them.
* @param polymorphicTypeIdFieldDef Identification field for the polymorphic configuration instance.
*/
private static void addNodeTraverseChildrenMethod(ClassDefinition classDef, Class<?> schemaClass, Map<String, FieldDefinition> fieldDefs, List<Field> schemaFields, Collection<Field> internalFields, Map<Class<?>, List<Field>> polymorphicFieldsByExtension, @Nullable FieldDefinition polymorphicTypeIdFieldDef) {
MethodDefinition traverseChildrenMtd = classDef.declareMethod(of(PUBLIC), "traverseChildren", type(void.class), arg("visitor", type(ConfigurationVisitor.class)), arg("includeInternal", type(boolean.class))).addException(NoSuchElementException.class);
BytecodeBlock mtdBody = traverseChildrenMtd.getBody();
// invokeVisit for public (common in case polymorphic config) fields.
for (Field schemaField : schemaFields) {
if (isInjectedName(schemaField)) {
continue;
}
mtdBody.append(invokeVisit(traverseChildrenMtd, schemaField, fieldDefs.get(schemaField.getName())).pop());
}
if (!internalFields.isEmpty()) {
BytecodeBlock includeInternalBlock = new BytecodeBlock();
for (Field internalField : internalFields) {
includeInternalBlock.append(invokeVisit(traverseChildrenMtd, internalField, fieldDefs.get(internalField.getName())).pop());
}
// if (includeInternal) invokeVisit for internal fields.
mtdBody.append(new IfStatement().condition(traverseChildrenMtd.getScope().getVariable("includeInternal")).ifTrue(includeInternalBlock));
} else if (!polymorphicFieldsByExtension.isEmpty()) {
assert polymorphicTypeIdFieldDef != null : schemaClass.getName();
assert isPolymorphicId(schemaFields.get(0)) : schemaClass.getName();
// Create switch by polymorphicTypeIdField.
StringSwitchBuilder switchBuilderTypeId = typeIdSwitchBuilder(traverseChildrenMtd, polymorphicTypeIdFieldDef);
for (Map.Entry<Class<?>, List<Field>> e : polymorphicFieldsByExtension.entrySet()) {
BytecodeBlock codeBlock = new BytecodeBlock();
for (Field polymorphicField : e.getValue()) {
String fieldName = fieldName(polymorphicField);
// invokeVisit for specific polymorphic config fields.
codeBlock.append(invokeVisit(traverseChildrenMtd, polymorphicField, fieldDefs.get(fieldName)).pop());
}
switchBuilderTypeId.addCase(polymorphicInstanceId(e.getKey()), codeBlock);
}
// if (polymorphicTypeIdField != null) switch_by_polymorphicTypeIdField
mtdBody.append(new IfStatement().condition(isNotNull(getThisFieldCode(traverseChildrenMtd, polymorphicTypeIdFieldDef))).ifTrue(switchBuilderTypeId.build()));
}
mtdBody.ret();
}
use of org.apache.ignite.internal.configuration.tree.ConfigurationVisitor in project ignite-3 by apache.
the class ConfigurationNode method keyPath.
/**
* Converts {@link #keys} into a list of {@link KeyPathNode}. Result is used in implementations of {@link DirectPropertyProxy}.
*/
protected final List<KeyPathNode> keyPath() {
if (listenOnly) {
throw listenOnlyException();
}
ConfigurationVisitor<List<KeyPathNode>> visitor = new ConfigurationVisitor<>() {
/**
* List with the result.
*/
private List<KeyPathNode> res = new ArrayList<>(keys.size());
/**
* Current index.
*/
private int idx = 1;
/**
* {@inheritDoc}
*/
@Nullable
@Override
public List<KeyPathNode> visitLeafNode(String key, Serializable val) {
res.add(new KeyPathNode(key));
return res;
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public List<KeyPathNode> visitInnerNode(String key, InnerNode node) {
res.add(new KeyPathNode(key));
if (keys.size() == idx) {
return res;
}
node.traverseChild(keys.get(idx++), this, true);
return res;
}
/**
* {@inheritDoc}
*/
@Nullable
@Override
public List<KeyPathNode> visitNamedListNode(String key, NamedListNode node) {
res.add(new KeyPathNode(key));
if (keys.size() == idx) {
return res;
}
InnerNode innerNode = node.getInnerNode(keys.get(idx++));
if (innerNode == null) {
throw noSuchElementException();
}
// This is important, node is added as a resolved named list entry here.
res.add(new KeyPathNode(innerNode.internalId().toString(), false));
if (keys.size() == idx) {
return res;
}
innerNode.traverseChild(keys.get(idx++), this, true);
return res;
}
};
return changer.getRootNode(rootKey).accept(keys.get(0), visitor);
}
Aggregations