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.ParserNamespaces;
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.StmtContext;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
39 * Once we have identified the {@code operations} container we want to enrich, we need to identify all RPC statements
40 * in the reactor. For that we need that all sources complete {@link ModelProcessingPhase#FULL_DECLARATION} -- after
41 * which we are still not done, as not all those RPCs may make it to the resulting {@link EffectiveModelContext}.
43 final class OperationsCreateLeafStatements implements InferenceAction {
44 private final List<Prerequisite<? extends StmtContext<?, ?, ?>>> prereqs;
45 private final Mutable<?, ?, ?> operations;
47 private OperationsCreateLeafStatements(final Mutable<?, ?, ?> operations,
48 final List<Prerequisite<? extends StmtContext<?, ?, ?>>> prereqs) {
49 this.operations = requireNonNull(operations);
50 this.prereqs = requireNonNull(prereqs);
53 static void applyTo(final StmtContext<?, ?, ?> ietfRestconfModule, final Mutable<?, ?, ?> operations) {
54 final var action = operations.newInferenceAction(ModelProcessingPhase.EFFECTIVE_MODEL);
55 action.mutatesEffectiveCtx(operations);
57 final var prereqs = new ArrayList<Prerequisite<? extends StmtContext<?, ?, ?>>>();
58 // FIXME: this not accurate: we need all sources, not just modules
59 for (var module : ietfRestconfModule.namespace(ParserNamespaces.MODULE).values()) {
60 if (!ietfRestconfModule.equals(module)) {
61 prereqs.add(action.requiresCtx((StmtContext<?, ?, ?>)module, ModelProcessingPhase.EFFECTIVE_MODEL));
65 action.apply(new OperationsCreateLeafStatements(operations, prereqs));
69 public void apply(final InferenceContext ctx) {
70 // Enumerate all RPCs that can be built
71 final var qnames = prereqs.stream()
72 .flatMap(prereq -> prereq.resolve(ctx).declaredSubstatements().stream())
73 .filter(stmt -> stmt.producesDeclared(RpcStatement.class)
74 && stmt.isSupportedToBuildEffective() && stmt.isSupportedByFeatures())
75 .map(stmt -> (QName) stmt.argument())
76 // predictable order...
77 .sorted(Comparator.naturalOrder())
78 // each QName should be distinct, but let's make sure anyway
80 .collect(Collectors.toUnmodifiableList());
82 if (!qnames.isEmpty()) {
83 final var leafSupport = getSupport(YangStmtMapping.LEAF, LeafEffectiveStatement.class);
84 final var typeSupport = getSupport(YangStmtMapping.TYPE, TypeEffectiveStatement.class);
86 for (var qname : qnames) {
87 final var leaf = operations.createUndeclaredSubstatement(leafSupport, qname);
88 leaf.addEffectiveSubstatement(leaf.createUndeclaredSubstatement(typeSupport, TypeDefinitions.EMPTY));
89 operations.addEffectiveSubstatement(leaf);
95 public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
96 // We do not really need to fail, as this means reactor will fail anyway
99 private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
100 StatementSupport<X, Y, Z> getSupport(final StatementDefinition def, final Class<Z> effectiveClass) {
101 final var tmp = verifyNotNull(operations.namespaceItem(StatementSupport.NAMESPACE, def.getStatementName()));
102 final var repr = tmp.definition().getEffectiveRepresentationClass();
103 verify(effectiveClass.equals(repr), "Unexpected support %s representation %s", tmp, repr);
105 @SuppressWarnings("unchecked")
106 final var ret = (StatementSupport<X, Y, Z>) tmp;