From 29d80646b7acb5dd731d4218829626826c79c239 Mon Sep 17 00:00:00 2001 From: jianwu chen Date: Sun, 4 Dec 2022 18:09:12 -0800 Subject: [PATCH] Support TreeDoc.dedupeNodes(); update TDNode.hashCode() to not include key --- pom.xml | 8 ++--- .../main/java/org/jsonex/treedoc/TDNode.java | 8 +++-- .../main/java/org/jsonex/treedoc/TreeDoc.java | 33 +++++++++++++++++-- .../java/org/jsonex/treeedoc/TDPathTest.java | 19 ----------- .../resources/org/jsonex/treedoc/test.json | 17 ++++++++++ .../org/jsonex/treedoc/test_deduped.json | 19 +++++++++++ 6 files changed, 75 insertions(+), 29 deletions(-) delete mode 100644 treedoc/src/test/java/org/jsonex/treeedoc/TDPathTest.java create mode 100644 treedoc/src/test/resources/org/jsonex/treedoc/test.json create mode 100644 treedoc/src/test/resources/org/jsonex/treedoc/test_deduped.json diff --git a/pom.xml b/pom.xml index 7c09e9d..a6b1e7f 100755 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ org.projectlombok lombok - 1.18.16 + 1.18.24 provided @@ -124,7 +124,7 @@ org.projectlombok lombok - 1.18.2 + 1.18.24 @@ -182,7 +182,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.21.0 + 2.12.4 true @@ -218,7 +218,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 + 3.4.1 attach-javadocs diff --git a/treedoc/src/main/java/org/jsonex/treedoc/TDNode.java b/treedoc/src/main/java/org/jsonex/treedoc/TDNode.java index ec4a773..78cfeff 100644 --- a/treedoc/src/main/java/org/jsonex/treedoc/TDNode.java +++ b/treedoc/src/main/java/org/jsonex/treedoc/TDNode.java @@ -27,6 +27,7 @@ import static org.jsonex.core.util.LangUtil.orElse; import static org.jsonex.core.util.ListUtil.last; +import static org.jsonex.core.util.ListUtil.map; /** A Node in TreeDoc */ @RequiredArgsConstructor @@ -249,11 +250,11 @@ public StringBuilder toString(StringBuilder sb, boolean includeRootKey, boolean } public List childrenValueAsList() { - return getChildren() == null ? Collections.emptyList() : ListUtil.map(getChildren(), c -> c.getValue()); + return getChildren() == null ? Collections.emptyList() : map(getChildren(), c -> c.getValue()); } public List> childrenValueAsListOfList() { - return getChildren() == null ? Collections.emptyList() : ListUtil.map(getChildren(), c -> c.childrenValueAsList()); + return getChildren() == null ? Collections.emptyList() : map(getChildren(), c -> c.childrenValueAsList()); } @Override public boolean equals(Object o) { @@ -267,7 +268,8 @@ public List> childrenValueAsListOfList() { return Objects.equals(key, tdNode.key) && Objects.equals(value, tdNode.value) && Objects.equals(children, tdNode.children); } + /** Hash code of value and children, key is not included */ @Override public int hashCode() { - return hash.getOrCompute(() -> Objects.hash(key, value, children)); + return hash.getOrCompute(() -> Objects.hash(value, children, map(children, TDNode::getKey))); } } diff --git a/treedoc/src/main/java/org/jsonex/treedoc/TreeDoc.java b/treedoc/src/main/java/org/jsonex/treedoc/TreeDoc.java index c8ed41c..d0f2818 100644 --- a/treedoc/src/main/java/org/jsonex/treedoc/TreeDoc.java +++ b/treedoc/src/main/java/org/jsonex/treedoc/TreeDoc.java @@ -6,10 +6,9 @@ import lombok.experimental.Accessors; import java.net.URI; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; +import java.util.*; +import static java.lang.String.format; import static org.jsonex.core.util.LangUtil.doIfNotNull; import static org.jsonex.core.util.ListUtil.mapKeys; @@ -64,4 +63,32 @@ public static TreeDoc merge(Collection nodes) { return result; } + + /** + * Dedupe the nodes that are with the same contends by comparing the hash + */ + public void dedupeNodes() { + Map hashToNodeMap = new LinkedHashMap<>(); + Queue queue = new LinkedList<>(); + queue.add(root); + while(!queue.isEmpty()) { + TDNode n = queue.poll(); + if (n.isLeaf()) + continue; // Don't dedupe leaf node and array node + int hash = n.hashCode(); + TDNode refNode = hashToNodeMap.get(hash); + if ( refNode != null && refNode.getType() == TDNode.Type.MAP) { + if (refNode.getChild(TDNode.ID_KEY) == null) + refNode.createChild(TDNode.ID_KEY).setValue(format("%x", hash)); + n.children.clear();; + n.setType(TDNode.Type.MAP).createChild(TDNode.REF_KEY).setValue(format("#%x", hash)); + } else { + hashToNodeMap.put(hash, n); + if (n.hasChildren()) + for (TDNode cn : n.children) { + queue.add(cn); + } + } + } + } } diff --git a/treedoc/src/test/java/org/jsonex/treeedoc/TDPathTest.java b/treedoc/src/test/java/org/jsonex/treeedoc/TDPathTest.java deleted file mode 100644 index 9497a4a..0000000 --- a/treedoc/src/test/java/org/jsonex/treeedoc/TDPathTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.jsonex.treeedoc; - -import org.jsonex.treedoc.TDPath; -import org.junit.Test; - -import static org.jsonex.treedoc.TDPath.Part.*; -import static org.jsonex.treedoc.TDPath.parse; -import static org.junit.Assert.assertEquals; - -public class TDPathTest { - @Test public void testParse() { - assertEquals(TDPath.ofParts(ofRoot(), ofChild("p1"), ofChild("p2")), parse("/p1/p2")); - assertEquals(TDPath.ofParts(ofRelative(1), ofChild("p1"), ofChild("p2")), parse("../p1/p2")); - assertEquals(TDPath.ofParts(ofRelative(0), ofChild("p1"), ofChild("p2")), parse("./p1/p2")); - assertEquals(TDPath.ofParts(ofChildOrId("#100", "100"), ofChild("p1"), ofChild("p2")), parse("#100/p1/p2")); - assertEquals(TDPath.ofParts(ofRoot(), ofChild("p1"), ofChild("p2")), parse("#/p1/p2")); - assertEquals(TDPath.ofParts(ofRelative(1)), parse("../")); - } -} diff --git a/treedoc/src/test/resources/org/jsonex/treedoc/test.json b/treedoc/src/test/resources/org/jsonex/treedoc/test.json new file mode 100644 index 0000000..a151329 --- /dev/null +++ b/treedoc/src/test/resources/org/jsonex/treedoc/test.json @@ -0,0 +1,17 @@ +{ + "a": 1, + "b": { + "c": [1,2,3,4], + "d": { + "e": 1, + "f": 2 + } + }, + "e": { + "c": [1, 2, 3, 4], + "d": { + "e": 1, + "f": 2 + } + } +} \ No newline at end of file diff --git a/treedoc/src/test/resources/org/jsonex/treedoc/test_deduped.json b/treedoc/src/test/resources/org/jsonex/treedoc/test_deduped.json new file mode 100644 index 0000000..39024db --- /dev/null +++ b/treedoc/src/test/resources/org/jsonex/treedoc/test_deduped.json @@ -0,0 +1,19 @@ +{ + a:1, + b:{ + c:[ + 1, + 2, + 3, + 4 + ], + d:{ + e:1, + f:2 + }, + $id:"5a9c3cc0" + }, + e:{ + $ref:"#5a9c3cc0" + } +} \ No newline at end of file