Search in sources :

Example 16 with InnerNode

use of org.apache.ignite.internal.configuration.tree.InnerNode in project ignite-3 by apache.

the class ConfigurationUtilTest method findSuccessfully.

/**
 * Tests that {@link ConfigurationUtil#find(List, TraversableTreeNode, boolean)} finds proper node when provided with correct path.
 */
@Test
public void findSuccessfully() {
    InnerNode parentNode = newNodeInstance(ParentConfigurationSchema.class);
    ParentChange parentChange = (ParentChange) parentNode;
    parentChange.changeElements(elements -> elements.createOrUpdate("name", element -> element.changeChild(child -> child.changeStr("value"))));
    assertSame(parentNode, ConfigurationUtil.find(List.of(), parentNode, true));
    assertSame(parentChange.elements(), ConfigurationUtil.find(List.of("elements"), parentNode, true));
    assertSame(parentChange.elements().get("name"), ConfigurationUtil.find(List.of("elements", "name"), parentNode, true));
    assertSame(parentChange.elements().get("name").child(), ConfigurationUtil.find(List.of("elements", "name", "child"), parentNode, true));
    assertSame(parentChange.elements().get("name").child().str(), ConfigurationUtil.find(List.of("elements", "name", "child", "str"), parentNode, true));
}
Also used : PolymorphicId(org.apache.ignite.configuration.annotation.PolymorphicId) Matchers.hasToString(org.hamcrest.Matchers.hasToString) Arrays(java.util.Arrays) RootInnerNode(org.apache.ignite.internal.configuration.RootInnerNode) DISTRIBUTED(org.apache.ignite.configuration.annotation.ConfigurationType.DISTRIBUTED) NamedConfigValue(org.apache.ignite.configuration.annotation.NamedConfigValue) AfterAll(org.junit.jupiter.api.AfterAll) BeforeAll(org.junit.jupiter.api.BeforeAll) Matchers.nullValue(org.hamcrest.Matchers.nullValue) Map(java.util.Map) ConfigurationUtil.addDefaults(org.apache.ignite.internal.configuration.util.ConfigurationUtil.addDefaults) Matchers.allOf(org.hamcrest.Matchers.allOf) Set(java.util.Set) UUID(java.util.UUID) RootKey(org.apache.ignite.configuration.RootKey) Serializable(java.io.Serializable) ConfigurationUtil.removeLastKey(org.apache.ignite.internal.configuration.util.ConfigurationUtil.removeLastKey) Test(org.junit.jupiter.api.Test) ConfigValue(org.apache.ignite.configuration.annotation.ConfigValue) Matchers.matchesPattern(org.hamcrest.Matchers.matchesPattern) List(java.util.List) NAME(org.apache.ignite.internal.configuration.tree.NamedListNode.NAME) LOCAL(org.apache.ignite.configuration.annotation.ConfigurationType.LOCAL) ConfigurationUtil.checkConfigurationType(org.apache.ignite.internal.configuration.util.ConfigurationUtil.checkConfigurationType) ConfigurationUtil.collectSchemas(org.apache.ignite.internal.configuration.util.ConfigurationUtil.collectSchemas) ConfigurationFlattener.createFlattenedUpdatesMap(org.apache.ignite.internal.configuration.util.ConfigurationFlattener.createFlattenedUpdatesMap) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) Config(org.apache.ignite.configuration.annotation.Config) Matchers.is(org.hamcrest.Matchers.is) NotNull(org.jetbrains.annotations.NotNull) ConfigurationAsmGenerator(org.apache.ignite.internal.configuration.asm.ConfigurationAsmGenerator) EMPTY_CFG_SRC(org.apache.ignite.internal.configuration.util.ConfigurationUtil.EMPTY_CFG_SRC) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) Matchers.aMapWithSize(org.hamcrest.Matchers.aMapWithSize) NamedListNode(org.apache.ignite.internal.configuration.tree.NamedListNode) ORDER_IDX(org.apache.ignite.internal.configuration.tree.NamedListNode.ORDER_IDX) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HashMap(java.util.HashMap) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) ConfigurationUtil.internalSchemaExtensions(org.apache.ignite.internal.configuration.util.ConfigurationUtil.internalSchemaExtensions) TraversableTreeNode(org.apache.ignite.internal.configuration.tree.TraversableTreeNode) PolymorphicConfig(org.apache.ignite.configuration.annotation.PolymorphicConfig) Collections.singletonMap(java.util.Collections.singletonMap) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) NoSuchElementException(java.util.NoSuchElementException) ConfigurationUtil.extensionsFields(org.apache.ignite.internal.configuration.util.ConfigurationUtil.extensionsFields) Matchers.hasEntry(org.hamcrest.Matchers.hasEntry) ConfigurationRoot(org.apache.ignite.configuration.annotation.ConfigurationRoot) ConfigurationUtil.compressDeletedEntries(org.apache.ignite.internal.configuration.util.ConfigurationUtil.compressDeletedEntries) Assertions.assertSame(org.junit.jupiter.api.Assertions.assertSame) Consumer(java.util.function.Consumer) ConverterToMapVisitor(org.apache.ignite.internal.configuration.tree.ConverterToMapVisitor) Collectors.toList(java.util.stream.Collectors.toList) ConfigurationUtil.find(org.apache.ignite.internal.configuration.util.ConfigurationUtil.find) PolymorphicConfigInstance(org.apache.ignite.configuration.annotation.PolymorphicConfigInstance) SuperRoot(org.apache.ignite.internal.configuration.SuperRoot) ConfigurationUtil.polymorphicSchemaExtensions(org.apache.ignite.internal.configuration.util.ConfigurationUtil.polymorphicSchemaExtensions) TestConfigurationStorage(org.apache.ignite.internal.configuration.storage.TestConfigurationStorage) Matchers.anEmptyMap(org.hamcrest.Matchers.anEmptyMap) Value(org.apache.ignite.configuration.annotation.Value) InternalConfiguration(org.apache.ignite.configuration.annotation.InternalConfiguration) RootInnerNode(org.apache.ignite.internal.configuration.RootInnerNode) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) Test(org.junit.jupiter.api.Test)

Example 17 with InnerNode

use of org.apache.ignite.internal.configuration.tree.InnerNode in project ignite-3 by apache.

the class ConfigurationExtension method cfgValue.

/**
 * Instantiates a configuration instance for injection.
 *
 * @param type Type of the field or parameter. Class name must end with {@code Configuration}.
 * @param annotation Annotation present on the field or parameter.
 * @param cgen Runtime code generator associated with the extension instance.
 * @param pool Single-threaded executor service to perform configuration changes.
 * @param revisionListenerHolder Configuration storage revision change listener holder.
 * @return Mock configuration instance.
 * @throws ClassNotFoundException If corresponding configuration schema class is not found.
 */
private static Object cfgValue(Class<?> type, InjectConfiguration annotation, ConfigurationAsmGenerator cgen, ExecutorService pool, StorageRevisionListenerHolderImpl revisionListenerHolder) throws ClassNotFoundException {
    // Trying to find a schema class using configuration naming convention. This code won't work for inner Java
    // classes, extension is designed to mock actual configurations from public API to configure Ignite components.
    Class<?> schemaClass = Class.forName(type.getCanonicalName() + "Schema");
    cgen.compileRootSchema(schemaClass, internalSchemaExtensions(List.of(annotation.internalExtensions())), polymorphicSchemaExtensions(List.of(annotation.polymorphicExtensions())));
    // RootKey must be mocked, there's no way to instantiate it using a public constructor.
    RootKey rootKey = mock(RootKey.class);
    when(rootKey.key()).thenReturn("mock");
    when(rootKey.type()).thenReturn(LOCAL);
    when(rootKey.schemaClass()).thenReturn(schemaClass);
    when(rootKey.internal()).thenReturn(false);
    SuperRoot superRoot = new SuperRoot(s -> new RootInnerNode(rootKey, cgen.instantiateNode(schemaClass)));
    ConfigObject hoconCfg = ConfigFactory.parseString(annotation.value()).root();
    HoconConverter.hoconSource(hoconCfg).descend(superRoot);
    ConfigurationUtil.addDefaults(superRoot);
    // Reference to the super root is required to make DynamicConfigurationChanger#change method atomic.
    var superRootRef = new AtomicReference<>(superRoot);
    // Reference that's required for notificator.
    var cfgRef = new AtomicReference<DynamicConfiguration<?, ?>>();
    cfgRef.set(cgen.instantiateCfg(rootKey, new DynamicConfigurationChanger() {

        /**
         * {@inheritDoc}
         */
        @Override
        public CompletableFuture<Void> change(ConfigurationSource change) {
            return CompletableFuture.supplyAsync(() -> {
                SuperRoot sr = superRootRef.get();
                SuperRoot copy = sr.copy();
                change.descend(copy);
                ConfigurationUtil.dropNulls(copy);
                if (superRootRef.compareAndSet(sr, copy)) {
                    long storageRevision = revisionListenerHolder.storageRev.incrementAndGet();
                    long notificationNumber = revisionListenerHolder.notificationListenerCnt.incrementAndGet();
                    List<CompletableFuture<?>> futures = new ArrayList<>();
                    futures.addAll(notifyListeners(sr.getRoot(rootKey), copy.getRoot(rootKey), (DynamicConfiguration<InnerNode, ?>) cfgRef.get(), storageRevision, notificationNumber));
                    futures.addAll(revisionListenerHolder.notifyStorageRevisionListeners(storageRevision, notificationNumber));
                    return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new));
                }
                return change(change);
            }, pool).thenCompose(Function.identity());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public InnerNode getRootNode(RootKey<?, ?> rk) {
            return superRootRef.get().getRoot(rk);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public <T> T getLatest(List<KeyPathNode> path) {
            return findEx(path, superRootRef.get());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public long notificationCount() {
            return revisionListenerHolder.notificationListenerCnt.get();
        }
    }));
    touch(cfgRef.get());
    return cfgRef.get();
}
Also used : ConfigurationSource(org.apache.ignite.internal.configuration.tree.ConfigurationSource) RootKey(org.apache.ignite.configuration.RootKey) SuperRoot(org.apache.ignite.internal.configuration.SuperRoot) AtomicReference(java.util.concurrent.atomic.AtomicReference) DynamicConfigurationChanger(org.apache.ignite.internal.configuration.DynamicConfigurationChanger) RootInnerNode(org.apache.ignite.internal.configuration.RootInnerNode) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) RootInnerNode(org.apache.ignite.internal.configuration.RootInnerNode) ArrayList(java.util.ArrayList) List(java.util.List) ConfigObject(com.typesafe.config.ConfigObject)

Example 18 with InnerNode

use of org.apache.ignite.internal.configuration.tree.InnerNode in project ignite-3 by apache.

the class ConfigurationAsmGenerator method createNodeClass.

/**
 * Construct a {@link InnerNode} definition for a configuration schema.
 *
 * @param schemaClass           Configuration schema class.
 * @param internalExtensions    Internal extensions of the configuration schema.
 * @param polymorphicExtensions Polymorphic 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 InnerNode} definition for the configuration schema.
 */
private ClassDefinition createNodeClass(Class<?> schemaClass, Set<Class<?>> internalExtensions, Set<Class<?>> polymorphicExtensions, List<Field> schemaFields, Collection<Field> internalFields, Collection<Field> polymorphicFields, @Nullable Field internalIdField) {
    SchemaClassesInfo schemaClassInfo = schemasInfo.get(schemaClass);
    // Node class definition.
    ClassDefinition classDef = new ClassDefinition(of(PUBLIC, FINAL), internalName(schemaClassInfo.nodeClassName), type(InnerNode.class), nodeClassInterfaces(schemaClass, internalExtensions));
    // Spec fields.
    Map<Class<?>, FieldDefinition> specFields = new HashMap<>();
    int i = 0;
    for (Class<?> clazz : concat(List.of(schemaClass), internalExtensions, polymorphicExtensions)) {
        specFields.put(clazz, classDef.declareField(of(PRIVATE, FINAL), "_spec" + i++, clazz));
    }
    // Define the rest of the fields.
    Map<String, FieldDefinition> fieldDefs = new HashMap<>();
    // To store the id of the polymorphic configuration instance.
    FieldDefinition polymorphicTypeIdFieldDef = null;
    // Field with @InjectedName.
    FieldDefinition injectedNameFieldDef = null;
    for (Field schemaField : concat(schemaFields, internalFields, polymorphicFields)) {
        String fieldName = fieldName(schemaField);
        FieldDefinition fieldDef = addNodeField(classDef, schemaField, fieldName);
        fieldDefs.put(fieldName, fieldDef);
        if (isPolymorphicId(schemaField)) {
            polymorphicTypeIdFieldDef = fieldDef;
        } else if (isInjectedName(schemaField)) {
            injectedNameFieldDef = fieldDef;
        }
    }
    // org.apache.ignite.internal.configuration.tree.InnerNode#schemaType
    addNodeSchemaTypeMethod(classDef, schemaClass, polymorphicExtensions, polymorphicTypeIdFieldDef);
    // Constructor.
    addNodeConstructor(classDef, specFields, fieldDefs, schemaFields, internalFields, polymorphicFields);
    // Add view method for internal id.
    if (internalIdField != null) {
        addNodeInternalIdMethod(classDef, internalIdField);
    }
    // VIEW and CHANGE methods.
    for (Field schemaField : concat(schemaFields, internalFields)) {
        String fieldName = schemaField.getName();
        FieldDefinition fieldDef = fieldDefs.get(fieldName);
        addNodeViewMethod(classDef, schemaField, viewMtd -> getThisFieldCode(viewMtd, fieldDef), null);
        // Read only.
        if (isPolymorphicId(schemaField) || isInjectedName(schemaField)) {
            continue;
        }
        // Add change methods.
        MethodDefinition changeMtd0 = addNodeChangeMethod(classDef, schemaField, changeMtd -> getThisFieldCode(changeMtd, fieldDef), (changeMtd, newValue) -> setThisFieldCode(changeMtd, newValue, fieldDef), null);
        addNodeChangeBridgeMethod(classDef, changeClassName(schemaField.getDeclaringClass()), changeMtd0);
    }
    Map<Class<?>, List<Field>> polymorphicFieldsByExtension = Map.of();
    MethodDefinition changePolymorphicTypeIdMtd = null;
    if (!polymorphicExtensions.isEmpty()) {
        assert polymorphicTypeIdFieldDef != null : schemaClass.getName();
        addNodeSpecificNodeMethod(classDef, polymorphicExtensions, polymorphicTypeIdFieldDef);
        changePolymorphicTypeIdMtd = addNodeChangePolymorphicTypeIdMethod(classDef, fieldDefs, polymorphicExtensions, polymorphicFields, polymorphicTypeIdFieldDef);
        addNodeConvertMethod(classDef, schemaClass, polymorphicExtensions, changePolymorphicTypeIdMtd);
        polymorphicFieldsByExtension = new LinkedHashMap<>();
        for (Class<?> polymorphicExtension : polymorphicExtensions) {
            polymorphicFieldsByExtension.put(polymorphicExtension, polymorphicFields.stream().filter(f -> polymorphicExtension.equals(f.getDeclaringClass())).collect(toList()));
        }
    }
    // traverseChildren
    addNodeTraverseChildrenMethod(classDef, schemaClass, fieldDefs, schemaFields, internalFields, polymorphicFieldsByExtension, polymorphicTypeIdFieldDef);
    // traverseChild
    addNodeTraverseChildMethod(classDef, fieldDefs, schemaFields, internalFields, polymorphicFieldsByExtension, polymorphicTypeIdFieldDef);
    // construct
    addNodeConstructMethod(classDef, fieldDefs, schemaFields, internalFields, polymorphicFieldsByExtension, polymorphicTypeIdFieldDef, changePolymorphicTypeIdMtd);
    // constructDefault
    addNodeConstructDefaultMethod(classDef, specFields, fieldDefs, schemaFields, internalFields, polymorphicFieldsByExtension, polymorphicTypeIdFieldDef);
    if (injectedNameFieldDef != null) {
        addInjectedNameFieldMethods(classDef, injectedNameFieldDef);
    }
    return classDef;
}
Also used : LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) BytecodeExpressions.constantString(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantString) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) Field(java.lang.reflect.Field) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeExpressions.constantClass(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantClass) Arrays.asList(java.util.Arrays.asList) ArrayList(java.util.ArrayList) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList)

Example 19 with InnerNode

use of org.apache.ignite.internal.configuration.tree.InnerNode in project ignite-3 by apache.

the class ConfigurationChanger method getLatest.

/**
 * {@inheritDoc}
 */
@Override
public <T> T getLatest(List<KeyPathNode> path) {
    assert !path.isEmpty();
    assert path instanceof RandomAccess : path.getClass();
    assert !path.get(0).unresolvedName : path;
    // This map will be merged into the data from the storage. It's required for the conversion into tree to work.
    // Namely, named list order indexes and names are mandatory for conversion.
    Map<String, Map<String, Serializable>> extras = new HashMap<>();
    // Joiner for the prefix that will be used to fetch data from the storage.
    StringJoiner prefixJoiner = new StringJoiner(KEY_SEPARATOR);
    int pathSize = path.size();
    KeyPathNode lastPathNode = path.get(pathSize - 1);
    // This loop is required to accumulate prefix and resolve all unresolved named list elements' ids.
    for (int idx = 0; idx < pathSize; idx++) {
        KeyPathNode keyPathNode = path.get(idx);
        // Regular keys and resolved ids go straight to the prefix.
        if (!keyPathNode.unresolvedName) {
            // Fake name and 0 index go to extras in case of resolved named list elements.
            if (keyPathNode.namedListEntry) {
                prefixJoiner.add(escape(keyPathNode.key));
                String prefix = prefixJoiner + KEY_SEPARATOR;
                extras.put(prefix, Map.of(prefix + NamedListNode.NAME, "<name_placeholder>", prefix + NamedListNode.ORDER_IDX, 0));
            } else {
                prefixJoiner.add(keyPathNode.key);
            }
            continue;
        }
        assert keyPathNode.namedListEntry : path;
        // Here we have unresolved named list element. Name must be translated into the internal id.
        // There's a special path for this purpose in the storage.
        String unresolvedNameKey = prefixJoiner + KEY_SEPARATOR + NamedListNode.IDS + KEY_SEPARATOR + escape(keyPathNode.key);
        // Data from the storage.
        Serializable resolvedName = storage.readLatest(unresolvedNameKey);
        if (resolvedName == null) {
            throw new NoSuchElementException(prefixJoiner + KEY_SEPARATOR + escape(keyPathNode.key));
        }
        assert resolvedName instanceof String : resolvedName;
        // Resolved internal id from the map.
        String internalId = (String) resolvedName;
        // `*.get("resourceName").internalId()` then the result can be returned straight away.
        if (idx == pathSize - 2 && INTERNAL_ID.equals(lastPathNode.key)) {
            assert !lastPathNode.unresolvedName : path;
            // Despite the fact that this cast looks very stupid, it is correct. Internal ids are always UUIDs.
            return (T) UUID.fromString(internalId);
        }
        prefixJoiner.add(internalId);
        String prefix = prefixJoiner + KEY_SEPARATOR;
        // Real name and 0 index go to extras in case of unresolved named list elements.
        extras.put(prefix, Map.of(prefix + NamedListNode.NAME, keyPathNode.key, prefix + NamedListNode.ORDER_IDX, 0));
    }
    // That id must be resolved, otherwise method would already be completed in the loop above.
    if (lastPathNode.key.equals(INTERNAL_ID) && !lastPathNode.unresolvedName && path.get(pathSize - 2).namedListEntry) {
        assert !path.get(pathSize - 2).unresolvedName : path;
        // Not very elegant, I know. <internal_id> is replaced with the <name> in the prefix.
        // <name> always exists in named list element, and it's an easy way to check element's existence.
        String nameStorageKey = prefixJoiner.toString().replaceAll(quote(INTERNAL_ID) + "$", NamedListNode.NAME);
        // Data from the storage.
        Serializable name = storage.readLatest(nameStorageKey);
        if (name != null) {
            // Id is already known.
            return (T) UUID.fromString(path.get(pathSize - 2).key);
        } else {
            throw new NoSuchElementException(prefixJoiner.toString());
        }
    }
    String prefix = prefixJoiner.toString();
    if (lastPathNode.key.equals(INTERNAL_ID) && !path.get(pathSize - 2).namedListEntry) {
        // This is not particularly efficient, but there's no way someone will actually use this case for real outside of tests.
        prefix = prefix.replaceAll(quote(KEY_SEPARATOR + INTERNAL_ID) + "$", "");
    } else if (lastPathNode.key.contains(INJECTED_NAME)) {
        prefix = prefix.replaceAll(quote(KEY_SEPARATOR + INJECTED_NAME), "");
    }
    // Data from the storage.
    Map<String, ? extends Serializable> storageData = storage.readAllLatest(prefix);
    // Data to be converted into the tree.
    Map<String, Serializable> mergedData = new HashMap<>();
    if (!storageData.isEmpty()) {
        mergedData.putAll(storageData);
        for (Entry<String, Map<String, Serializable>> extrasEntry : extras.entrySet()) {
            for (String storageKey : storageData.keySet()) {
                String extrasPrefix = extrasEntry.getKey();
                if (storageKey.startsWith(extrasPrefix)) {
                    // Add extra order indexes and names before converting it to the tree.
                    for (Entry<String, Serializable> extrasEntryMap : extrasEntry.getValue().entrySet()) {
                        mergedData.putIfAbsent(extrasEntryMap.getKey(), extrasEntryMap.getValue());
                    }
                    break;
                }
            }
        }
        if (lastPathNode.namedListEntry) {
            // Change element's order index to zero. Conversion won't work if indexes range is not continuous.
            mergedData.put(prefix + KEY_SEPARATOR + NamedListNode.ORDER_IDX, 0);
        }
    }
    // Super root that'll be filled from the storage data.
    InnerNode rootNode = new SuperRoot(rootCreator());
    fillFromPrefixMap(rootNode, toPrefixMap(mergedData));
    // "addDefaults" won't work if regular root is missing.
    if (storageData.isEmpty()) {
        rootNode.construct(path.get(0).key, ConfigurationUtil.EMPTY_CFG_SRC, true);
    }
    addDefaults(rootNode);
    return findEx(path, rootNode);
}
Also used : Serializable(java.io.Serializable) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) RandomAccess(java.util.RandomAccess) InnerNode(org.apache.ignite.internal.configuration.tree.InnerNode) KeyPathNode(org.apache.ignite.internal.configuration.direct.KeyPathNode) Collectors.toMap(java.util.stream.Collectors.toMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ConfigurationUtil.fillFromPrefixMap(org.apache.ignite.internal.configuration.util.ConfigurationUtil.fillFromPrefixMap) ConfigurationFlattener.createFlattenedUpdatesMap(org.apache.ignite.internal.configuration.util.ConfigurationFlattener.createFlattenedUpdatesMap) HashMap(java.util.HashMap) ConfigurationUtil.toPrefixMap(org.apache.ignite.internal.configuration.util.ConfigurationUtil.toPrefixMap) StringJoiner(java.util.StringJoiner) NoSuchElementException(java.util.NoSuchElementException)

Example 20 with InnerNode

use of org.apache.ignite.internal.configuration.tree.InnerNode 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

InnerNode (org.apache.ignite.internal.configuration.tree.InnerNode)20 HashMap (java.util.HashMap)13 Serializable (java.io.Serializable)12 List (java.util.List)12 Map (java.util.Map)12 NoSuchElementException (java.util.NoSuchElementException)11 Set (java.util.Set)11 NamedListNode (org.apache.ignite.internal.configuration.tree.NamedListNode)11 Collectors.toList (java.util.stream.Collectors.toList)10 RootKey (org.apache.ignite.configuration.RootKey)10 RootInnerNode (org.apache.ignite.internal.configuration.RootInnerNode)10 Test (org.junit.jupiter.api.Test)10 Arrays (java.util.Arrays)9 UUID (java.util.UUID)9 Consumer (java.util.function.Consumer)9 Config (org.apache.ignite.configuration.annotation.Config)9 ConfigurationRoot (org.apache.ignite.configuration.annotation.ConfigurationRoot)9 InternalConfiguration (org.apache.ignite.configuration.annotation.InternalConfiguration)9 NamedConfigValue (org.apache.ignite.configuration.annotation.NamedConfigValue)9 PolymorphicConfig (org.apache.ignite.configuration.annotation.PolymorphicConfig)9