Populate ietf-restconf operations container
[yangtools.git] / parser / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / meta / LeafStatementSupport.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.meta;
9
10 import static com.google.common.base.Verify.verify;
11
12 import com.google.common.collect.ImmutableList;
13 import java.util.Collection;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
17 import org.opendaylight.yangtools.yang.model.api.Status;
18 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
19 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.stmt.DefaultEffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.LeafEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.TypeEffectiveStatement;
28 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
29 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
30 import org.opendaylight.yangtools.yang.model.ri.stmt.EffectiveStatements;
31 import org.opendaylight.yangtools.yang.model.ri.stmt.UndeclaredStatements;
32 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
33 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
34 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStatementState;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
38 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
39 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameWithFlagsEffectiveStatementState;
40 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
41 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
42 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
43 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
44
45 public final class LeafStatementSupport
46         extends AbstractImplicitStatementSupport<LeafStatement, LeafEffectiveStatement> {
47     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR =
48         SubstatementValidator.builder(YangStmtMapping.LEAF)
49             .addOptional(YangStmtMapping.CONFIG)
50             .addOptional(YangStmtMapping.DEFAULT)
51             .addOptional(YangStmtMapping.DESCRIPTION)
52             .addAny(YangStmtMapping.IF_FEATURE)
53             .addOptional(YangStmtMapping.MANDATORY)
54             .addAny(YangStmtMapping.MUST)
55             .addOptional(YangStmtMapping.REFERENCE)
56             .addOptional(YangStmtMapping.STATUS)
57             .addMandatory(YangStmtMapping.TYPE)
58             .addOptional(YangStmtMapping.UNITS)
59             .addOptional(YangStmtMapping.WHEN)
60             .build();
61
62     public LeafStatementSupport(final YangParserConfiguration config) {
63         super(YangStmtMapping.LEAF, instantiatedPolicy(), config, SUBSTATEMENT_VALIDATOR);
64     }
65
66     @Override
67     public void onFullDefinitionDeclared(final Mutable<QName, LeafStatement, LeafEffectiveStatement> ctx) {
68         super.onFullDefinitionDeclared(ctx);
69         StmtContextUtils.validateIfFeatureAndWhenOnListKeys(ctx);
70     }
71
72     @Override
73     protected LeafStatement createDeclared(final BoundStmtCtx<QName> ctx,
74             final ImmutableList<DeclaredStatement<?>> substatements) {
75         return DeclaredStatements.createLeaf(ctx.getArgument(), substatements);
76     }
77
78     @Override
79     protected LeafStatement attachDeclarationReference(final LeafStatement stmt, final DeclarationReference reference) {
80         return DeclaredStatementDecorators.decorateLeaf(stmt, reference);
81     }
82
83     @Override
84     public LeafEffectiveStatement copyEffective(final Current<QName, LeafStatement> stmt,
85             final LeafEffectiveStatement original) {
86         return EffectiveStatements.copyLeaf(original, stmt.getArgument(),
87             computeFlags(stmt, original.effectiveSubstatements()));
88     }
89
90     @Override
91     protected LeafEffectiveStatement createEffective(final Current<QName, LeafStatement> stmt,
92             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
93         validateEffective(stmt, substatements);
94         return EffectiveStatements.createLeaf(stmt.declared(), stmt.getArgument(), computeFlags(stmt, substatements),
95             substatements);
96     }
97
98     @Override
99     LeafEffectiveStatement createUndeclaredEffective(final UndeclaredCurrent<QName, LeafStatement> stmt,
100             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
101         validateEffective(stmt, substatements);
102         return UndeclaredStatements.createLeaf(stmt.getArgument(), computeFlags(stmt, substatements), substatements);
103     }
104
105     private static void validateEffective(final @NonNull BoundStmtCtx<QName> stmt,
106             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
107         final TypeEffectiveStatement<?> typeStmt = SourceException.throwIfNull(
108             findFirstStatement(substatements, TypeEffectiveStatement.class), stmt,
109             "Leaf is missing a 'type' statement");
110         final String dflt = findFirstArgument(substatements, DefaultEffectiveStatement.class, null);
111         SourceException.throwIf(
112             EffectiveStmtUtils.hasDefaultValueMarkedWithIfFeature(stmt.yangVersion(), typeStmt, dflt), stmt,
113             "Leaf '%s' has default value '%s' marked with an if-feature statement.", stmt.argument(), dflt);
114     }
115
116     @Override
117     public EffectiveStatementState extractEffectiveState(final LeafEffectiveStatement stmt) {
118         verify(stmt instanceof LeafSchemaNode, "Unexpected statement %s", stmt);
119         final var schema = (LeafSchemaNode) stmt;
120         return new QNameWithFlagsEffectiveStatementState(stmt.argument(), new FlagsBuilder()
121             .setHistory(schema)
122             .setStatus(schema.getStatus())
123             .setConfiguration(schema.effectiveConfig().orElse(null))
124             .setMandatory(schema.isMandatory())
125             .toFlags());
126     }
127
128     private static int computeFlags(final Current<?, ?> stmt,
129             final Collection<? extends EffectiveStatement<?, ?>> substatements) {
130         return new FlagsBuilder()
131             .setHistory(stmt.history())
132             .setStatus(findFirstArgument(substatements, StatusEffectiveStatement.class, Status.CURRENT))
133             .setConfiguration(stmt.effectiveConfig().asNullable())
134             .setMandatory(findFirstArgument(substatements, MandatoryEffectiveStatement.class, Boolean.FALSE))
135             .toFlags();
136     }
137 }