Search in sources :

Example 1 with ConfigurationVisitor

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));
    }
}
Also used : Serializable(java.io.Serializable) NamedListNode(org.apache.ignite.internal.configuration.tree.NamedListNode) ConfigurationWrongPolymorphicTypeIdException(org.apache.ignite.configuration.ConfigurationWrongPolymorphicTypeIdException) ConfigurationVisitor(org.apache.ignite.internal.configuration.tree.ConfigurationVisitor) KeyPathNode(org.apache.ignite.internal.configuration.direct.KeyPathNode) NoSuchElementException(java.util.NoSuchElementException) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with ConfigurationVisitor

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());
    }
}
Also used : Field(java.lang.reflect.Field) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeExpressions.constantString(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantString) ConfigurationVisitor(org.apache.ignite.internal.configuration.tree.ConfigurationVisitor) NoSuchElementException(java.util.NoSuchElementException)

Example 3 with ConfigurationVisitor

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();
}
Also used : Field(java.lang.reflect.Field) IfStatement(com.facebook.presto.bytecode.control.IfStatement) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ConfigurationVisitor(org.apache.ignite.internal.configuration.tree.ConfigurationVisitor) BytecodeExpressions.constantString(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantString)

Example 4 with ConfigurationVisitor

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);
}
Also used : Serializable(java.io.Serializable) NamedListNode(org.apache.ignite.internal.configuration.tree.NamedListNode) ArrayList(java.util.ArrayList) List(java.util.List) ConfigurationVisitor(org.apache.ignite.internal.configuration.tree.ConfigurationVisitor) KeyPathNode(org.apache.ignite.internal.configuration.direct.KeyPathNode) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode)

Aggregations

ConfigurationVisitor (org.apache.ignite.internal.configuration.tree.ConfigurationVisitor)4 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)2 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)2 IfStatement (com.facebook.presto.bytecode.control.IfStatement)2 BytecodeExpressions.constantString (com.facebook.presto.bytecode.expression.BytecodeExpressions.constantString)2 Serializable (java.io.Serializable)2 Field (java.lang.reflect.Field)2 NoSuchElementException (java.util.NoSuchElementException)2 KeyPathNode (org.apache.ignite.internal.configuration.direct.KeyPathNode)2 InnerNode (org.apache.ignite.internal.configuration.tree.InnerNode)2 NamedListNode (org.apache.ignite.internal.configuration.tree.NamedListNode)2 Variable (com.facebook.presto.bytecode.Variable)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 ConfigurationWrongPolymorphicTypeIdException (org.apache.ignite.configuration.ConfigurationWrongPolymorphicTypeIdException)1 Nullable (org.jetbrains.annotations.Nullable)1