3996134eb1bd4f13eea0f4072baa0c9cdabafbf4
[smo/teiv.git] /
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2024 Ericsson
4  *  Modifications Copyright (C) 2024 OpenInfra Foundation Europe
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21 package org.oran.smo.yangtools.parser.model.statements.ietf;
22
23 import java.util.Arrays;
24 import java.util.List;
25
26 import org.oran.smo.yangtools.parser.ParserExecutionContext;
27 import org.oran.smo.yangtools.parser.findings.Finding;
28 import org.oran.smo.yangtools.parser.findings.ParserFindingType;
29 import org.oran.smo.yangtools.parser.model.statements.AbstractStatement;
30 import org.oran.smo.yangtools.parser.model.statements.ExtensionStatement;
31 import org.oran.smo.yangtools.parser.model.statements.StatementModuleAndName;
32 import org.oran.smo.yangtools.parser.model.statements.yang.CY;
33 import org.oran.smo.yangtools.parser.model.yangdom.YangDomElement;
34
35 /**
36  * From module ietf-yang-metadata:
37  *
38  * This extension allows for defining metadata annotations in
39  * YANG modules. The 'md:annotation' statement can appear only
40  * at the top level of a YANG module or submodule, i.e., it
41  * becomes a new alternative in the ABNF production rule for
42  * 'body-stmts' (Section 14 in RFC 7950).
43  *
44  * The argument of the 'md:annotation' statement defines the name
45  * of the annotation. Syntactically, it is a YANG identifier as
46  * defined in Section 6.2 of RFC 7950.
47  *
48  * An annotation defined with this 'extension' statement inherits
49  * the namespace and other context from the YANG module in which
50  * it is defined.
51  *
52  * The data type of the annotation value is specified in the same
53  * way as for a leaf data node using the 'type' statement.
54  *
55  * The semantics of the annotation and other documentation can be
56  * specified using the following standard YANG substatements (all
57  * are optional): 'description', 'if-feature', 'reference',
58  * 'status', and 'units'.
59  *
60  * A server announces support for a particular annotation by
61  * including the module in which the annotation is defined among
62  * the advertised YANG modules, e.g., in a NETCONF <hello>
63  * message or in the YANG library (RFC 7950). The annotation can
64  * then be attached to any instance of a data node defined in any
65  * YANG module that is advertised by the server.
66  *
67  * XML encoding and JSON encoding of annotations are defined in
68  * RFC 7952.;
69  *
70  * @author Mark Hollmann
71  */
72 public class YIetfAnnotation extends ExtensionStatement {
73
74     public YIetfAnnotation(final AbstractStatement parentStatement, final YangDomElement domNode) {
75         super(parentStatement, domNode);
76     }
77
78     @Override
79     public StatementArgumentType getArgumentType() {
80         return StatementArgumentType.NAME;
81     }
82
83     @Override
84     public StatementModuleAndName getStatementModuleAndName() {
85         return CIETF.IETF_YANG_METADATA__ANNOTATION;
86     }
87
88     @Override
89     public boolean argumentIsMandatory() {
90         return true;
91     }
92
93     public String getAnnotationName() {
94         return getValue() != null ? getValue() : "";
95     }
96
97     @Override
98     public MaxCardinality getMaxCardinalityUnderParent() {
99         return MaxCardinality.MULTIPLE;
100     }
101
102     private static final List<StatementModuleAndName> REQUIRED_PARENTS = Arrays.asList(CY.STMT_MODULE, CY.STMT_SUBMODULE);
103
104     @Override
105     public boolean canBeChildOf(final StatementModuleAndName parentSman) {
106         return REQUIRED_PARENTS.contains(parentSman);
107     }
108
109     @Override
110     protected void validate(final ParserExecutionContext context) {
111         checkParent(context);
112
113         validateArgumentNotNullNotEmpty(context);
114         validateIsYangIdentifier(context, getValue());
115     }
116
117     @Override
118     protected void subtreeProcessed(final ParserExecutionContext context) {
119         /*
120          * There must be exactly a single type statement under the annotation.
121          */
122         if (getChildren(CY.STMT_TYPE).size() != 1) {
123             context.addFinding(new Finding(this, ParserFindingType.P019_MISSING_REQUIRED_CHILD_STATEMENT.toString(),
124                     "A 'type' statement is required for the annotation."));
125         }
126     }
127 }