Add bounds to sphinx requirement
[ccsdk/features.git] / sdnr / wt / devicemanager-o-ran-sc / o-ran / ru-fh / provider / src / test / java / org / onap / ccsdk / features / sdnr / wt / devicemanager / oran / impl / dom / TestORANInventory.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2021 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.devicemanager.oran.impl.dom;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.net.URISyntaxException;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.List;
30 import java.util.Objects;
31 import java.util.Optional;
32 import javax.xml.stream.XMLStreamException;
33 import javax.xml.stream.XMLStreamReader;
34
35 import org.eclipse.jdt.annotation.NonNull;
36 import org.eclipse.jdt.annotation.Nullable;
37 import org.junit.AfterClass;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.Inventory;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev201110.InventoryBuilder;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yangtools.util.xml.UntrustedXML;
44 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.common.QNameModule;
47 import org.opendaylight.yangtools.yang.common.Revision;
48 import org.opendaylight.yangtools.yang.common.Uint32;
49 import org.opendaylight.yangtools.yang.common.XMLNamespace;
50 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
51 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
53 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
56 import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
57 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
58 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
59 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
60 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63 import org.xml.sax.SAXException;
64
65 public class TestORANInventory {
66
67         private static final Logger LOG = LoggerFactory.getLogger(TestORANInventory.class);
68         private static final QNameModule IETF_HARDWARE_MODULE = QNameModule
69                         .create(XMLNamespace.of("urn:ietf:params:xml:ns:yang:ietf-hardware"), Revision.of("2018-03-13"));
70         private static final QName HW_CONTAINER = QName.create(IETF_HARDWARE_MODULE, "hardware");
71         private static final QName HW_COMPONENT_LIST = QName.create(IETF_HARDWARE_MODULE, "component");
72         private static final QName HW_COMPONENT_LIST_KEY = QName.create(IETF_HARDWARE_MODULE, "name");
73         private static final QName HW_COMPONENT_LIST_CLASS = QName.create(IETF_HARDWARE_MODULE, "class");
74         private static final QName HW_COMPONENT_LIST_DESC = QName.create(IETF_HARDWARE_MODULE, "description"); // leaf:String
75         private static final QName HW_COMPONENT_LIST_PARENT = QName.create(IETF_HARDWARE_MODULE, "parent"); // leaf:leafref
76         private static final QName HW_COMPONENT_LIST_CONTAINS_CHILD = QName.create(IETF_HARDWARE_MODULE, "contains-child"); // leaf-list:leafref
77         private static final QName HW_COMPONENT_LIST_HW_REV = QName.create(IETF_HARDWARE_MODULE, "hardware-rev"); // leaf:String
78         private static final QName HW_COMPONENT_LIST_SER_NUM = QName.create(IETF_HARDWARE_MODULE, "serial-num"); // leaf:String
79         private static final QName HW_COMPONENT_LIST_MFG_NAME = QName.create(IETF_HARDWARE_MODULE, "mfg-name"); // leaf:String
80         private static final QName HW_COMPONENT_LIST_MODEL_NAME = QName.create(IETF_HARDWARE_MODULE, "model-name"); // leaf:String
81         private static final QName HW_COMPONENT_LIST_MFG_DATE = QName.create(IETF_HARDWARE_MODULE, "mfg-date"); // leaf:yang:date-and-time
82
83         private static EffectiveModelContext schemaContext;
84         private static @NonNull Inference hwContainerSchema;
85
86         @BeforeClass
87         public static void setup() throws IOException {
88                 schemaContext = YangParserTestUtils.parseYangResourceDirectory("/");
89                 hwContainerSchema = Inference.ofDataTreePath(schemaContext, HW_CONTAINER);
90                 System.out.println("URL is - " + TestORANReadHardware.class.getResource("/"));
91         }
92
93         @AfterClass
94         public static void cleanup() {
95                 schemaContext = null;
96                 hwContainerSchema = null;
97         }
98
99         @Test
100         public void testIetfHardwareFromXML() throws XMLStreamException, URISyntaxException, IOException, SAXException {
101
102                 final InputStream resourceAsStream = TestORANReadHardware.class.getResourceAsStream("/ietf-hardware.xml");
103
104                 /*
105                  * final XMLInputFactory factory = XMLInputFactory.newInstance();
106                  * XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
107                  */
108                 final XMLStreamReader reader = UntrustedXML.createXMLStreamReader(resourceAsStream);
109
110                 final NormalizedNodeResult result = new NormalizedNodeResult();
111                 final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
112
113                 final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, hwContainerSchema);
114                 xmlParser.parse(reader);
115
116                 xmlParser.flush();
117                 xmlParser.close();
118
119                 NormalizedNode transformedInput = result.getResult();
120                 NodeId nodeId = new NodeId("nSky");
121                 getInventoryList(nodeId, transformedInput);
122         }
123
124         public static List<Inventory> getInventoryList(NodeId nodeId, NormalizedNode hwData) {
125
126                 List<Inventory> inventoryResultList = new ArrayList<Inventory>();
127                 ContainerNode hwContainer = (ContainerNode) hwData;
128                 MapNode componentMap = (MapNode) hwContainer.getChildByArg(new NodeIdentifier(HW_COMPONENT_LIST));
129                 Collection<MapEntryNode> componentMapEntries = componentMap.body();
130
131                 for (MapEntryNode componentMapEntryNode : getRootComponents(componentMapEntries)) {
132                         inventoryResultList = recurseGetInventory(nodeId, componentMapEntryNode, componentMapEntries, 0,
133                                         inventoryResultList);
134                 }
135                 // Verify if result is complete
136                 if (componentMapEntries.size() != inventoryResultList.size()) {
137                         LOG.warn(
138                                         "Not all data were written to the Inventory. Potential entries with missing "
139                                                         + "contained-child. Node Id = {}, Components Found = {}, Entries written to Database = {}",
140                                         nodeId.getValue(), componentMapEntries.size(), inventoryResultList.size());
141                 }
142                 return inventoryResultList;
143         }
144
145         private static List<Inventory> recurseGetInventory(NodeId nodeId, MapEntryNode component,
146                         Collection<MapEntryNode> componentList, int treeLevel, List<Inventory> inventoryResultList) {
147                 LOG.info("Tree level = {}", treeLevel);
148                 // Add element to list, if conversion successfull
149                 Optional<Inventory> oInventory = getInternalEquipment(nodeId, component, treeLevel);
150                 if (oInventory.isPresent()) {
151                         inventoryResultList.add(oInventory.get());
152                 }
153                 // Walk through list of child keys and add to list
154                 for (String childUuid : CodeHelpers
155                                 .nonnull(ORanDMDOMUtility.getLeafListValue(component, HW_COMPONENT_LIST_CONTAINS_CHILD))) {
156                         LOG.info("Calling recursively- component is {}", childUuid);
157                         for (MapEntryNode c : getComponentsByName(childUuid, componentList)) {
158                                 inventoryResultList = recurseGetInventory(nodeId, c, componentList, treeLevel + 1, inventoryResultList);
159                         }
160                 }
161                 return inventoryResultList;
162         }
163
164         public static List<MapEntryNode> getRootComponents(Collection<MapEntryNode> componentMapEntries) {
165                 List<MapEntryNode> resultList = new ArrayList<>();
166                 for (MapEntryNode componentMapEntryNode : componentMapEntries) {
167                         if (ORanDMDOMUtility.getLeafValue(componentMapEntryNode, HW_COMPONENT_LIST_PARENT) == null) { // Root
168                                                                                                                                                                                                                         // elements
169                                                                                                                                                                                                                         // do not
170                                                                                                                                                                                                                         // have a
171                                                                                                                                                                                                                         // parent
172                                 resultList.add(componentMapEntryNode);
173                         }
174                 }
175                 return resultList;
176         }
177
178         private static List<MapEntryNode> getComponentsByName(String name, Collection<MapEntryNode> componentList) {
179                 List<MapEntryNode> resultList = new ArrayList<>();
180                 for (MapEntryNode c : componentList) {
181                         if (name.equals(ORanDMDOMUtility.getKeyValue(c))) { // <-- Component list is flat search for child's of name
182                                 resultList.add(c);
183                         }
184                 }
185                 return resultList;
186         }
187
188         public static Optional<Inventory> getInternalEquipment(NodeId nodeId, MapEntryNode component, int treeLevel) {
189
190                 // Make sure that expected data are not null
191                 Objects.requireNonNull(nodeId);
192                 Objects.requireNonNull(component);
193
194                 // Read manadatory data
195
196                 @Nullable
197                 String nodeIdString = nodeId.getValue();
198                 @Nullable
199                 String uuid = ORanDMDOMUtility.getKeyValue(component);
200                 @Nullable
201                 String idParent = ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_PARENT);
202                 @Nullable
203                 String uuidParent = idParent != null ? idParent : uuid; // <- Passt nicht
204                 LOG.info("Dump = {}, {}, {}, {}", uuidParent, uuid, treeLevel, nodeIdString);
205                 // do consistency check if all mandatory parameters are there
206                 if (treeLevel >= 0 && nodeIdString != null && uuid != null && uuidParent != null) {
207                         LOG.info("Creating new instance of Inventory");
208                         // Build output data
209
210                         InventoryBuilder inventoryBuilder = new InventoryBuilder();
211
212                         // General assumed as mandatory
213                         inventoryBuilder.setNodeId(nodeIdString);
214                         inventoryBuilder.setUuid(uuid);
215                         inventoryBuilder.setParentUuid(uuidParent);
216                         inventoryBuilder.setTreeLevel(Uint32.valueOf(treeLevel));
217
218                         // -- String list with ids of holders (optional)
219                         inventoryBuilder
220                                         .setContainedHolder(ORanDMDOMUtility.getLeafListValue(component, HW_COMPONENT_LIST_CONTAINS_CHILD));
221
222                         // -- Manufacturer related things (optional)
223                         @Nullable
224                         String mfgName = ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_MFG_NAME);
225                         inventoryBuilder.setManufacturerName(mfgName);
226                         inventoryBuilder.setManufacturerIdentifier(mfgName);
227
228                         // Equipment type (optional)
229                         inventoryBuilder.setDescription(ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_DESC));
230                         inventoryBuilder.setModelIdentifier(ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_MODEL_NAME));
231
232                         inventoryBuilder.setPartTypeId(ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_CLASS));
233
234                         inventoryBuilder.setTypeName(ORanDMDOMUtility.getKeyValue(component));
235                         inventoryBuilder.setVersion(ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_HW_REV));
236
237                         // Equipment instance (optional)
238                         @Nullable
239                         String mfgDate = ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_MFG_DATE);
240                         if (mfgDate != null) {
241                                 inventoryBuilder.setDate(mfgDate);
242                         }
243                         inventoryBuilder.setSerial(ORanDMDOMUtility.getLeafValue(component, HW_COMPONENT_LIST_SER_NUM));
244
245                         return Optional.of(inventoryBuilder.build());
246                 }
247                 return Optional.empty();
248         }
249
250 }