13084e043b1970cacb444400a78a2e0832f5124b
[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.data.instance;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.function.Predicate;
27 import java.util.stream.Collectors;
28
29 import org.oran.smo.yangtools.parser.data.dom.YangDataDomNode;
30 import org.oran.smo.yangtools.parser.model.statements.AbstractStatement;
31
32 /**
33  * This class represents a structural element, which can be either a true (singleton)
34  * container, or an instance of a list.
35  *
36  * @author Mark Hollmann
37  */
38 public abstract class AbstractStructureInstance extends AbstractDataInstance {
39
40     /**
41      * The child structure instances, if any (i.e. containers / lists under this container / list).
42      */
43     private final List<AbstractStructureInstance> structureChildren = new ArrayList<>();
44
45     /**
46      * The content values, if any (non-presence containers are usually empty), of the structure (i.e. leaf or leaf-list
47      * data).
48      */
49     private final List<AbstractContentInstance> contentChildren = new ArrayList<>();
50
51     /**
52      * Constructor for a structure instance that was specified in data.
53      */
54     public AbstractStructureInstance(final AbstractStatement schemaNode, final YangDataDomNode dataDomNode,
55             final AbstractStructureInstance parent) {
56         super(schemaNode, dataDomNode, parent);
57     }
58
59     /**
60      * Constructor for a structure instance that was created by default (i.e. not specified in data).
61      */
62     public AbstractStructureInstance(final AbstractStatement schemaNode, final AbstractStructureInstance parent) {
63         super(schemaNode, parent);
64     }
65
66     public void addStructureChild(final AbstractStructureInstance structureChild) {
67         structureChildren.add(structureChild);
68     }
69
70     public List<AbstractStructureInstance> getStructureChildren() {
71         return structureChildren;
72     }
73
74     public void addContentChild(final AbstractContentInstance contentChild) {
75         contentChildren.add(contentChild);
76     }
77
78     public List<AbstractContentInstance> getContentChildren() {
79         return contentChildren;
80     }
81
82     /**
83      * Returns the container instance of the given namespace and name. May return null if not found.
84      */
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);
88     }
89
90     public boolean hasContainerInstance(final String namespace, final String name) {
91         return structureChildren.stream().filter(new InstanceTester(namespace, name, ContainerInstance.class)).findFirst()
92                 .isPresent();
93     }
94
95     /**
96      * Returns the leaf instance of the given namespace and name. May return null if not found.
97      */
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);
101     }
102
103     public boolean hasLeafInstance(final String namespace, final String name) {
104         return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafInstance.class)).findFirst()
105                 .isPresent();
106     }
107
108     /**
109      * Returns all occurrences of list instances of the given namespace and name.
110      */
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());
114     }
115
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()
119                 .orElse(null);
120     }
121
122     public boolean hasListInstance(final String namespace, final String name) {
123         return structureChildren.stream().filter(new InstanceTester(namespace, name, ListInstance.class)).findFirst()
124                 .isPresent();
125     }
126
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();
130     }
131
132     /**
133      * Returns all occurrences of leaf-list instances of the given namespace and name.
134      */
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());
138     }
139
140     /**
141      * Returns the values of leaf-list. Note that the order may be undefined where a merge of multiple inputs happened.
142      */
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());
146     }
147
148     public boolean hasLeafListInstance(final String namespace, final String name) {
149         return contentChildren.stream().filter(new InstanceTester(namespace, name, LeafListInstance.class)).findFirst()
150                 .isPresent();
151     }
152
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();
156     }
157
158     /**
159      * Returns the anydata instance of the given namespace and name. May return null if not found.
160      */
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);
164     }
165
166     public boolean hasAnyDataInstance(final String namespace, final String name) {
167         return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyDataInstance.class)).findFirst()
168                 .isPresent();
169     }
170
171     /**
172      * Returns the anyxml instance of the given namespace and name. May return null if not found.
173      */
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);
177     }
178
179     public boolean hasAnyXmlInstance(final String namespace, final String name) {
180         return contentChildren.stream().filter(new InstanceTester(namespace, name, AnyXmlInstance.class)).findFirst()
181                 .isPresent();
182     }
183
184     private class InstanceTester implements Predicate<AbstractDataInstance> {
185
186         private final String namespace;
187         private final String name;
188         private final Class<? extends AbstractDataInstance> soughtClazz;
189
190         public <T extends AbstractDataInstance> InstanceTester(final String namespace, final String name,
191                 final Class<T> soughtClazz) {
192             this.namespace = namespace;
193             this.name = name;
194             this.soughtClazz = soughtClazz;
195         }
196
197         @Override
198         public boolean test(final AbstractDataInstance dataInstance) {
199             return name.equals(dataInstance.getName()) && namespace.equals(dataInstance.getNamespace()) && (dataInstance
200                     .getClass().equals(soughtClazz));
201         }
202     }
203
204     /**
205      * Returns a human-readable string with the full path to the Container node.
206      */
207     public String getPath() {
208
209         final List<AbstractStructureInstance> containersFromRoot = new ArrayList<>(10);
210         AbstractStructureInstance runContainer = this;
211
212         while (runContainer != null) {
213             containersFromRoot.add(0, runContainer);
214             runContainer = runContainer.getParent();
215         }
216
217         final StringBuilder sb = new StringBuilder();
218         for (final AbstractStructureInstance container : containersFromRoot) {
219             sb.append('/').append(container.getName());
220         }
221
222         return sb.toString();
223     }
224
225 }