From f945af160a6ac2b688c70e86d079bc727195e055 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 11:29:42 +0100 Subject: [PATCH 1/7] NodeItem: deprecate dynamic node names With the aim of moving towards immutable objects, node shouldn't have dynamic names. I've not found a use for them in my own projects. --- src/main/java/net/kemitix/node/NodeItem.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java index ec71f11..899bf5c 100644 --- a/src/main/java/net/kemitix/node/NodeItem.java +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -52,7 +52,10 @@ public class NodeItem implements Node { * * @param data the data or null * @param nameSupplier the name supplier function + * + * @deprecated dynamic names don't work on immutable objects */ + @Deprecated public NodeItem( final T data, final Function, String> nameSupplier) { this(data); @@ -89,7 +92,10 @@ public class NodeItem implements Node { * @param data the data or null * @param nameSupplier the name supplier function * @param parent the parent node + * + * @deprecated dynamic names don't work on immutable objects */ + @Deprecated public NodeItem( final T data, final Function, String> nameSupplier, final Node parent) { From 39721e77c1636441c473e8f197e81d3d4c6c8f29 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 11:36:46 +0100 Subject: [PATCH 2/7] pom.xml: add dependency on net.trajano.commons to utility class testing --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index dd9ddbf..3071a0d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 3.4.1 4.2.0 + 2.1.0 @@ -69,5 +70,11 @@ ${assertj.version} test + + net.trajano.commons + commons-testing + ${trajano-commons-testing.version} + test + From 51e8194db76037a10619f3c493b1064ea1bd75f7 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 11:37:15 +0100 Subject: [PATCH 3/7] Nodes: add utility class to create Node instances --- src/main/java/net/kemitix/node/Nodes.java | 66 +++++++++++++++++++ src/test/java/net/kemitix/node/NodesTest.java | 62 +++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/main/java/net/kemitix/node/Nodes.java create mode 100644 src/test/java/net/kemitix/node/NodesTest.java diff --git a/src/main/java/net/kemitix/node/Nodes.java b/src/main/java/net/kemitix/node/Nodes.java new file mode 100644 index 0000000..24dc50e --- /dev/null +++ b/src/main/java/net/kemitix/node/Nodes.java @@ -0,0 +1,66 @@ +package net.kemitix.node; + +/** + * Utility class for {@link Node} items. + * + * @author pcampbell + */ +public final class Nodes { + + private Nodes() { + } + + /** + * Creates a new unnamed root node. + * + * @param data the data the node will contain + * @param the type of the data + * + * @return the new node + */ + public static Node unnamedRoot(final T data) { + return new NodeItem<>(data); + } + + /** + * Creates a new named root node. + * + * @param data the data the node will contain + * @param name the name of the node + * @param the type of the data + * + * @return the new node + */ + public static Node namedRoot(final T data, final String name) { + return new NodeItem<>(data, name); + } + + /** + * Creates a new unnamed child node. + * + * @param data the data the node will contain + * @param parent the parent of the node + * @param the type of the data + * + * @return the new node + */ + public static Node unnamedChild(final T data, final Node parent) { + return new NodeItem<>(data, parent); + } + + /** + * Creates a new named child node. + * + * @param data the data the node will contain + * @param name the name of the node + * @param parent the parent of the node + * @param the type of the data + * + * @return the new node + */ + public static Node namedChild( + final T data, final String name, final Node parent) { + return new NodeItem<>(data, name, parent); + } + +} diff --git a/src/test/java/net/kemitix/node/NodesTest.java b/src/test/java/net/kemitix/node/NodesTest.java new file mode 100644 index 0000000..ace4f79 --- /dev/null +++ b/src/test/java/net/kemitix/node/NodesTest.java @@ -0,0 +1,62 @@ +package net.kemitix.node; + +import lombok.val; +import org.assertj.core.api.SoftAssertions; +import org.junit.Test; + +import static net.trajano.commons.testing.UtilityClassTestUtil + .assertUtilityClassWellDefined; + +/** + * Tests for {@link Nodes}. + * + * @author pcampbell + */ +public class NodesTest { + + @Test + public void shouldBeValidUtilityClass() throws Exception { + assertUtilityClassWellDefined(Nodes.class); + } + + @Test + public void shouldCreateUnnamedRoot() throws Exception { + val node = Nodes.unnamedRoot("data"); + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(node.getData()).contains("data"); + softly.assertThat(node.getName()).isNull(); + softly.assertAll(); + } + + @Test + public void shouldCreateNamedRoot() throws Exception { + val node = Nodes.namedRoot("data", "name"); + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(node.getData()).contains("data"); + softly.assertThat(node.getName()).isEqualTo("name"); + softly.assertAll(); + } + + @Test + public void shouldCreateUnnamedChild() throws Exception { + val parent = Nodes.unnamedRoot("root"); + val node = Nodes.unnamedChild("data", parent); + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(node.getData()).contains("data"); + softly.assertThat(node.getName()).isNull(); + softly.assertThat(node.getParent()).contains(parent); + softly.assertAll(); + } + + @Test + public void shouldCreateNamedChild() throws Exception { + val parent = Nodes.unnamedRoot("root"); + val node = Nodes.namedChild("data", "child", parent); + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(node.getData()).contains("data"); + softly.assertThat(node.getName()).isEqualTo("child"); + softly.assertThat(node.getParent()).contains(parent); + softly.assertAll(); + } + +} From e9b43cb73c87a628b1a06eba5b67a96b8c9557ae Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 12:04:24 +0100 Subject: [PATCH 4/7] [BREAKING] NodeItem: require instantiation using Nodes This breaks the existing API where NodeItem could be instantiated directly. --- src/main/java/net/kemitix/node/NodeItem.java | 8 +- .../java/net/kemitix/node/NodeItemTest.java | 225 +++++++++--------- 2 files changed, 117 insertions(+), 116 deletions(-) diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java index 899bf5c..f54b6eb 100644 --- a/src/main/java/net/kemitix/node/NodeItem.java +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -32,7 +32,7 @@ public class NodeItem implements Node { * @param data the data or null * @param name the name */ - public NodeItem(final T data, final String name) { + NodeItem(final T data, final String name) { this(data); this.name = name; } @@ -42,7 +42,7 @@ public class NodeItem implements Node { * * @param data the data or null */ - public NodeItem(final T data) { + NodeItem(final T data) { this.data = data; this.nameSupplier = (n) -> null; } @@ -68,7 +68,7 @@ public class NodeItem implements Node { * @param data the data or null * @param parent the parent node */ - public NodeItem(final T data, final Node parent) { + NodeItem(final T data, final Node parent) { this.data = data; setParent(parent); } @@ -80,7 +80,7 @@ public class NodeItem implements Node { * @param name the name * @param parent the parent node */ - public NodeItem(final T data, final String name, final Node parent) { + NodeItem(final T data, final String name, final Node parent) { this.data = data; this.name = name; setParent(parent); diff --git a/src/test/java/net/kemitix/node/NodeItemTest.java b/src/test/java/net/kemitix/node/NodeItemTest.java index 700b053..87b5a69 100644 --- a/src/test/java/net/kemitix/node/NodeItemTest.java +++ b/src/test/java/net/kemitix/node/NodeItemTest.java @@ -33,7 +33,7 @@ public class NodeItemTest { //given val data = "this node data"; //when - node = new NodeItem<>(data); + node = Nodes.unnamedRoot(data); //then assertThat(node.getData()).as("can get the data from a node"). contains(data); @@ -42,7 +42,7 @@ public class NodeItemTest { @Test public void canCreateAnEmptyAndUnnamedNode() { //when - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //then SoftAssertions softly = new SoftAssertions(); softly.assertThat(node.isEmpty()).as("node is empty").isTrue(); @@ -64,7 +64,7 @@ public class NodeItemTest { @Test public void canSetName() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //when node.setName("named"); //then @@ -77,7 +77,7 @@ public class NodeItemTest { @Test public void shouldHaveNullForDefaultParent() { //given - node = new NodeItem<>("data"); + node = Nodes.unnamedRoot("data"); //then assertThat(node.getParent()).as( "node created without a parent has no parent").isEmpty(); @@ -89,9 +89,9 @@ public class NodeItemTest { @Test public void shouldReturnNodeParent() { //given - val parent = new NodeItem("parent"); + val parent = Nodes.unnamedRoot("parent"); //when - node = new NodeItem<>("subject", parent); + node = Nodes.unnamedChild("subject", parent); //then assertThat(node.getParent()).as( "node created with a parent can return the parent") @@ -105,8 +105,8 @@ public class NodeItemTest { @Test public void setParentShouldThrowNodeExceptionWhenParentIsAChild() { //given - node = new NodeItem<>("subject"); - val child = new NodeItem("child", node); + node = Nodes.unnamedRoot("subject"); + val child = Nodes.unnamedChild("child", node); exception.expect(NodeException.class); exception.expectMessage("Parent is a descendant"); //when @@ -121,9 +121,9 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void shouldAddNewNodeAsChildToParent() { //given - val parent = new NodeItem("parent"); + val parent = Nodes.unnamedRoot("parent"); //when - node = new NodeItem<>("subject", parent); + node = Nodes.unnamedChild("subject", parent); //then assertThat(parent.getChildren()).as( "when a node is created with a parent, the parent has the new" @@ -136,8 +136,8 @@ public class NodeItemTest { @Test public void shouldReturnSetParent() { //given - node = new NodeItem<>("subject"); - val parent = new NodeItem("parent"); + node = Nodes.unnamedRoot("subject"); + val parent = Nodes.unnamedRoot("parent"); //when node.setParent(parent); //then @@ -152,7 +152,7 @@ public class NodeItemTest { @Test public void shouldThrowNPEWhenSetParentNull() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("parent"); //when @@ -166,7 +166,7 @@ public class NodeItemTest { @Test public void setParentShouldThrowNodeExceptionWhenParentIsSelf() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NodeException.class); exception.expectMessage("Parent is a descendant"); //when @@ -180,9 +180,9 @@ public class NodeItemTest { @Test public void shouldUpdateOldParentWhenNodeSetToNewParent() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val child = node.createChild("child"); - val newParent = new NodeItem("newParent"); + val newParent = Nodes.unnamedRoot("newParent"); //when child.setParent(newParent); //then @@ -201,9 +201,9 @@ public class NodeItemTest { @Test public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val child = node.createChild("child"); - val newParent = new NodeItem("newParent"); + val newParent = Nodes.unnamedRoot("newParent"); //when newParent.addChild(child); //then @@ -223,7 +223,7 @@ public class NodeItemTest { @Test public void shouldThrowNPEWhenAddingNullAsChild() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("child"); //when @@ -237,8 +237,8 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void shouldReturnAddedChild() { //given - node = new NodeItem<>("subject"); - val child = new NodeItem("child"); + node = Nodes.unnamedRoot("subject"); + val child = Nodes.unnamedRoot("child"); //when node.addChild(child); //then @@ -253,7 +253,7 @@ public class NodeItemTest { @Test public void addChildShouldThrowNodeExceptionWhenAddingANodeAsOwnChild() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NodeException.class); exception.expectMessage("Child is an ancestor"); //then @@ -266,7 +266,7 @@ public class NodeItemTest { @Test public void addChildShouldThrowNodeExceptionWhenAddingSelfAsChild() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NodeException.class); exception.expectMessage("Child is an ancestor"); //when @@ -280,8 +280,8 @@ public class NodeItemTest { @Test public void addChildShouldThrowNodeExceptionWhenChildIsParent() { //given - val parent = new NodeItem("parent"); - node = new NodeItem<>("subject", parent); + val parent = Nodes.unnamedRoot("parent"); + node = Nodes.unnamedChild("subject", parent); exception.expect(NodeException.class); exception.expectMessage("Child is an ancestor"); //when @@ -295,9 +295,9 @@ public class NodeItemTest { @Test public void addChildShouldThrowNodeExceptionWhenAddingGrandParentAsChild() { //given - val grandParent = new NodeItem("grandparent"); - val parent = new NodeItem("parent", grandParent); - node = new NodeItem<>("subject", parent); + val grandParent = Nodes.unnamedRoot("grandparent"); + val parent = Nodes.unnamedChild("parent", grandParent); + node = Nodes.unnamedChild("subject", parent); exception.expect(NodeException.class); exception.expectMessage("Child is an ancestor"); //when @@ -310,8 +310,8 @@ public class NodeItemTest { @Test public void shouldSetParentOnChildWhenAddedAsChild() { //given - node = new NodeItem<>("subject"); - val child = new NodeItem("child"); + node = Nodes.unnamedRoot("subject"); + val child = Nodes.unnamedRoot("child"); //when node.addChild(child); //then @@ -327,11 +327,11 @@ public class NodeItemTest { public void shouldWalkTreeToNode() { //given val grandparent = "grandparent"; - val grandParentNode = new NodeItem(grandparent); + val grandParentNode = Nodes.unnamedRoot(grandparent); val parent = "parent"; - val parentNode = new NodeItem(parent, grandParentNode); + val parentNode = Nodes.unnamedChild(parent, grandParentNode); val subject = "subject"; - node = new NodeItem<>(subject, parentNode); + node = Nodes.unnamedChild(subject, parentNode); //when val result = grandParentNode.findInPath(Arrays.asList(parent, subject)); //then @@ -352,9 +352,9 @@ public class NodeItemTest { public void shouldNotFindNonExistentChildNode() { //given val parent = "parent"; - val parentNode = new NodeItem(parent); + val parentNode = Nodes.unnamedRoot(parent); val subject = "subject"; - node = new NodeItem<>(subject, parentNode); + node = Nodes.unnamedChild(subject, parentNode); //when val result = parentNode.findInPath(Arrays.asList(subject, "no child")); //then @@ -369,7 +369,7 @@ public class NodeItemTest { @Test public void shouldThrowNEWhenWalkTreeNull() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("path"); //when @@ -383,7 +383,7 @@ public class NodeItemTest { @Test public void shouldReturnEmptyForEmptyWalkTreePath() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); //when val result = node.findInPath(Collections.emptyList()); //then @@ -396,7 +396,7 @@ public class NodeItemTest { @Test public void shouldCreateDescendantNodes() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val alphaData = "alpha"; val betaData = "beta"; val gammaData = "gamma"; @@ -445,7 +445,7 @@ public class NodeItemTest { @Test public void createDescendantLineShouldThrowNPEWhenDescendantsAreNull() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("descendants"); //when @@ -458,7 +458,7 @@ public class NodeItemTest { @Test public void shouldChangeNothingWhenCreateDescendantEmpty() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); //when node.createDescendantLine(Collections.emptyList()); //then @@ -473,9 +473,9 @@ public class NodeItemTest { @Test public void shouldFindExistingChildNode() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val childData = "child"; - val child = new NodeItem(childData, node); + val child = Nodes.unnamedChild(childData, node); //when val found = node.findOrCreateChild(childData); //then @@ -490,7 +490,7 @@ public class NodeItemTest { @Test public void shouldFindCreateNewChildNode() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val childData = "child"; //when val found = node.findOrCreateChild(childData); @@ -506,7 +506,7 @@ public class NodeItemTest { @Test public void findOrCreateChildShouldThrowNPEFWhenChildIsNull() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("child"); //when @@ -519,9 +519,9 @@ public class NodeItemTest { @Test public void shouldGetChild() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val childData = "child"; - val child = new NodeItem(childData); + val child = Nodes.unnamedRoot(childData); node.addChild(child); //when val found = node.findChild(childData); @@ -541,7 +541,7 @@ public class NodeItemTest { @Test public void getChildShouldThrowNPEWhenThereIsNoChild() { //given - node = new NodeItem<>("data"); + node = Nodes.unnamedRoot("data"); exception.expect(NullPointerException.class); exception.expectMessage("child"); //when @@ -555,7 +555,7 @@ public class NodeItemTest { @Test public void shouldCreateChild() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); val childData = "child"; //when val child = node.createChild(childData); @@ -580,7 +580,7 @@ public class NodeItemTest { @Test public void createChildShouldThrowNPEWhenChildIsNull() { //given - node = new NodeItem<>("subject"); + node = Nodes.unnamedRoot("subject"); exception.expect(NullPointerException.class); exception.expectMessage("child"); //when @@ -599,7 +599,7 @@ public class NodeItemTest { public void getNameShouldUseParentNameSupplier() { //given val root = new NodeItem("root", n -> n.getData().get()); - node = new NodeItem<>("child", root); + node = Nodes.unnamedChild("child", root); //then assertThat(node.getName()).isEqualTo("child"); } @@ -622,7 +622,7 @@ public class NodeItemTest { node = new NodeItem<>("root", n -> n.getData().get()); val child = new NodeItem("child", Object::toString); node.addChild(child); - val grandChild = new NodeItem<>("grandchild", child); + val grandChild = Nodes.unnamedChild("grandchild", child); //then assertThat(node.getName()).isEqualTo("root"); assertThat(child.getName()).isNotEqualTo("child"); @@ -631,8 +631,8 @@ public class NodeItemTest { @Test public void getNameShouldWorkWithoutNameSupplier() { - node = new NodeItem<>(null, "root"); - val namedchild = new NodeItem<>("named", "Alice", node); + node = Nodes.namedRoot(null, "root"); + val namedchild = Nodes.namedChild("named", "Alice", node); //then assertThat(node.getName()).isEqualTo("root"); assertThat(namedchild.getName()).isEqualTo("Alice"); @@ -640,22 +640,22 @@ public class NodeItemTest { @Test public void canCreateRootNodeWithoutData() { - node = new NodeItem<>(null, "empty"); + node = Nodes.namedRoot(null, "empty"); assertThat(node.getData()).isEmpty(); } @Test public void canCreateRootNodeWithoutDataButWithNameSupplier() { - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); assertThat(node.getData()).isEmpty(); } @Test public void getChildNamedFindsChild() { //given - node = new NodeItem<>(null, "root"); - val alpha = new NodeItem(null, "alpha"); - val beta = new NodeItem(null, "beta"); + node = Nodes.namedRoot("root data", "root"); + val alpha = Nodes.namedRoot("alpha data", "alpha"); + val beta = Nodes.namedRoot("beta data", "beta"); node.addChild(alpha); node.addChild(beta); //when @@ -667,9 +667,9 @@ public class NodeItemTest { @Test public void getChildNamedFindsNothing() { //given - node = new NodeItem<>(null, "root"); - val alpha = new NodeItem(null, "alpha"); - val beta = new NodeItem(null, "beta"); + node = Nodes.namedRoot("root data", "root"); + val alpha = Nodes.namedRoot("alpha data", "alpha"); + val beta = Nodes.namedRoot("beta data", "beta"); node.addChild(alpha); node.addChild(beta); exception.expect(NodeException.class); @@ -681,10 +681,10 @@ public class NodeItemTest { @Test public void nodeNamesAreUniqueWithinAParent() { //given - node = new NodeItem<>(null, "root"); - val alpha = new NodeItem(null, "alpha"); + node = Nodes.namedRoot("root data", "root"); + val alpha = Nodes.namedRoot("alpha data", "alpha"); node.addChild(alpha); - val beta = new NodeItem(null, "alpha"); + val beta = Nodes.namedRoot("beta data", "alpha"); exception.expect(NodeException.class); exception.expectMessage("Node with that name already exists here"); //when @@ -694,8 +694,8 @@ public class NodeItemTest { @Test public void canPlaceNodeInTreeByPathNames() { //given - node = new NodeItem<>(null, "root"); // create a root - val four = new NodeItem("data", "four"); + node = Nodes.namedRoot("root data", "root"); // create a root + val four = Nodes.namedRoot("data", "four"); //when node.insertInPath(four, "one", "two", "three"); //then @@ -717,9 +717,9 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void canPlaceInTreeUnderExistingNode() { //given - node = new NodeItem<>(null, "root"); - val child = new NodeItem("child data", "child"); - val grandchild = new NodeItem("grandchild data", "grandchild"); + node = Nodes.namedRoot(null, "root"); + val child = Nodes.namedRoot("child data", "child"); + val grandchild = Nodes.namedRoot("grandchild data", "grandchild"); //when node.insertInPath(child); // as root/child node.insertInPath(grandchild, "child"); // as root/child/grandchild @@ -734,9 +734,9 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void canPlaceInTreeAboveExistingNode() { //given - node = new NodeItem<>(null, "root"); - val child = new NodeItem("child data", "child"); - val grandchild = new NodeItem("grandchild data", "grandchild"); + node = Nodes.namedRoot(null, "root"); + val child = Nodes.namedRoot("child data", "child"); + val grandchild = Nodes.namedRoot("grandchild data", "grandchild"); //when node.insertInPath(grandchild, "child"); node.insertInPath(child); @@ -752,7 +752,7 @@ public class NodeItemTest { @Test public void removingParentFromNodeWithNoParentIsNoop() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //when node.removeParent(); } @@ -760,8 +760,8 @@ public class NodeItemTest { @Test public void removingParentFromNodeWithParentRemovesParent() { //given - node = new NodeItem<>(null); - val child = new NodeItem(null, node); + node = Nodes.unnamedRoot(null); + val child = Nodes.unnamedChild("child data", node); //when child.removeParent(); //then @@ -775,22 +775,22 @@ public class NodeItemTest { exception.expect(NodeException.class); exception.expectMessage( "A non-empty node named 'grandchild' already exists here"); - node = new NodeItem<>(null); - val child = new NodeItem(null, "child", node); - new NodeItem<>("data", "grandchild", child); + node = Nodes.unnamedRoot(null); + val child = Nodes.namedChild("child data", "child", node); + Nodes.namedChild("data", "grandchild", child); // root -> child -> grandchild // only grandchild has data //when // attempt to add another node called 'grandchild' to 'child' - node.insertInPath(new NodeItem<>("cuckoo", "grandchild"), "child"); + node.insertInPath(Nodes.namedRoot("cuckoo", "grandchild"), "child"); } @Test @SuppressWarnings("unchecked") public void placeNodeInTreeWhenAddedNodeIsUnnamed() { //given - node = new NodeItem<>(null); - final Node newNode = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); + final Node newNode = Nodes.unnamedRoot(null); //when node.insertInPath(newNode); //then @@ -801,12 +801,12 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void placeNodeInTreeWhenEmptyChildWithTargetNameExists() { //given - node = new NodeItem<>(null); - final NodeItem child = new NodeItem<>(null, "child"); - final NodeItem target = new NodeItem<>(null, "target"); + node = Nodes.unnamedRoot(null); + final Node child = Nodes.namedRoot(null, "child"); + final Node target = Nodes.namedRoot(null, "target"); node.addChild(child); child.addChild(target); - final NodeItem addMe = new NodeItem<>("I'm new", "target"); + val addMe = Nodes.namedRoot("I'm new", "target"); assertThat(addMe.getParent()).isEmpty(); assertThat(child.getChildByName("target").isEmpty()).as( "target starts empty").isTrue(); @@ -823,7 +823,7 @@ public class NodeItemTest { //given exception.expect(NullPointerException.class); exception.expectMessage("name"); - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //when node.findChildByName(null); } @@ -831,7 +831,7 @@ public class NodeItemTest { @Test public void isNamedNull() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //then assertThat(node.isNamed()).isFalse(); } @@ -839,7 +839,7 @@ public class NodeItemTest { @Test public void isNamedEmpty() { //given - node = new NodeItem<>(null, ""); + node = Nodes.namedRoot(null, ""); //then assertThat(node.isNamed()).isFalse(); } @@ -847,7 +847,7 @@ public class NodeItemTest { @Test public void isNamedNamed() { //given - node = new NodeItem<>(null, "named"); + node = Nodes.namedRoot(null, "named"); //then assertThat(node.isNamed()).isTrue(); } @@ -858,7 +858,7 @@ public class NodeItemTest { // provider //given node = new NodeItem<>("data", n -> n.getData().get()); - final NodeItem child = new NodeItem<>("other", node); + val child = Nodes.unnamedChild("other", node); assertThat(node.getName()).as("initial root name").isEqualTo("data"); assertThat(child.getName()).as("initial child name").isEqualTo("other"); //when @@ -872,7 +872,7 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void removeChildRemovesTheChild() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); Node child = node.createChild("child"); assertThat(node.getChildren()).containsExactly(child); //then @@ -885,13 +885,14 @@ public class NodeItemTest { @Test public void drawTreeIsCorrect() { //given - node = new NodeItem<>(null, "root"); - val bob = new NodeItem(null, "bob", node); - val alice = new NodeItem(null, "alice", node); - new NodeItem<>(null, "dave", alice); - new NodeItem<>(null, bob); // has no name and no children so no included - val kim = new NodeItem(null, node); // nameless mother - new NodeItem<>(null, "lucy", kim); + node = Nodes.namedRoot(null, "root"); + val bob = Nodes.namedChild("bob data", "bob", node); + val alice = Nodes.namedChild("alice data", "alice", node); + Nodes.namedChild("dave data", "dave", alice); + Nodes.unnamedChild("bob's child's data", + bob); // has no name and no children so no included + val kim = Nodes.unnamedChild("kim data", node); // nameless mother + Nodes.namedChild("lucy data", "lucy", kim); //when val tree = node.drawTree(0); //then @@ -907,7 +908,7 @@ public class NodeItemTest { @Test public void canChangeNodeData() { //given - node = new NodeItem<>("initial"); + node = Nodes.unnamedRoot("initial"); //when node.setData("updated"); //then @@ -918,7 +919,7 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void canCreateNamedChild() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //when Node child = node.createChild("child data", "child name"); //then @@ -930,10 +931,10 @@ public class NodeItemTest { @Test public void canGetChildWhenFound() { //given - node = new NodeItem<>("data"); - Node child = new NodeItem<>("child data", "child name", node); + node = Nodes.unnamedRoot("data"); + val child = Nodes.namedChild("child data", "child name", node); //when - Node found = node.getChild("child data"); + val found = node.getChild("child data"); //then assertThat(found).isSameAs(child); } @@ -943,7 +944,7 @@ public class NodeItemTest { //given exception.expect(NodeException.class); exception.expectMessage("Child not found"); - node = new NodeItem<>("data"); + node = Nodes.unnamedRoot("data"); //when node.getChild("child data"); } @@ -952,9 +953,9 @@ public class NodeItemTest { @SuppressWarnings("unchecked") public void constructorWithNameSupplierAndParentBeChildOfParent() { //given - node = new NodeItem<>(null); + node = Nodes.unnamedRoot(null); //when - NodeItem child = new NodeItem<>(null, node); + val child = Nodes.unnamedChild("child data", node); //then assertThat(child.getParent()).contains(node); assertThat(node.getChildren()).containsExactly(child); @@ -965,7 +966,7 @@ public class NodeItemTest { public void removeParentCopiesRootNameSupplier() { //given node = new NodeItem<>("root data", n -> "root supplier"); - val child = new NodeItem<>("child data", node); + val child = Nodes.unnamedChild("child data", node); assertThat(child.getName()).isEqualTo("root supplier"); //when child.removeParent(); @@ -990,7 +991,7 @@ public class NodeItemTest { public void setNameToNullRevertsToParentNameSupplier() { //given node = new NodeItem<>(null, n -> "root supplier"); - val child = new NodeItem(null, "child name", node); + val child = Nodes.namedChild("child data", "child name", node); assertThat(child.getName()).isEqualTo("child name"); //when child.setName(null); @@ -1034,8 +1035,8 @@ public class NodeItemTest { return ""; }; node = new NodeItem<>(null, pathNameSupplier); - val child = new NodeItem("child", node); - val grandchild = new NodeItem("grandchild", child); + val child = Nodes.unnamedChild("child", node); + val grandchild = Nodes.unnamedChild("grandchild", child); //then assertThat(grandchild.getName()).isEqualTo("/child/grandchild"); } @@ -1043,8 +1044,8 @@ public class NodeItemTest { @Test public void canSafelyHandleFindChildWhenAChildHasNoData() { //given - node = new NodeItem<>(null); - new NodeItem<>(null, node); + node = Nodes.unnamedRoot(null); + Nodes.unnamedChild(null, node); //when node.findChild("data"); } From 2da1d9aa3dfd747146fa46390f780a9b2a3c1393 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 12:27:50 +0100 Subject: [PATCH 5/7] NodeItem: add deprecated to implementation of deprecated interface method --- src/main/java/net/kemitix/node/NodeItem.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java index f54b6eb..3afbe8b 100644 --- a/src/main/java/net/kemitix/node/NodeItem.java +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -235,6 +235,7 @@ public class NodeItem implements Node { * @return the found or created child node */ @Override + @Deprecated public Node findOrCreateChild(final T child) { if (child == null) { throw new NullPointerException("child"); From 1b0b0222815a284703f1e1a79e77f35b1992f7c4 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 12:36:40 +0100 Subject: [PATCH 6/7] NodeItem.findChild(): rewrite stream filter --- src/main/java/net/kemitix/node/NodeItem.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java index 3afbe8b..9e34a83 100644 --- a/src/main/java/net/kemitix/node/NodeItem.java +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -255,10 +255,10 @@ public class NodeItem implements Node { if (child == null) { throw new NullPointerException("child"); } - return children.stream() - .filter(n -> !n.isEmpty()) - .filter(n -> n.getData().get().equals(child)) - .findAny(); + return children.stream().filter(node -> { + final Optional d = node.getData(); + return d.isPresent() && d.get().equals(child); + }).findAny(); } @Override From 7a10498a31b51f78e3af567a9d5cd62070cd0b0c Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Aug 2016 12:42:21 +0100 Subject: [PATCH 7/7] NodeItem: remove dynamic name support for nodes --- src/main/java/net/kemitix/node/NodeItem.java | 32 ---- .../java/net/kemitix/node/NodeItemTest.java | 168 ------------------ 2 files changed, 200 deletions(-) diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java index 9e34a83..1a83c73 100644 --- a/src/main/java/net/kemitix/node/NodeItem.java +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -47,21 +47,6 @@ public class NodeItem implements Node { this.nameSupplier = (n) -> null; } - /** - * Creates root node with a name supplier. - * - * @param data the data or null - * @param nameSupplier the name supplier function - * - * @deprecated dynamic names don't work on immutable objects - */ - @Deprecated - public NodeItem( - final T data, final Function, String> nameSupplier) { - this(data); - this.nameSupplier = nameSupplier; - } - /** * Creates a node with a parent. * @@ -86,23 +71,6 @@ public class NodeItem implements Node { setParent(parent); } - /** - * Creates a node with a name supplier and a parent. - * - * @param data the data or null - * @param nameSupplier the name supplier function - * @param parent the parent node - * - * @deprecated dynamic names don't work on immutable objects - */ - @Deprecated - public NodeItem( - final T data, final Function, String> nameSupplier, - final Node parent) { - this(data, nameSupplier); - setParent(parent); - } - private String generateName() { return getNameSupplier().apply(this); } diff --git a/src/test/java/net/kemitix/node/NodeItemTest.java b/src/test/java/net/kemitix/node/NodeItemTest.java index 87b5a69..247e7fb 100644 --- a/src/test/java/net/kemitix/node/NodeItemTest.java +++ b/src/test/java/net/kemitix/node/NodeItemTest.java @@ -8,13 +8,9 @@ import org.junit.rules.ExpectedException; import static org.assertj.core.api.Assertions.assertThat; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Collections; import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; /** * Test for {@link NodeItem}. @@ -50,17 +46,6 @@ public class NodeItemTest { softly.assertAll(); } - @Test - public void canCreateNodeWithParentAndCustomNameSupplier() { - //given - node = new NodeItem<>(null, n -> "root name supplier"); - //when - val child = new NodeItem(null, n -> "overridden", node); - //then - assertThat(child.getName()).isEqualTo("overridden"); - assertThat(child.getParent()).contains(node); - } - @Test public void canSetName() { //given @@ -587,69 +572,12 @@ public class NodeItemTest { node.createChild(null); } - @Test - public void getNameShouldBeCorrect() { - //given - node = new NodeItem<>("subject", n -> n.getData().get()); - //then - assertThat(node.getName()).isEqualTo("subject"); - } - - @Test - public void getNameShouldUseParentNameSupplier() { - //given - val root = new NodeItem("root", n -> n.getData().get()); - node = Nodes.unnamedChild("child", root); - //then - assertThat(node.getName()).isEqualTo("child"); - } - - @Test - public void getNameShouldReturnNameForNonStringData() { - val root = new NodeItem(LocalDate.parse("2016-05-23"), n -> { - if (n.isEmpty()) { - return null; - } - return n.getData().get().format(DateTimeFormatter.BASIC_ISO_DATE); - - }); - //then - assertThat(root.getName()).isEqualTo("20160523"); - } - - @Test - public void getNameShouldUseClosestNameSupplier() { - node = new NodeItem<>("root", n -> n.getData().get()); - val child = new NodeItem("child", Object::toString); - node.addChild(child); - val grandChild = Nodes.unnamedChild("grandchild", child); - //then - assertThat(node.getName()).isEqualTo("root"); - assertThat(child.getName()).isNotEqualTo("child"); - assertThat(grandChild.getName()).isNotEqualTo("grandchild"); - } - - @Test - public void getNameShouldWorkWithoutNameSupplier() { - node = Nodes.namedRoot(null, "root"); - val namedchild = Nodes.namedChild("named", "Alice", node); - //then - assertThat(node.getName()).isEqualTo("root"); - assertThat(namedchild.getName()).isEqualTo("Alice"); - } - @Test public void canCreateRootNodeWithoutData() { node = Nodes.namedRoot(null, "empty"); assertThat(node.getData()).isEmpty(); } - @Test - public void canCreateRootNodeWithoutDataButWithNameSupplier() { - node = Nodes.unnamedRoot(null); - assertThat(node.getData()).isEmpty(); - } - @Test public void getChildNamedFindsChild() { //given @@ -852,22 +780,6 @@ public class NodeItemTest { assertThat(node.isNamed()).isTrue(); } - @Test - public void removeParentNodeProvidesSameNameSupplier() { - // once a node has it's parent removed it should provide a default name - // provider - //given - node = new NodeItem<>("data", n -> n.getData().get()); - val child = Nodes.unnamedChild("other", node); - assertThat(node.getName()).as("initial root name").isEqualTo("data"); - assertThat(child.getName()).as("initial child name").isEqualTo("other"); - //when - child.removeParent(); - //then - assertThat(node.getName()).as("final root name").isEqualTo("data"); - assertThat(child.getName()).as("final child name").isEqualTo("other"); - } - @Test @SuppressWarnings("unchecked") public void removeChildRemovesTheChild() { @@ -961,86 +873,6 @@ public class NodeItemTest { assertThat(node.getChildren()).containsExactly(child); } - @Test - @SuppressWarnings("unchecked") - public void removeParentCopiesRootNameSupplier() { - //given - node = new NodeItem<>("root data", n -> "root supplier"); - val child = Nodes.unnamedChild("child data", node); - assertThat(child.getName()).isEqualTo("root supplier"); - //when - child.removeParent(); - //then - assertThat(child.getName()).isEqualTo("root supplier"); - } - - @Test - @SuppressWarnings("unchecked") - public void removeParentDoesNotReplaceLocalNameSupplier() { - //given - node = new NodeItem<>("root data", n -> "root supplier"); - val child = new NodeItem<>("child data", n -> "local supplier", node); - assertThat(child.getName()).isEqualTo("local supplier"); - //when - child.removeParent(); - //then - assertThat(child.getName()).isEqualTo("local supplier"); - } - - @Test - public void setNameToNullRevertsToParentNameSupplier() { - //given - node = new NodeItem<>(null, n -> "root supplier"); - val child = Nodes.namedChild("child data", "child name", node); - assertThat(child.getName()).isEqualTo("child name"); - //when - child.setName(null); - //then - assertThat(child.getName()).isEqualTo("root supplier"); - } - - @Test - public void getNameWithNameSupplierIsRecalculatedEachCall() { - val counter = new AtomicInteger(0); - node = new NodeItem<>(null, - n -> Integer.toString(counter.incrementAndGet())); - //then - assertThat(node.getName()).isNotEqualTo(node.getName()); - } - - @Test - public void isNamedWithNameSupplierIsRecalculatedEachCall() { - val counter = new AtomicInteger(0); - node = new NodeItem<>(null, n -> { - // alternate between even numbers and nulls: null, 2, null, 4, null - final int i = counter.incrementAndGet(); - if (i % 2 == 0) { - return Integer.toString(i); - } - return null; - }); - //then - assertThat(node.isNamed()).isFalse(); - assertThat(node.isNamed()).isTrue(); - } - - @Test - public void canUseNameSupplierToBuildFullPath() { - //given - final Function, String> pathNameSupplier = node -> { - Optional> parent = node.getParent(); - if (parent.isPresent()) { - return parent.get().getName() + "/" + node.getData().get(); - } - return ""; - }; - node = new NodeItem<>(null, pathNameSupplier); - val child = Nodes.unnamedChild("child", node); - val grandchild = Nodes.unnamedChild("grandchild", child); - //then - assertThat(grandchild.getName()).isEqualTo("/child/grandchild"); - } - @Test public void canSafelyHandleFindChildWhenAChildHasNoData() { //given