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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
21 package org.oran.smo.yangtools.parser.model.statements;
23 import java.util.ArrayList;
24 import java.util.List;
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.ModulePrefixResolver;
30 import org.oran.smo.yangtools.parser.model.YangModel;
31 import org.oran.smo.yangtools.parser.model.schema.Schema;
32 import org.oran.smo.yangtools.parser.model.statements.yang.YImport;
33 import org.oran.smo.yangtools.parser.model.statements.yang.YInclude;
34 import org.oran.smo.yangtools.parser.model.statements.yang.YModule;
35 import org.oran.smo.yangtools.parser.model.statements.yang.YNamespace;
36 import org.oran.smo.yangtools.parser.model.statements.yang.YPrefix;
37 import org.oran.smo.yangtools.parser.model.statements.yang.YRevision;
38 import org.oran.smo.yangtools.parser.model.statements.yang.YSubmodule;
39 import org.oran.smo.yangtools.parser.model.yangdom.YangDomDocumentRoot;
40 import org.oran.smo.yangtools.parser.model.yangdom.YangDomElement;
43 * Root element for a YANG statement tree. Every YAM will result in a tree of type-safe statements.
44 * Usages of groupings and typedefs, augmentations and deviations, and merge-in of submodule content,
45 * will all be performed on the tree (depending on settings in the context).
47 * For each YAM, there will be both a Yang DOM element tree (see {@link YangDomDocumentRoot}) and a
48 * YANG statement tree. However, these are not the exact same, and it is important to understand the
52 * <li>The Yang DOM element tree is an exact 1:1 representation of the original YAM. It is the result
53 * of the parse of the YAM. During runtime of the parser it does not change, with some marked
54 * exceptions (see {@link YangDomDocumentRoot}).</li>
55 * <li>The YANG statement tree is the end result of applying various Yang statements (such as augment)
56 * to the YAM. This means that the YANG statement tree for a given YAM may end up pointing to DOM
57 * elements located in a different YAM (eg. the YAM that contains the 'augment' statement).</li>
60 * For compliant YAMs, an instance of this class will only ever have a single child statement (of type
61 * YModule or YSubmodule).
63 * @author Mark Hollmann
65 public class YangModelRoot extends AbstractStatement {
68 * Pointer to the root of the corresponding Yang DOM element tree.
70 private final YangDomDocumentRoot domDocumentRoot;
72 private final Schema owningSchema;
74 private YModule module = null;
75 private YSubmodule submodule = null;
78 * This is the model root of the owner of this YAM. This is either the module itself (i.e. "this")
79 * or the module owning this submodule.
81 private YangModelRoot owningYangModelRoot = this;
84 * The submodules owned by this module here, if any.
86 private List<YangModelRoot> ownedSubmodules = new ArrayList<>();
88 public YangModelRoot(final YangDomDocumentRoot domDocumentRoot, final Schema owningSchema) {
89 super(domDocumentRoot);
90 this.domDocumentRoot = domDocumentRoot;
91 this.owningSchema = owningSchema;
95 public StatementArgumentType getArgumentType() {
96 return StatementArgumentType.NO_ARG;
99 public YangDomDocumentRoot getDomDocumentRoot() {
100 return domDocumentRoot;
103 public Schema getOwningSchema() {
107 public YangModel getYangModel() {
108 return domDocumentRoot.getYangModel();
112 * Will tweak the pointer to point at the module that owns this module here.
114 public void setOwningYangModelRoot(final YangModelRoot owningYangModelRoot) {
115 this.owningYangModelRoot = owningYangModelRoot;
116 if (owningYangModelRoot != null) {
117 this.owningYangModelRoot.ownedSubmodules.add(this);
122 * Returns the module owning this submodule. Returns "this" if this YAM is a module.
124 public YangModelRoot getOwningYangModelRoot() {
125 return owningYangModelRoot;
129 * Returns the submodules owned by this module. Will be empty if this YAM here is a
130 * submodule, or if this module has no submodules.
132 public List<YangModelRoot> getOwnedSubmodules() {
133 return ownedSubmodules;
137 * The namespace of the module, or the namespace of the owning module if this here is a submodule.
138 * May return null if a namespace has not been defined on the module, or the submodule is orphaned.
140 public String getNamespace() {
143 final YNamespace yNamespace = module.getNamespace();
144 return yNamespace != null ? yNamespace.getValue() : null;
147 return owningYangModelRoot != null ? owningYangModelRoot.getNamespace() : null;
151 public ModulePrefixResolver getPrefixResolver() {
152 return getYangModel().getPrefixResolver();
156 protected void validate(ParserExecutionContext context) {
157 // nothing to validate
160 public YModule getModule() {
164 public YSubmodule getSubmodule() {
168 @SuppressWarnings("unchecked")
169 public <T extends AbstractStatement> T getModuleOrSubmodule() {
170 return module != null ? (T) module : (T) submodule;
174 * Processes the DOM and starts building the statement tree in accordance with the DOM.
176 public void processYangDom(final ParserExecutionContext context, final YangDomDocumentRoot domDocRoot) {
178 final List<YangDomElement> childrenOfDocRoot = domDocRoot.getChildren();
179 if (childrenOfDocRoot.size() != 1) {
180 context.addFinding(new Finding(getYangModel(), ParserFindingType.P013_INVALID_SYNTAX_AT_DOCUMENT_ROOT,
181 "Expected single statement ('module' or 'submodule')."));
185 final YangDomElement moduleElement = childrenOfDocRoot.get(0).getName().equals("module") ?
186 childrenOfDocRoot.get(0) :
188 final YangDomElement submoduleElement = childrenOfDocRoot.get(0).getName().equals("submodule") ?
189 childrenOfDocRoot.get(0) :
192 if (moduleElement != null) {
193 module = new YModule(this, moduleElement);
194 module.process(context);
195 } else if (submoduleElement != null) {
196 submodule = new YSubmodule(this, submoduleElement);
197 submodule.process(context);
199 context.addFinding(new Finding(getYangModel(), ParserFindingType.P013_INVALID_SYNTAX_AT_DOCUMENT_ROOT,
200 "Expected either 'module' or 'submodule' as root-statement in the document."));
204 public boolean isModule() {
205 return module != null;
208 public boolean isSubmodule() {
209 return submodule != null;
213 * The module / submodule name will always be non-null.
215 public String getModuleOrSubModuleName() {
216 return isModule() ? module.getModuleName() : submodule.getSubmoduleName();
219 public List<YRevision> getRevisions() {
220 return isModule() ? module.getRevisions() : submodule.getRevisions();
223 public List<YImport> getImports() {
224 return isModule() ? module.getImports() : submodule.getImports();
227 public List<YInclude> getIncludes() {
228 return isModule() ? module.getIncludes() : submodule.getIncludes();
232 * Returns the prefix statement of the module, or the prefix statement underneath the 'belongs-to' if
233 * it is a submodule. May return null if the prefix statement does not exist (which would be a very
236 public YPrefix getPrefix() {
239 submodule.getBelongsTo() != null ? submodule.getBelongsTo().getPrefix() : null;
242 public String getYangVersion() {
244 return module.getYangVersion() == null ? "1" : module.getYangVersion().getValue();
247 return submodule.getYangVersion() == null ? "1" : submodule.getYangVersion().getValue();