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("../")); - } -}