2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.rfc8040.parser;
10 import static com.google.common.base.Verify.verify;
11 import static com.google.common.base.Verify.verifyNotNull;
12 import static java.util.Objects.requireNonNull;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Comparator;
17 import java.util.List;
18 import java.util.stream.Collectors;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
21 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
25 import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.RpcStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
29 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportNamespace;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
40 * Once we have identified the {@code operations} container we want to enrich, we need to identify all RPC statements
41 * in the reactor. For that we need that all sources complete {@link ModelProcessingPhase#FULL_DECLARATION} -- after
42 * which we are still not done, as not all those RPCs may make it to the resulting {@link EffectiveModelContext}.
44 final class OperationsCreateLeafStatements implements InferenceAction {
45 private final List<Prerequisite<? extends StmtContext<?, ?, ?>>> prereqs;
46 private final Mutable<?, ?, ?> operations;
48 private OperationsCreateLeafStatements(final Mutable<?, ?, ?> operations,
49 final List<Prerequisite<? extends StmtContext<?, ?, ?>>> prereqs) {
50 this.operations = requireNonNull(operations);
51 this.prereqs = requireNonNull(prereqs);
54 static void applyTo(final StmtContext<?, ?, ?> ietfRestconfModule, final Mutable<?, ?, ?> operations) {
55 final var action = operations.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
56 action.mutatesEffectiveCtx(operations);
58 final var prereqs = new ArrayList<Prerequisite<? extends StmtContext<?, ?, ?>>>();
59 // FIXME: this not accurate: we need all sources, not just modules
60 for (var module : ietfRestconfModule.getAllFromNamespace(ModuleNamespace.class).values()) {
61 if (!ietfRestconfModule.equals(module)) {
62 prereqs.add(action.requiresCtx((StmtContext<?, ?, ?>)module, ModelProcessingPhase.EFFECTIVE_MODEL));
66 action.apply(new OperationsCreateLeafStatements(operations, prereqs));
70 public void apply(final InferenceContext ctx) {
71 // Enumerate all RPCs that can be built
72 final var qnames = prereqs.stream()
73 .flatMap(prereq -> prereq.resolve(ctx).declaredSubstatements().stream())
74 .filter(stmt -> stmt.producesDeclared(RpcStatement.class)
75 && stmt.isSupportedToBuildEffective() && stmt.isSupportedByFeatures())
76 .map(stmt -> (QName) stmt.argument())
77 // predictable order...
78 .sorted(Comparator.naturalOrder())
79 // each QName should be distinct, but let's make sure anyway
81 .collect(Collectors.toUnmodifiableList());
83 if (!qnames.isEmpty()) {
84 final var leafSupport = getSupport(YangStmtMapping.LEAF, LeafEffectiveStatement.class);
85 final var typeSupport = getSupport(YangStmtMapping.TYPE, TypeEffectiveStatement.class);
87 for (var qname : qnames) {
88 final var leaf = operations.createUndeclaredSubstatement(leafSupport, qname);
89 leaf.addEffectiveSubstatement(leaf.createUndeclaredSubstatement(typeSupport, TypeDefinitions.EMPTY));
90 operations.addEffectiveSubstatement(leaf);
96 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
97 // We do not really need to fail, as this means reactor will fail anyway
100 private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
101 StatementSupport<X, Y, Z> getSupport(final StatementDefinition def, final Class<Z> effectiveClass) {
102 final var tmp = verifyNotNull(operations.getFromNamespace(StatementSupportNamespace.class,
103 def.getStatementName()));
104 final var repr = tmp.getEffectiveRepresentationClass();
105 verify(effectiveClass.equals(repr), "Unexpected support %s representation %s", tmp, repr);
107 @SuppressWarnings("unchecked")
108 final var ret = (StatementSupport<X, Y, Z>) tmp;