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.schema;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
28 import java.util.stream.Collectors;
30 import org.oran.smo.yangtools.parser.findings.Finding;
31 import org.oran.smo.yangtools.parser.findings.FindingsManager;
32 import org.oran.smo.yangtools.parser.findings.ParserFindingType;
33 import org.oran.smo.yangtools.parser.model.ConformanceType;
34 import org.oran.smo.yangtools.parser.model.ModuleIdentity;
35 import org.oran.smo.yangtools.parser.model.YangModel;
38 * Keeps track of all the YAMs for a given schema.
40 * @author Mark Hollmann
42 public class ModuleRegistry {
44 private final List<YangModel> yangModels = new ArrayList<>();
45 private final Set<String> duplicatedModuleNames = new HashSet<>();
47 public ModuleRegistry() {
50 public void addModule(final FindingsManager findingsManager, final YangModel yangModelToAdd) {
52 final String toAddModuleName = yangModelToAdd.getModuleIdentity().getModuleName();
53 final String toAddRevision = yangModelToAdd.getModuleIdentity().getRevision();
56 * Make sure that this very module has not been added twice, or more than once as IMPLEMENTS.
58 for (final YangModel validYangModel : yangModels) {
59 if (validYangModel.getModuleIdentity().getModuleName().equals(toAddModuleName)) {
61 duplicatedModuleNames.add(toAddModuleName);
63 if (validYangModel.getModuleIdentity().getRevision() == null && toAddRevision == null) {
64 findingsManager.addFinding(new Finding(yangModelToAdd, ParserFindingType.P003_DUPLICATE_INPUT,
65 "Same module '" + toAddModuleName + "' provided twice as input. Remove the duplicate."));
66 } else if (validYangModel.getModuleIdentity()
67 .getRevision() != null && toAddRevision != null && validYangModel.getModuleIdentity().getRevision()
68 .equals(toAddRevision)) {
69 findingsManager.addFinding(new Finding(yangModelToAdd, ParserFindingType.P003_DUPLICATE_INPUT,
70 "Same module '" + toAddModuleName + "/" + toAddRevision + "' provided twice as input. Remove the duplicate."));
73 * We are not out of the woods yet. So the revisions are not the same - but then at
74 * most one of them can be IMPLEMENTS, the others have to be IMPORTS.
76 checkForDuplicateImplements(findingsManager, toAddModuleName, yangModelToAdd);
81 yangModels.add(yangModelToAdd);
84 private void checkForDuplicateImplements(final FindingsManager findingsManager, final String toAddModuleName,
85 final YangModel modelInputToAdd) {
87 final List<YangModel> allYangFilesOfSameModuleName = byModuleName(toAddModuleName);
88 allYangFilesOfSameModuleName.add(modelInputToAdd);
90 int conformImplementsCount = 0;
92 for (final YangModel yangFileOfSameName : allYangFilesOfSameModuleName) {
93 if (yangFileOfSameName.getConformanceType() == ConformanceType.IMPLEMENT) {
94 conformImplementsCount++;
98 if (conformImplementsCount > 1) {
99 findingsManager.addFinding(new Finding(modelInputToAdd, ParserFindingType.P004_SAME_MODULE_DUPLICATE_IMPLEMENTS,
100 "(Sub-)Module with different revisions supplied multiple times as conformance IMPLEMENTS."));
104 public List<YangModel> getAllYangModels() {
105 return Collections.unmodifiableList(yangModels);
109 * Returns all modules with the given name. May return multiple results if the module is in
110 * the input multiple times (with different revisions, of course).
112 public List<YangModel> byModuleName(final String soughtModuleName) {
114 return yangModels.stream().filter(ymi -> ymi.getModuleIdentity().getModuleName().equals(soughtModuleName)).collect(
115 Collectors.toList());
119 * Returns an exact match for the supplied module name and revision (or null if no match was found).
121 * The sought revision may be null, in which case the module will be tested for having no revision.
123 public YangModel exactMatch(final String soughtModuleName, final String soughtRevision) {
125 return yangModels.stream().filter(ymi -> ymi.getModuleIdentity().getModuleName().equals(soughtModuleName)).filter(
127 if (soughtRevision == null && ymi.getModuleIdentity().getRevision() == null) {
130 if (soughtRevision != null && soughtRevision.equals(ymi.getModuleIdentity().getRevision())) {
134 }).findAny().orElse(null);
138 * Returns exactly one match, or null if not found.
140 * Where the sought revision is UNKWOWN_REVISION, will return the first found module matching
141 * the module name. Where this could be ambiguous for the caller, use byModuleName() instead
142 * and iterate over the results to find the correct module.
144 * Where the sought revision is null, or an actual revision-date, will try to find an exact match.
146 public YangModel find(final ModuleIdentity moduleIdentity) {
147 return find(moduleIdentity.getModuleName(), moduleIdentity.getRevision());
151 * Returns exactly one match, or null if not found.
153 * Where the sought revision is UNKWOWN_REVISION, will return the first found module matching
154 * the module name. Where this could be ambiguous for the caller, use byModuleName() instead
155 * and iterate over the results to find the correct module.
157 * Where the sought revision is null, or an actual revision-date, will try to find an exact match.
159 public YangModel find(final String soughtModuleName, final String soughtRevision) {
161 return yangModels.stream().filter(ymi -> ymi.getModuleIdentity().getModuleName().equals(soughtModuleName)).filter(
163 if (ModuleIdentity.UNKWOWN_REVISION.equals(soughtRevision)) {
166 if (soughtRevision == null && ymi.getModuleIdentity().getRevision() == null) {
169 if (soughtRevision != null && soughtRevision.equals(ymi.getModuleIdentity().getRevision())) {
173 }).findAny().orElse(null);