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.data.instance;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
29 import java.util.function.Predicate;
30 import java.util.stream.Collectors;
32 import org.oran.smo.yangtools.parser.data.dom.YangDataDomNode;
33 import org.oran.smo.yangtools.parser.model.statements.AbstractStatement;
34 import org.oran.smo.yangtools.parser.util.NamespaceModuleIdentifier;
37 * This class represents a structural element, which can be either a true (singleton)
38 * container, or an instance of a list.
40 * @author Mark Hollmann
42 public abstract class AbstractStructureInstance extends AbstractDataInstance {
45 * The child structure instances, if any (i.e. containers / lists under this container / list).
47 private final List<AbstractStructureInstance> structureChildren = new ArrayList<>();
50 * The content values, if any (non-presence containers are usually empty), of the structure (i.e. leaf or leaf-list
53 private final List<AbstractContentInstance> contentChildren = new ArrayList<>();
55 private Set<NamespaceModuleIdentifier> emptyChildLeafListIdentifiers;
58 * Constructor for a structure instance that was specified in data.
60 public AbstractStructureInstance(final AbstractStatement schemaNode, final YangDataDomNode dataDomNode,
61 final AbstractStructureInstance parent) {
62 super(schemaNode, dataDomNode, parent);
66 * Constructor for a structure instance that was created by default (i.e. not specified in data).
68 public AbstractStructureInstance(final AbstractStatement schemaNode, final AbstractStructureInstance parent) {
69 super(schemaNode, parent);
72 public void addStructureChild(final AbstractStructureInstance structureChild) {
73 structureChildren.add(structureChild);
76 public List<AbstractStructureInstance> getStructureChildren() {
77 return structureChildren;
80 public void addContentChild(final AbstractContentInstance contentChild) {
81 contentChildren.add(contentChild);
84 public List<AbstractContentInstance> getContentChildren() {
85 return contentChildren;
88 public void setEmptyChildLeafListIdentifiers(final Set<NamespaceModuleIdentifier> val) {
89 this.emptyChildLeafListIdentifiers = val;
92 public void addEmptyChildLeafListIdentifiers(final Set<NamespaceModuleIdentifier> toAdd) {
93 if (toAdd.isEmpty()) {
96 if (emptyChildLeafListIdentifiers == null) {
97 emptyChildLeafListIdentifiers = new HashSet<>();
99 emptyChildLeafListIdentifiers.addAll(toAdd);
102 public Set<NamespaceModuleIdentifier> getEmptyChildLeafListIdentifiers() {
103 return emptyChildLeafListIdentifiers == null ? Collections.emptySet() : emptyChildLeafListIdentifiers;
107 * Returns the container instance of the given namespace and name. May return null if not found.
109 public ContainerInstance getContainerInstance(final String namespace, final String name) {
110 return (ContainerInstance) structureChildren.stream().filter(new InstanceTester(namespace, name,
111 ContainerInstance.class)).findFirst().orElse(null);
114 public boolean hasContainerInstance(final String namespace, final String name) {
115 return structureChildren.stream().filter(new InstanceTester(namespace, name, ContainerInstance.class)).findFirst()
120 * Returns the leaf instance of the given namespace and name. May return null if not found.
122 public LeafInstance getLeafInstance(final String namespace, final String name) {
123 return (LeafInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, LeafInstance.class))
124 .findFirst().orElse(null);
127 public boolean hasLeafInstance(final String namespace, final String name) {
128 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafInstance.class)).findFirst()
133 * Returns all occurrences of list instances of the given namespace and name.
135 public List<ListInstance> getListInstances(final String namespace, final String name) {
136 return (List<ListInstance>) structureChildren.stream().filter(new InstanceTester(namespace, name,
137 ListInstance.class)).map(child -> (ListInstance) child).collect(Collectors.toList());
140 public ListInstance getListInstance(final String namespace, final String name, final Map<String, String> keyValues) {
141 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).map(
142 child -> (ListInstance) child).filter(listChild -> keyValues.equals(listChild.getKeyValues())).findFirst()
146 public boolean hasListInstance(final String namespace, final String name) {
147 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).findFirst()
151 public boolean hasListInstance(final String namespace, final String name, final Map<String, String> keyValues) {
152 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).filter(
153 child -> keyValues.equals(((ListInstance) child).getKeyValues())).findFirst().isPresent();
157 * Returns all occurrences of leaf-list instances of the given namespace and name.
159 public List<LeafListInstance> getLeafListInstances(final String namespace, final String name) {
160 return (List<LeafListInstance>) contentChildren.stream().filter(new InstanceTester(namespace, name,
161 LeafListInstance.class)).map(child -> (LeafListInstance) child).collect(Collectors.toList());
165 * Returns the values of leaf-list. Note that the order may be undefined where a merge of multiple inputs happened.
167 public List<Object> getLeafListValues(final String namespace, final String name) {
168 return (List<Object>) contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class))
169 .map(child -> ((LeafListInstance) child).getValue()).collect(Collectors.toList());
172 public boolean hasLeafListInstance(final String namespace, final String name) {
173 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class)).findFirst()
177 public boolean hasLeafListInstance(final String namespace, final String name, final Object value) {
178 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class)).filter(
179 child -> value.equals(((LeafListInstance) child).getValue())).findFirst().isPresent();
183 * Returns the anydata instance of the given namespace and name. May return null if not found.
185 public AnyDataInstance getAnyDataInstance(final String namespace, final String name) {
186 return (AnyDataInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, AnyDataInstance.class))
187 .findFirst().orElse(null);
190 public boolean hasAnyDataInstance(final String namespace, final String name) {
191 return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyDataInstance.class)).findFirst()
196 * Returns the anyxml instance of the given namespace and name. May return null if not found.
198 public AnyXmlInstance getAnyXmlInstance(final String namespace, final String name) {
199 return (AnyXmlInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, AnyXmlInstance.class))
200 .findFirst().orElse(null);
203 public boolean hasAnyXmlInstance(final String namespace, final String name) {
204 return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyXmlInstance.class)).findFirst()
208 private class InstanceTester implements Predicate<AbstractDataInstance> {
210 private final String namespace;
211 private final String name;
212 private final Class<? extends AbstractDataInstance> soughtClazz;
214 public <T extends AbstractDataInstance> InstanceTester(final String namespace, final String name,
215 final Class<T> soughtClazz) {
216 this.namespace = namespace;
218 this.soughtClazz = soughtClazz;
222 public boolean test(final AbstractDataInstance dataInstance) {
223 return name.equals(dataInstance.getName()) && namespace.equals(dataInstance.getNamespace()) && (dataInstance
224 .getClass().equals(soughtClazz));
229 * Returns a human-readable string with the full path to the Container node.
231 public String getPath() {
233 final List<AbstractStructureInstance> containersFromRoot = new ArrayList<>(10);
234 AbstractStructureInstance runContainer = this;
236 while (runContainer != null) {
237 containersFromRoot.add(0, runContainer);
238 runContainer = runContainer.getParent();
241 final StringBuilder sb = new StringBuilder();
242 for (final AbstractStructureInstance container : containersFromRoot) {
243 sb.append('/').append(container.getName());
246 return sb.toString();