All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.yangtools.rfc8040.parser.OperationsCreateLeafStatements Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.rfc8040.parser;

import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RpcStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;

/**
 * Once we have identified the {@code operations} container we want to enrich, we need to identify all RPC statements
 * in the reactor. For that we need that all sources complete {@link ModelProcessingPhase#FULL_DECLARATION} -- after
 * which we are still not done, as not all those RPCs may make it to the resulting {@link EffectiveModelContext}.
 */
final class OperationsCreateLeafStatements implements InferenceAction {
    private final List>> prereqs;
    private final Mutable operations;

    private OperationsCreateLeafStatements(final Mutable operations,
            final List>> prereqs) {
        this.operations = requireNonNull(operations);
        this.prereqs = requireNonNull(prereqs);
    }

    static void applyTo(final StmtContext ietfRestconfModule, final Mutable operations) {
        final var action = operations.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
        action.mutatesEffectiveCtx(operations);

        final var prereqs = new ArrayList>>();
        // FIXME: this not accurate: we need all sources, not just modules
        for (var module : ietfRestconfModule.namespace(ParserNamespaces.MODULE).values()) {
            if (!ietfRestconfModule.equals(module)) {
                prereqs.add(action.requiresCtx((StmtContext)module, ModelProcessingPhase.EFFECTIVE_MODEL));
            }
        }

        action.apply(new OperationsCreateLeafStatements(operations, prereqs));
    }

    @Override
    public void apply(final InferenceContext ctx) {
        // Enumerate all RPCs that can be built
        final var qnames = prereqs.stream()
            .flatMap(prereq -> prereq.resolve(ctx).declaredSubstatements().stream())
            .filter(stmt -> stmt.producesDeclared(RpcStatement.class)
                && stmt.isSupportedToBuildEffective() && stmt.isSupportedByFeatures())
            .map(stmt -> (QName) stmt.argument())
            // predictable order...
            .sorted(Comparator.naturalOrder())
            // each QName should be distinct, but let's make sure anyway
            .distinct()
            .collect(Collectors.toUnmodifiableList());

        if (!qnames.isEmpty()) {
            final var leafSupport = getSupport(YangStmtMapping.LEAF, LeafEffectiveStatement.class);
            final var typeSupport = getSupport(YangStmtMapping.TYPE, TypeEffectiveStatement.class);

            for (var qname : qnames) {
                final var leaf = operations.createUndeclaredSubstatement(leafSupport, qname);
                leaf.addEffectiveSubstatement(leaf.createUndeclaredSubstatement(typeSupport, TypeDefinitions.EMPTY));
                operations.addEffectiveSubstatement(leaf);
            }
        }
    }

    @Override
    public void prerequisiteFailed(final Collection> failed) {
        // We do not really need to fail, as this means reactor will fail anyway
    }

    private , Z extends EffectiveStatement>
            StatementSupport getSupport(final StatementDefinition def, final Class effectiveClass) {
        final var tmp = verifyNotNull(operations.namespaceItem(StatementSupport.NAMESPACE, def.getStatementName()));
        final var repr = tmp.definition().getEffectiveRepresentationClass();
        verify(effectiveClass.equals(repr), "Unexpected support %s representation %s", tmp, repr);

        @SuppressWarnings("unchecked")
        final var ret = (StatementSupport) tmp;
        return ret;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy