15c4eea254b09fee0c42e7ee196879984509d5b0
[dcaegen2/services/sdk.git] /
1 /*
2  * ============LICENSE_START====================================
3  * DCAEGEN2-SERVICES-SDK
4  * =========================================================
5  * Copyright (C) 2019 Nokia. All rights reserved.
6  * =========================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *       http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=====================================
19  */
20 package org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.listener;
21
22 import com.google.gson.JsonArray;
23 import com.google.gson.JsonElement;
24 import com.google.gson.JsonObject;
25 import io.vavr.collection.List;
26 import org.jetbrains.annotations.NotNull;
27
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.Map.Entry;
31
32 import static java.lang.String.valueOf;
33
34
35 /**
36  * Class responsible for creating MerkleTree structure from JsonObject.
37  *
38  * @since 1.1.2
39  */
40 class MerkleTreeParser {
41
42     /**
43      * <p> Method used to parse {@link JsonObject} into {@link MerkleTree} structure.</p>
44      * <p> The algorithm will recursively create mapping of (path in tree)->(value) from JsonObject
45      * and use it to create MerkleTree by means of {@link MerkleTree#add(List, Object)} method. </p>
46      * <p> Each JsonObject will append it's key to path until value of primitive type is encountered.
47      * For each JsonArray element artificial path is created by creating lables from sequential integers.
48      * This results in array split into multiple nodes in MerkleTree structure.</p>
49      *
50      * <p>Example. For JsonObject:
51      * <pre>
52      * {
53      *      "p1": "v1",
54      *      "p2": ["v2", "v3"]
55      *      "p3": {
56      *          "p4": "v4"
57      *      }
58      * }
59      * </pre>
60      * following map would be created:</p>
61      * <pre>
62      *  "v1" <- ["p1"]
63      *  "v2" <- ["p2", "0"]
64      *  "v3" <- ["p2", "1"]
65      *  "v4" <- ["p3", "p4"]
66      * </pre>
67      *
68      * @param json JsonObject to be parsed
69      * @since 1.1.2
70      */
71     MerkleTree<String> fromJsonObject(final @NotNull JsonObject json) {
72         MerkleTree<String> tree = MerkleTree.emptyWithDefaultDigest(String::getBytes);
73         for (Entry<String, JsonElement> entry : json.entrySet()) {
74             tree = treeEnhancedWithEntry(tree, entry);
75         }
76
77         return tree;
78     }
79
80     private MerkleTree<String> treeEnhancedWithEntry(final MerkleTree<String> tree,
81                                                      final Entry<String, JsonElement> entry) {
82         return createTreeFromValuesPaths(tree, pathsToValues(entry, List.empty()));
83     }
84
85     private Map<List<String>, String> pathsToValues(Entry<String, JsonElement> entry, List<String> elementPathPrefix) {
86         return pathsToValuesFromJsonElement(entry.getKey(), entry.getValue(), elementPathPrefix);
87     }
88
89     private Map<List<String>, String> pathsToValuesFromJsonElement(final String jsonKey,
90                                                                    final JsonElement element,
91                                                                    final List<String> elementPathPrefix) {
92         final HashMap<List<String>, String> pathToValue = new HashMap<>();
93         final List<String> newPrefix = elementPathPrefix.append(jsonKey);
94
95         if (element.isJsonObject()) {
96             element.getAsJsonObject()
97                     .entrySet()
98                     .forEach(entry -> pathToValue.putAll(pathsToValues(entry, newPrefix)));
99         } else if (element.isJsonArray()) {
100             pathToValue.putAll(handleArray(newPrefix, element.getAsJsonArray()));
101         } else if (element.isJsonPrimitive()) {
102             pathToValue.put(newPrefix, element.getAsString());
103         } else if (element.isJsonNull()) {
104             pathToValue.put(newPrefix, null);
105         }
106         return pathToValue;
107     }
108
109     private HashMap<List<String>, String> handleArray(List<String> newPrefix, JsonArray jsonArray) {
110         final HashMap<List<String>, String> hashMap = new HashMap<>();
111         int labelIndex = 0;
112
113         for (JsonElement jsonElement : jsonArray) {
114             String jsonKey = valueOf(labelIndex++);
115             hashMap.putAll(pathsToValuesFromJsonElement(jsonKey, jsonElement, newPrefix));
116         }
117         return hashMap;
118     }
119
120     private MerkleTree<String> createTreeFromValuesPaths(MerkleTree<String> tree,
121                                                          final Map<List<String>, String> pathToValue) {
122         for (Entry<List<String>, String> entry : pathToValue.entrySet()) {
123             List<String> path = entry.getKey();
124             String value = entry.getValue();
125             tree = tree.add(path, value);
126         }
127         return tree;
128     }
129 }