From fc88ac806f5650ec9f70c4849e3815132038ec5c Mon Sep 17 00:00:00 2001 From: Filip Krzywka Date: Tue, 19 Feb 2019 13:33:45 +0100 Subject: Parse JsonObject to MerkleTree Change-Id: I424eec2c4c47ddff1bff3ef612a7b31a62e1cf3e Issue-ID: DCAEGEN2-1254 Signed-off-by: Filip Krzywka --- .../cbs/client/api/listener/MerkleTreeParser.java | 129 +++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/listener/MerkleTreeParser.java (limited to 'rest-services/cbs-client/src/main') diff --git a/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/listener/MerkleTreeParser.java b/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/listener/MerkleTreeParser.java new file mode 100644 index 00000000..15c4eea2 --- /dev/null +++ b/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/listener/MerkleTreeParser.java @@ -0,0 +1,129 @@ +/* + * ============LICENSE_START==================================== + * DCAEGEN2-SERVICES-SDK + * ========================================================= + * Copyright (C) 2019 Nokia. All rights reserved. + * ========================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END===================================== + */ +package org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.listener; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.vavr.collection.List; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import static java.lang.String.valueOf; + + +/** + * Class responsible for creating MerkleTree structure from JsonObject. + * + * @since 1.1.2 + */ +class MerkleTreeParser { + + /** + *

Method used to parse {@link JsonObject} into {@link MerkleTree} structure.

+ *

The algorithm will recursively create mapping of (path in tree)->(value) from JsonObject + * and use it to create MerkleTree by means of {@link MerkleTree#add(List, Object)} method.

+ *

Each JsonObject will append it's key to path until value of primitive type is encountered. + * For each JsonArray element artificial path is created by creating lables from sequential integers. + * This results in array split into multiple nodes in MerkleTree structure.

+ * + *

Example. For JsonObject: + *

+     * {
+     *      "p1": "v1",
+     *      "p2": ["v2", "v3"]
+     *      "p3": {
+     *          "p4": "v4"
+     *      }
+     * }
+     * 
+ * following map would be created:

+ *
+     *  "v1" <- ["p1"]
+     *  "v2" <- ["p2", "0"]
+     *  "v3" <- ["p2", "1"]
+     *  "v4" <- ["p3", "p4"]
+     * 
+ * + * @param json JsonObject to be parsed + * @since 1.1.2 + */ + MerkleTree fromJsonObject(final @NotNull JsonObject json) { + MerkleTree tree = MerkleTree.emptyWithDefaultDigest(String::getBytes); + for (Entry entry : json.entrySet()) { + tree = treeEnhancedWithEntry(tree, entry); + } + + return tree; + } + + private MerkleTree treeEnhancedWithEntry(final MerkleTree tree, + final Entry entry) { + return createTreeFromValuesPaths(tree, pathsToValues(entry, List.empty())); + } + + private Map, String> pathsToValues(Entry entry, List elementPathPrefix) { + return pathsToValuesFromJsonElement(entry.getKey(), entry.getValue(), elementPathPrefix); + } + + private Map, String> pathsToValuesFromJsonElement(final String jsonKey, + final JsonElement element, + final List elementPathPrefix) { + final HashMap, String> pathToValue = new HashMap<>(); + final List newPrefix = elementPathPrefix.append(jsonKey); + + if (element.isJsonObject()) { + element.getAsJsonObject() + .entrySet() + .forEach(entry -> pathToValue.putAll(pathsToValues(entry, newPrefix))); + } else if (element.isJsonArray()) { + pathToValue.putAll(handleArray(newPrefix, element.getAsJsonArray())); + } else if (element.isJsonPrimitive()) { + pathToValue.put(newPrefix, element.getAsString()); + } else if (element.isJsonNull()) { + pathToValue.put(newPrefix, null); + } + return pathToValue; + } + + private HashMap, String> handleArray(List newPrefix, JsonArray jsonArray) { + final HashMap, String> hashMap = new HashMap<>(); + int labelIndex = 0; + + for (JsonElement jsonElement : jsonArray) { + String jsonKey = valueOf(labelIndex++); + hashMap.putAll(pathsToValuesFromJsonElement(jsonKey, jsonElement, newPrefix)); + } + return hashMap; + } + + private MerkleTree createTreeFromValuesPaths(MerkleTree tree, + final Map, String> pathToValue) { + for (Entry, String> entry : pathToValue.entrySet()) { + List path = entry.getKey(); + String value = entry.getValue(); + tree = tree.add(path, value); + } + return tree; + } +} -- cgit 1.2.3-korg