152118e92b94701668e3a1b4311091f732e29286
[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.yang;
22
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.oran.smo.yangtools.parser.ParserExecutionContext;
29 import org.oran.smo.yangtools.parser.findings.Finding;
30 import org.oran.smo.yangtools.parser.findings.ParserFindingType;
31 import org.oran.smo.yangtools.parser.model.statements.AbstractStatement;
32 import org.oran.smo.yangtools.parser.model.statements.StatementModuleAndName;
33 import org.oran.smo.yangtools.parser.model.yangdom.YangDomElement;
34
35 /**
36  * Type-safe Yang core statement.
37  *
38  * @author Mark Hollmann
39  */
40 public class YDeviate extends AbstractStatement {
41
42     public YDeviate(final AbstractStatement parentStatement, final YangDomElement domNode) {
43         super(parentStatement, domNode);
44     }
45
46     public String getDeviateOperation() {
47         return domElement.getTrimmedValueOrEmpty();
48     }
49
50     @Override
51     public StatementArgumentType getArgumentType() {
52         return StatementArgumentType.VALUE;
53     }
54
55     @Override
56     public StatementModuleAndName getStatementModuleAndName() {
57         return CY.STMT_DEVIATE;
58     }
59
60     /**
61      * Returns the deviate type or null if the deviate type is unknown / wrong.
62      */
63     public DeviateType getDeviateType() {
64
65         switch (getDeviateOperation()) {
66             case "not-supported":
67                 return DeviateType.NOT_SUPPORTED;
68             case "add":
69                 return DeviateType.ADD;
70             case "replace":
71                 return DeviateType.REPLACE;
72             case "delete":
73                 return DeviateType.DELETE;
74             default:
75         }
76
77         return null;
78     }
79
80     public YConfig getConfig() {
81         return getChild(CY.STMT_CONFIG);
82     }
83
84     public List<YDefault> getDefaults() {
85         return getChildren(CY.STMT_DEFAULT);
86     }
87
88     public YMandatory getMandatory() {
89         return getChild(CY.STMT_MANDATORY);
90     }
91
92     public YMaxElements getMaxElements() {
93         return getChild(CY.STMT_MAX_ELEMENTS);
94     }
95
96     public YMinElements getMinElements() {
97         return getChild(CY.STMT_MIN_ELEMENTS);
98     }
99
100     public List<YMust> getMusts() {
101         return getChildren(CY.STMT_MUST);
102     }
103
104     public YType getType() {
105         return getChild(CY.STMT_TYPE);
106     }
107
108     public List<YUnique> getUniques() {
109         return getChildren(CY.STMT_UNIQUE);
110     }
111
112     public YUnits getUnits() {
113         return getChild(CY.STMT_UNITS);
114     }
115
116     protected void validate(final ParserExecutionContext context) {
117         if (!validateArgumentNotNullNotEmpty(context)) {
118             /* no point trying to perform more validation */
119             return;
120         }
121
122         final DeviateType deviateType = getDeviateType();
123         if (deviateType == null) {
124             context.addFinding(new Finding(this, ParserFindingType.P015_INVALID_SYNTAX_IN_DOCUMENT, "'" + domElement
125                     .getValue() + "' is not valid as argument for deviate. Use one of: not-supported, add, replace, delete."));
126         }
127     }
128
129     private static final Set<String> NOT_ALLOWED_FOR_ADD_OR_DELETE = new HashSet<>(Arrays.asList(CY.CONFIG, CY.MANDATORY,
130             CY.TYPE, CY.MAX_ELEMENTS, CY.MIN_ELEMENTS));
131
132     @Override
133     protected void subtreeProcessed(final ParserExecutionContext context) {
134
135         final DeviateType deviateType = getDeviateType();
136         if (deviateType == null) {
137             return;
138         }
139
140         final List<AbstractStatement> nonExtensionChildStatements = getNonExtensionChildStatements();
141
142         switch (deviateType) {
143             case NOT_SUPPORTED:
144                 if (!nonExtensionChildStatements.isEmpty()) {
145                     for (final AbstractStatement child : nonExtensionChildStatements) {
146                         context.addFinding(new Finding(child, ParserFindingType.P018_ILLEGAL_CHILD_STATEMENT,
147                                 "Statement '" + child
148                                         .getStatementName() + "' cannot occur under 'deviate not-supported'."));
149                     }
150                 }
151                 break;
152             case ADD:
153             case REPLACE:
154             case DELETE:
155                 if (getChildStatements().isEmpty()) {
156                     context.addFinding(new Finding(this, ParserFindingType.P019_MISSING_REQUIRED_CHILD_STATEMENT,
157                             "Statements are required under " + this.getDomElement().getNameValue() + "."));
158                 }
159                 break;
160         }
161
162         /*
163          * After some discussion on the IETF netmod mailing list, a decision was made that some
164          * properties always exist and hence can never be ADDed or DELETEd:
165          *
166          * "I think that config, mandatory, type, max-elements, min-elements cannot be added or
167          *  deleted, only replaced, because they always exist."
168          *
169          * "default, must, unique, units are all optional, and hence may be added, replaced,
170          *  or deleted"
171          */
172         if (deviateType == DeviateType.ADD || deviateType == DeviateType.DELETE) {
173             for (final AbstractStatement nonExtensionChild : nonExtensionChildStatements) {
174                 if (NOT_ALLOWED_FOR_ADD_OR_DELETE.contains(nonExtensionChild.getStatementName())) {
175                     context.addFinding(new Finding(nonExtensionChild,
176                             ParserFindingType.P167_CANNOT_USE_UNDER_DEVIATE_ADD_OR_DELETE,
177                             "This statement cannot be used under 'deviate add/delete' as it refers to a property that always exists. Use a 'deviate replace' instead."));
178                 }
179             }
180         }
181     }
182
183     public enum DeviateType {
184         NOT_SUPPORTED,
185         ADD,
186         REPLACE,
187         DELETE
188     }
189 }