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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================
20 package org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.listener;
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;
28 import java.util.HashMap;
30 import java.util.Map.Entry;
32 import static java.lang.String.valueOf;
36 * Class responsible for creating MerkleTree structure from JsonObject.
40 class MerkleTreeParser {
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>
50 * <p>Example. For JsonObject:
60 * following map would be created:</p>
65 * "v4" <- ["p3", "p4"]
68 * @param json JsonObject to be parsed
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);
80 private MerkleTree<String> treeEnhancedWithEntry(final MerkleTree<String> tree,
81 final Entry<String, JsonElement> entry) {
82 return createTreeFromValuesPaths(tree, pathsToValues(entry, List.empty()));
85 private Map<List<String>, String> pathsToValues(Entry<String, JsonElement> entry, List<String> elementPathPrefix) {
86 return pathsToValuesFromJsonElement(entry.getKey(), entry.getValue(), elementPathPrefix);
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);
95 if (element.isJsonObject()) {
96 element.getAsJsonObject()
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);
109 private HashMap<List<String>, String> handleArray(List<String> newPrefix, JsonArray jsonArray) {
110 final HashMap<List<String>, String> hashMap = new HashMap<>();
113 for (JsonElement jsonElement : jsonArray) {
114 String jsonKey = valueOf(labelIndex++);
115 hashMap.putAll(pathsToValuesFromJsonElement(jsonKey, jsonElement, newPrefix));
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);