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.List;
26 import java.util.function.Predicate;
27 import java.util.stream.Collectors;
29 import org.oran.smo.yangtools.parser.data.dom.YangDataDomNode;
30 import org.oran.smo.yangtools.parser.model.statements.AbstractStatement;
33 * This class represents a structural element, which can be either a true (singleton)
34 * container, or an instance of a list.
36 * @author Mark Hollmann
38 public abstract class AbstractStructureInstance extends AbstractDataInstance {
41 * The child structure instances, if any (i.e. containers / lists under this container / list).
43 private final List<AbstractStructureInstance> structureChildren = new ArrayList<>();
46 * The content values, if any (non-presence containers are usually empty), of the structure (i.e. leaf or leaf-list
49 private final List<AbstractContentInstance> contentChildren = new ArrayList<>();
52 * Constructor for a structure instance that was specified in data.
54 public AbstractStructureInstance(final AbstractStatement schemaNode, final YangDataDomNode dataDomNode,
55 final AbstractStructureInstance parent) {
56 super(schemaNode, dataDomNode, parent);
60 * Constructor for a structure instance that was created by default (i.e. not specified in data).
62 public AbstractStructureInstance(final AbstractStatement schemaNode, final AbstractStructureInstance parent) {
63 super(schemaNode, parent);
66 public void addStructureChild(final AbstractStructureInstance structureChild) {
67 structureChildren.add(structureChild);
70 public List<AbstractStructureInstance> getStructureChildren() {
71 return structureChildren;
74 public void addContentChild(final AbstractContentInstance contentChild) {
75 contentChildren.add(contentChild);
78 public List<AbstractContentInstance> getContentChildren() {
79 return contentChildren;
83 * Returns the container instance of the given namespace and name. May return null if not found.
85 public ContainerInstance getContainerInstance(final String namespace, final String name) {
86 return (ContainerInstance) structureChildren.stream().filter(new InstanceTester(namespace, name,
87 ContainerInstance.class)).findFirst().orElse(null);
90 public boolean hasContainerInstance(final String namespace, final String name) {
91 return structureChildren.stream().filter(new InstanceTester(namespace, name, ContainerInstance.class)).findFirst()
96 * Returns the leaf instance of the given namespace and name. May return null if not found.
98 public LeafInstance getLeafInstance(final String namespace, final String name) {
99 return (LeafInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, LeafInstance.class))
100 .findFirst().orElse(null);
103 public boolean hasLeafInstance(final String namespace, final String name) {
104 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafInstance.class)).findFirst()
109 * Returns all occurrences of list instances of the given namespace and name.
111 public List<ListInstance> getListInstances(final String namespace, final String name) {
112 return (List<ListInstance>) structureChildren.stream().filter(new InstanceTester(namespace, name,
113 ListInstance.class)).map(child -> (ListInstance) child).collect(Collectors.toList());
116 public ListInstance getListInstance(final String namespace, final String name, final Map<String, String> keyValues) {
117 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).map(
118 child -> (ListInstance) child).filter(listChild -> keyValues.equals(listChild.getKeyValues())).findFirst()
122 public boolean hasListInstance(final String namespace, final String name) {
123 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).findFirst()
127 public boolean hasListInstance(final String namespace, final String name, final Map<String, String> keyValues) {
128 return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).filter(
129 child -> keyValues.equals(((ListInstance) child).getKeyValues())).findFirst().isPresent();
133 * Returns all occurrences of leaf-list instances of the given namespace and name.
135 public List<LeafListInstance> getLeafListInstances(final String namespace, final String name) {
136 return (List<LeafListInstance>) contentChildren.stream().filter(new InstanceTester(namespace, name,
137 LeafListInstance.class)).map(child -> (LeafListInstance) child).collect(Collectors.toList());
141 * Returns the values of leaf-list. Note that the order may be undefined where a merge of multiple inputs happened.
143 public List<Object> getLeafListValues(final String namespace, final String name) {
144 return (List<Object>) contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class))
145 .map(child -> ((LeafListInstance) child).getValue()).collect(Collectors.toList());
148 public boolean hasLeafListInstance(final String namespace, final String name) {
149 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class)).findFirst()
153 public boolean hasLeafListInstance(final String namespace, final String name, final Object value) {
154 return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class)).filter(
155 child -> value.equals(((LeafListInstance) child).getValue())).findFirst().isPresent();
159 * Returns the anydata instance of the given namespace and name. May return null if not found.
161 public AnyDataInstance getAnyDataInstance(final String namespace, final String name) {
162 return (AnyDataInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, AnyDataInstance.class))
163 .findFirst().orElse(null);
166 public boolean hasAnyDataInstance(final String namespace, final String name) {
167 return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyDataInstance.class)).findFirst()
172 * Returns the anyxml instance of the given namespace and name. May return null if not found.
174 public AnyXmlInstance getAnyXmlInstance(final String namespace, final String name) {
175 return (AnyXmlInstance) contentChildren.stream().filter(new InstanceTester(namespace, name, AnyXmlInstance.class))
176 .findFirst().orElse(null);
179 public boolean hasAnyXmlInstance(final String namespace, final String name) {
180 return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyXmlInstance.class)).findFirst()
184 private class InstanceTester implements Predicate<AbstractDataInstance> {
186 private final String namespace;
187 private final String name;
188 private final Class<? extends AbstractDataInstance> soughtClazz;
190 public <T extends AbstractDataInstance> InstanceTester(final String namespace, final String name,
191 final Class<T> soughtClazz) {
192 this.namespace = namespace;
194 this.soughtClazz = soughtClazz;
198 public boolean test(final AbstractDataInstance dataInstance) {
199 return name.equals(dataInstance.getName()) && namespace.equals(dataInstance.getNamespace()) && (dataInstance
200 .getClass().equals(soughtClazz));
205 * Returns a human-readable string with the full path to the Container node.
207 public String getPath() {
209 final List<AbstractStructureInstance> containersFromRoot = new ArrayList<>(10);
210 AbstractStructureInstance runContainer = this;
212 while (runContainer != null) {
213 containersFromRoot.add(0, runContainer);
214 runContainer = runContainer.getParent();
217 final StringBuilder sb = new StringBuilder();
218 for (final AbstractStructureInstance container : containersFromRoot) {
219 sb.append('/').append(container.getName());
222 return sb.toString();