Merge pull request #14 from kemitix/static-factory-constructors
Static factory constructors
This commit is contained in:
commit
427f0ac3b1
5 changed files with 247 additions and 304 deletions
7
pom.xml
7
pom.xml
|
@ -17,6 +17,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<assertj.version>3.4.1</assertj.version>
|
<assertj.version>3.4.1</assertj.version>
|
||||||
<coveralls-maven-plugin.version>4.2.0</coveralls-maven-plugin.version>
|
<coveralls-maven-plugin.version>4.2.0</coveralls-maven-plugin.version>
|
||||||
|
<trajano-commons-testing.version>2.1.0</trajano-commons-testing.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<issueManagement>
|
<issueManagement>
|
||||||
|
@ -69,5 +70,11 @@
|
||||||
<version>${assertj.version}</version>
|
<version>${assertj.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.trajano.commons</groupId>
|
||||||
|
<artifactId>commons-testing</artifactId>
|
||||||
|
<version>${trajano-commons-testing.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class NodeItem<T> implements Node<T> {
|
||||||
* @param data the data or null
|
* @param data the data or null
|
||||||
* @param name the name
|
* @param name the name
|
||||||
*/
|
*/
|
||||||
public NodeItem(final T data, final String name) {
|
NodeItem(final T data, final String name) {
|
||||||
this(data);
|
this(data);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
@ -42,30 +42,18 @@ public class NodeItem<T> implements Node<T> {
|
||||||
*
|
*
|
||||||
* @param data the data or null
|
* @param data the data or null
|
||||||
*/
|
*/
|
||||||
public NodeItem(final T data) {
|
NodeItem(final T data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.nameSupplier = (n) -> null;
|
this.nameSupplier = (n) -> null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates root node with a name supplier.
|
|
||||||
*
|
|
||||||
* @param data the data or null
|
|
||||||
* @param nameSupplier the name supplier function
|
|
||||||
*/
|
|
||||||
public NodeItem(
|
|
||||||
final T data, final Function<Node<T>, String> nameSupplier) {
|
|
||||||
this(data);
|
|
||||||
this.nameSupplier = nameSupplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a node with a parent.
|
* Creates a node with a parent.
|
||||||
*
|
*
|
||||||
* @param data the data or null
|
* @param data the data or null
|
||||||
* @param parent the parent node
|
* @param parent the parent node
|
||||||
*/
|
*/
|
||||||
public NodeItem(final T data, final Node<T> parent) {
|
NodeItem(final T data, final Node<T> parent) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
setParent(parent);
|
setParent(parent);
|
||||||
}
|
}
|
||||||
|
@ -77,26 +65,12 @@ public class NodeItem<T> implements Node<T> {
|
||||||
* @param name the name
|
* @param name the name
|
||||||
* @param parent the parent node
|
* @param parent the parent node
|
||||||
*/
|
*/
|
||||||
public NodeItem(final T data, final String name, final Node<T> parent) {
|
NodeItem(final T data, final String name, final Node<T> parent) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
setParent(parent);
|
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
|
|
||||||
*/
|
|
||||||
public NodeItem(
|
|
||||||
final T data, final Function<Node<T>, String> nameSupplier,
|
|
||||||
final Node<T> parent) {
|
|
||||||
this(data, nameSupplier);
|
|
||||||
setParent(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String generateName() {
|
private String generateName() {
|
||||||
return getNameSupplier().apply(this);
|
return getNameSupplier().apply(this);
|
||||||
}
|
}
|
||||||
|
@ -229,6 +203,7 @@ public class NodeItem<T> implements Node<T> {
|
||||||
* @return the found or created child node
|
* @return the found or created child node
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public Node<T> findOrCreateChild(final T child) {
|
public Node<T> findOrCreateChild(final T child) {
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
throw new NullPointerException("child");
|
throw new NullPointerException("child");
|
||||||
|
@ -248,10 +223,10 @@ public class NodeItem<T> implements Node<T> {
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
throw new NullPointerException("child");
|
throw new NullPointerException("child");
|
||||||
}
|
}
|
||||||
return children.stream()
|
return children.stream().filter(node -> {
|
||||||
.filter(n -> !n.isEmpty())
|
final Optional<T> d = node.getData();
|
||||||
.filter(n -> n.getData().get().equals(child))
|
return d.isPresent() && d.get().equals(child);
|
||||||
.findAny();
|
}).findAny();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
66
src/main/java/net/kemitix/node/Nodes.java
Normal file
66
src/main/java/net/kemitix/node/Nodes.java
Normal file
|
@ -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 <T> the type of the data
|
||||||
|
*
|
||||||
|
* @return the new node
|
||||||
|
*/
|
||||||
|
public static <T> Node<T> 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 <T> the type of the data
|
||||||
|
*
|
||||||
|
* @return the new node
|
||||||
|
*/
|
||||||
|
public static <T> Node<T> 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 <T> the type of the data
|
||||||
|
*
|
||||||
|
* @return the new node
|
||||||
|
*/
|
||||||
|
public static <T> Node<T> unnamedChild(final T data, final Node<T> 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 <T> the type of the data
|
||||||
|
*
|
||||||
|
* @return the new node
|
||||||
|
*/
|
||||||
|
public static <T> Node<T> namedChild(
|
||||||
|
final T data, final String name, final Node<T> parent) {
|
||||||
|
return new NodeItem<>(data, name, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,13 +8,9 @@ import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link NodeItem}.
|
* Test for {@link NodeItem}.
|
||||||
|
@ -33,7 +29,7 @@ public class NodeItemTest {
|
||||||
//given
|
//given
|
||||||
val data = "this node data";
|
val data = "this node data";
|
||||||
//when
|
//when
|
||||||
node = new NodeItem<>(data);
|
node = Nodes.unnamedRoot(data);
|
||||||
//then
|
//then
|
||||||
assertThat(node.getData()).as("can get the data from a node").
|
assertThat(node.getData()).as("can get the data from a node").
|
||||||
contains(data);
|
contains(data);
|
||||||
|
@ -42,7 +38,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void canCreateAnEmptyAndUnnamedNode() {
|
public void canCreateAnEmptyAndUnnamedNode() {
|
||||||
//when
|
//when
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//then
|
//then
|
||||||
SoftAssertions softly = new SoftAssertions();
|
SoftAssertions softly = new SoftAssertions();
|
||||||
softly.assertThat(node.isEmpty()).as("node is empty").isTrue();
|
softly.assertThat(node.isEmpty()).as("node is empty").isTrue();
|
||||||
|
@ -50,21 +46,10 @@ public class NodeItemTest {
|
||||||
softly.assertAll();
|
softly.assertAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void canCreateNodeWithParentAndCustomNameSupplier() {
|
|
||||||
//given
|
|
||||||
node = new NodeItem<>(null, n -> "root name supplier");
|
|
||||||
//when
|
|
||||||
val child = new NodeItem<String>(null, n -> "overridden", node);
|
|
||||||
//then
|
|
||||||
assertThat(child.getName()).isEqualTo("overridden");
|
|
||||||
assertThat(child.getParent()).contains(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canSetName() {
|
public void canSetName() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
node.setName("named");
|
node.setName("named");
|
||||||
//then
|
//then
|
||||||
|
@ -77,7 +62,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldHaveNullForDefaultParent() {
|
public void shouldHaveNullForDefaultParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("data");
|
node = Nodes.unnamedRoot("data");
|
||||||
//then
|
//then
|
||||||
assertThat(node.getParent()).as(
|
assertThat(node.getParent()).as(
|
||||||
"node created without a parent has no parent").isEmpty();
|
"node created without a parent has no parent").isEmpty();
|
||||||
|
@ -89,9 +74,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnNodeParent() {
|
public void shouldReturnNodeParent() {
|
||||||
//given
|
//given
|
||||||
val parent = new NodeItem<String>("parent");
|
val parent = Nodes.unnamedRoot("parent");
|
||||||
//when
|
//when
|
||||||
node = new NodeItem<>("subject", parent);
|
node = Nodes.unnamedChild("subject", parent);
|
||||||
//then
|
//then
|
||||||
assertThat(node.getParent()).as(
|
assertThat(node.getParent()).as(
|
||||||
"node created with a parent can return the parent")
|
"node created with a parent can return the parent")
|
||||||
|
@ -105,8 +90,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void setParentShouldThrowNodeExceptionWhenParentIsAChild() {
|
public void setParentShouldThrowNodeExceptionWhenParentIsAChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val child = new NodeItem<String>("child", node);
|
val child = Nodes.unnamedChild("child", node);
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Parent is a descendant");
|
exception.expectMessage("Parent is a descendant");
|
||||||
//when
|
//when
|
||||||
|
@ -121,9 +106,9 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void shouldAddNewNodeAsChildToParent() {
|
public void shouldAddNewNodeAsChildToParent() {
|
||||||
//given
|
//given
|
||||||
val parent = new NodeItem<String>("parent");
|
val parent = Nodes.unnamedRoot("parent");
|
||||||
//when
|
//when
|
||||||
node = new NodeItem<>("subject", parent);
|
node = Nodes.unnamedChild("subject", parent);
|
||||||
//then
|
//then
|
||||||
assertThat(parent.getChildren()).as(
|
assertThat(parent.getChildren()).as(
|
||||||
"when a node is created with a parent, the parent has the new"
|
"when a node is created with a parent, the parent has the new"
|
||||||
|
@ -136,8 +121,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnSetParent() {
|
public void shouldReturnSetParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val parent = new NodeItem<String>("parent");
|
val parent = Nodes.unnamedRoot("parent");
|
||||||
//when
|
//when
|
||||||
node.setParent(parent);
|
node.setParent(parent);
|
||||||
//then
|
//then
|
||||||
|
@ -152,7 +137,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldThrowNPEWhenSetParentNull() {
|
public void shouldThrowNPEWhenSetParentNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("parent");
|
exception.expectMessage("parent");
|
||||||
//when
|
//when
|
||||||
|
@ -166,7 +151,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void setParentShouldThrowNodeExceptionWhenParentIsSelf() {
|
public void setParentShouldThrowNodeExceptionWhenParentIsSelf() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Parent is a descendant");
|
exception.expectMessage("Parent is a descendant");
|
||||||
//when
|
//when
|
||||||
|
@ -180,9 +165,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldUpdateOldParentWhenNodeSetToNewParent() {
|
public void shouldUpdateOldParentWhenNodeSetToNewParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val child = node.createChild("child");
|
val child = node.createChild("child");
|
||||||
val newParent = new NodeItem<String>("newParent");
|
val newParent = Nodes.unnamedRoot("newParent");
|
||||||
//when
|
//when
|
||||||
child.setParent(newParent);
|
child.setParent(newParent);
|
||||||
//then
|
//then
|
||||||
|
@ -201,9 +186,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() {
|
public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val child = node.createChild("child");
|
val child = node.createChild("child");
|
||||||
val newParent = new NodeItem<String>("newParent");
|
val newParent = Nodes.unnamedRoot("newParent");
|
||||||
//when
|
//when
|
||||||
newParent.addChild(child);
|
newParent.addChild(child);
|
||||||
//then
|
//then
|
||||||
|
@ -223,7 +208,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldThrowNPEWhenAddingNullAsChild() {
|
public void shouldThrowNPEWhenAddingNullAsChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("child");
|
exception.expectMessage("child");
|
||||||
//when
|
//when
|
||||||
|
@ -237,8 +222,8 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void shouldReturnAddedChild() {
|
public void shouldReturnAddedChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val child = new NodeItem<String>("child");
|
val child = Nodes.unnamedRoot("child");
|
||||||
//when
|
//when
|
||||||
node.addChild(child);
|
node.addChild(child);
|
||||||
//then
|
//then
|
||||||
|
@ -253,7 +238,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void addChildShouldThrowNodeExceptionWhenAddingANodeAsOwnChild() {
|
public void addChildShouldThrowNodeExceptionWhenAddingANodeAsOwnChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Child is an ancestor");
|
exception.expectMessage("Child is an ancestor");
|
||||||
//then
|
//then
|
||||||
|
@ -266,7 +251,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void addChildShouldThrowNodeExceptionWhenAddingSelfAsChild() {
|
public void addChildShouldThrowNodeExceptionWhenAddingSelfAsChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Child is an ancestor");
|
exception.expectMessage("Child is an ancestor");
|
||||||
//when
|
//when
|
||||||
|
@ -280,8 +265,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void addChildShouldThrowNodeExceptionWhenChildIsParent() {
|
public void addChildShouldThrowNodeExceptionWhenChildIsParent() {
|
||||||
//given
|
//given
|
||||||
val parent = new NodeItem<String>("parent");
|
val parent = Nodes.unnamedRoot("parent");
|
||||||
node = new NodeItem<>("subject", parent);
|
node = Nodes.unnamedChild("subject", parent);
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Child is an ancestor");
|
exception.expectMessage("Child is an ancestor");
|
||||||
//when
|
//when
|
||||||
|
@ -295,9 +280,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void addChildShouldThrowNodeExceptionWhenAddingGrandParentAsChild() {
|
public void addChildShouldThrowNodeExceptionWhenAddingGrandParentAsChild() {
|
||||||
//given
|
//given
|
||||||
val grandParent = new NodeItem<String>("grandparent");
|
val grandParent = Nodes.unnamedRoot("grandparent");
|
||||||
val parent = new NodeItem<String>("parent", grandParent);
|
val parent = Nodes.unnamedChild("parent", grandParent);
|
||||||
node = new NodeItem<>("subject", parent);
|
node = Nodes.unnamedChild("subject", parent);
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Child is an ancestor");
|
exception.expectMessage("Child is an ancestor");
|
||||||
//when
|
//when
|
||||||
|
@ -310,8 +295,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldSetParentOnChildWhenAddedAsChild() {
|
public void shouldSetParentOnChildWhenAddedAsChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val child = new NodeItem<String>("child");
|
val child = Nodes.unnamedRoot("child");
|
||||||
//when
|
//when
|
||||||
node.addChild(child);
|
node.addChild(child);
|
||||||
//then
|
//then
|
||||||
|
@ -327,11 +312,11 @@ public class NodeItemTest {
|
||||||
public void shouldWalkTreeToNode() {
|
public void shouldWalkTreeToNode() {
|
||||||
//given
|
//given
|
||||||
val grandparent = "grandparent";
|
val grandparent = "grandparent";
|
||||||
val grandParentNode = new NodeItem<String>(grandparent);
|
val grandParentNode = Nodes.unnamedRoot(grandparent);
|
||||||
val parent = "parent";
|
val parent = "parent";
|
||||||
val parentNode = new NodeItem<String>(parent, grandParentNode);
|
val parentNode = Nodes.unnamedChild(parent, grandParentNode);
|
||||||
val subject = "subject";
|
val subject = "subject";
|
||||||
node = new NodeItem<>(subject, parentNode);
|
node = Nodes.unnamedChild(subject, parentNode);
|
||||||
//when
|
//when
|
||||||
val result = grandParentNode.findInPath(Arrays.asList(parent, subject));
|
val result = grandParentNode.findInPath(Arrays.asList(parent, subject));
|
||||||
//then
|
//then
|
||||||
|
@ -352,9 +337,9 @@ public class NodeItemTest {
|
||||||
public void shouldNotFindNonExistentChildNode() {
|
public void shouldNotFindNonExistentChildNode() {
|
||||||
//given
|
//given
|
||||||
val parent = "parent";
|
val parent = "parent";
|
||||||
val parentNode = new NodeItem<String>(parent);
|
val parentNode = Nodes.unnamedRoot(parent);
|
||||||
val subject = "subject";
|
val subject = "subject";
|
||||||
node = new NodeItem<>(subject, parentNode);
|
node = Nodes.unnamedChild(subject, parentNode);
|
||||||
//when
|
//when
|
||||||
val result = parentNode.findInPath(Arrays.asList(subject, "no child"));
|
val result = parentNode.findInPath(Arrays.asList(subject, "no child"));
|
||||||
//then
|
//then
|
||||||
|
@ -369,7 +354,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldThrowNEWhenWalkTreeNull() {
|
public void shouldThrowNEWhenWalkTreeNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("path");
|
exception.expectMessage("path");
|
||||||
//when
|
//when
|
||||||
|
@ -383,7 +368,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnEmptyForEmptyWalkTreePath() {
|
public void shouldReturnEmptyForEmptyWalkTreePath() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
//when
|
//when
|
||||||
val result = node.findInPath(Collections.emptyList());
|
val result = node.findInPath(Collections.emptyList());
|
||||||
//then
|
//then
|
||||||
|
@ -396,7 +381,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateDescendantNodes() {
|
public void shouldCreateDescendantNodes() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val alphaData = "alpha";
|
val alphaData = "alpha";
|
||||||
val betaData = "beta";
|
val betaData = "beta";
|
||||||
val gammaData = "gamma";
|
val gammaData = "gamma";
|
||||||
|
@ -445,7 +430,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void createDescendantLineShouldThrowNPEWhenDescendantsAreNull() {
|
public void createDescendantLineShouldThrowNPEWhenDescendantsAreNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("descendants");
|
exception.expectMessage("descendants");
|
||||||
//when
|
//when
|
||||||
|
@ -458,7 +443,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldChangeNothingWhenCreateDescendantEmpty() {
|
public void shouldChangeNothingWhenCreateDescendantEmpty() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
//when
|
//when
|
||||||
node.createDescendantLine(Collections.emptyList());
|
node.createDescendantLine(Collections.emptyList());
|
||||||
//then
|
//then
|
||||||
|
@ -473,9 +458,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindExistingChildNode() {
|
public void shouldFindExistingChildNode() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val childData = "child";
|
val childData = "child";
|
||||||
val child = new NodeItem<String>(childData, node);
|
val child = Nodes.unnamedChild(childData, node);
|
||||||
//when
|
//when
|
||||||
val found = node.findOrCreateChild(childData);
|
val found = node.findOrCreateChild(childData);
|
||||||
//then
|
//then
|
||||||
|
@ -490,7 +475,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldFindCreateNewChildNode() {
|
public void shouldFindCreateNewChildNode() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val childData = "child";
|
val childData = "child";
|
||||||
//when
|
//when
|
||||||
val found = node.findOrCreateChild(childData);
|
val found = node.findOrCreateChild(childData);
|
||||||
|
@ -506,7 +491,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void findOrCreateChildShouldThrowNPEFWhenChildIsNull() {
|
public void findOrCreateChildShouldThrowNPEFWhenChildIsNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("child");
|
exception.expectMessage("child");
|
||||||
//when
|
//when
|
||||||
|
@ -519,9 +504,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldGetChild() {
|
public void shouldGetChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val childData = "child";
|
val childData = "child";
|
||||||
val child = new NodeItem<String>(childData);
|
val child = Nodes.unnamedRoot(childData);
|
||||||
node.addChild(child);
|
node.addChild(child);
|
||||||
//when
|
//when
|
||||||
val found = node.findChild(childData);
|
val found = node.findChild(childData);
|
||||||
|
@ -541,7 +526,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void getChildShouldThrowNPEWhenThereIsNoChild() {
|
public void getChildShouldThrowNPEWhenThereIsNoChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("data");
|
node = Nodes.unnamedRoot("data");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("child");
|
exception.expectMessage("child");
|
||||||
//when
|
//when
|
||||||
|
@ -555,7 +540,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void shouldCreateChild() {
|
public void shouldCreateChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
val childData = "child";
|
val childData = "child";
|
||||||
//when
|
//when
|
||||||
val child = node.createChild(childData);
|
val child = node.createChild(childData);
|
||||||
|
@ -580,82 +565,25 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void createChildShouldThrowNPEWhenChildIsNull() {
|
public void createChildShouldThrowNPEWhenChildIsNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("subject");
|
node = Nodes.unnamedRoot("subject");
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("child");
|
exception.expectMessage("child");
|
||||||
//when
|
//when
|
||||||
node.createChild(null);
|
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<String>("root", n -> n.getData().get());
|
|
||||||
node = new NodeItem<>("child", root);
|
|
||||||
//then
|
|
||||||
assertThat(node.getName()).isEqualTo("child");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getNameShouldReturnNameForNonStringData() {
|
|
||||||
val root = new NodeItem<LocalDate>(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<String>("child", Object::toString);
|
|
||||||
node.addChild(child);
|
|
||||||
val grandChild = new NodeItem<>("grandchild", child);
|
|
||||||
//then
|
|
||||||
assertThat(node.getName()).isEqualTo("root");
|
|
||||||
assertThat(child.getName()).isNotEqualTo("child");
|
|
||||||
assertThat(grandChild.getName()).isNotEqualTo("grandchild");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getNameShouldWorkWithoutNameSupplier() {
|
|
||||||
node = new NodeItem<>(null, "root");
|
|
||||||
val namedchild = new NodeItem<>("named", "Alice", node);
|
|
||||||
//then
|
|
||||||
assertThat(node.getName()).isEqualTo("root");
|
|
||||||
assertThat(namedchild.getName()).isEqualTo("Alice");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canCreateRootNodeWithoutData() {
|
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);
|
|
||||||
assertThat(node.getData()).isEmpty();
|
assertThat(node.getData()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getChildNamedFindsChild() {
|
public void getChildNamedFindsChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot("root data", "root");
|
||||||
val alpha = new NodeItem<String>(null, "alpha");
|
val alpha = Nodes.namedRoot("alpha data", "alpha");
|
||||||
val beta = new NodeItem<String>(null, "beta");
|
val beta = Nodes.namedRoot("beta data", "beta");
|
||||||
node.addChild(alpha);
|
node.addChild(alpha);
|
||||||
node.addChild(beta);
|
node.addChild(beta);
|
||||||
//when
|
//when
|
||||||
|
@ -667,9 +595,9 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void getChildNamedFindsNothing() {
|
public void getChildNamedFindsNothing() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot("root data", "root");
|
||||||
val alpha = new NodeItem<String>(null, "alpha");
|
val alpha = Nodes.namedRoot("alpha data", "alpha");
|
||||||
val beta = new NodeItem<String>(null, "beta");
|
val beta = Nodes.namedRoot("beta data", "beta");
|
||||||
node.addChild(alpha);
|
node.addChild(alpha);
|
||||||
node.addChild(beta);
|
node.addChild(beta);
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
|
@ -681,10 +609,10 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void nodeNamesAreUniqueWithinAParent() {
|
public void nodeNamesAreUniqueWithinAParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot("root data", "root");
|
||||||
val alpha = new NodeItem<String>(null, "alpha");
|
val alpha = Nodes.namedRoot("alpha data", "alpha");
|
||||||
node.addChild(alpha);
|
node.addChild(alpha);
|
||||||
val beta = new NodeItem<String>(null, "alpha");
|
val beta = Nodes.namedRoot("beta data", "alpha");
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Node with that name already exists here");
|
exception.expectMessage("Node with that name already exists here");
|
||||||
//when
|
//when
|
||||||
|
@ -694,8 +622,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void canPlaceNodeInTreeByPathNames() {
|
public void canPlaceNodeInTreeByPathNames() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root"); // create a root
|
node = Nodes.namedRoot("root data", "root"); // create a root
|
||||||
val four = new NodeItem<String>("data", "four");
|
val four = Nodes.namedRoot("data", "four");
|
||||||
//when
|
//when
|
||||||
node.insertInPath(four, "one", "two", "three");
|
node.insertInPath(four, "one", "two", "three");
|
||||||
//then
|
//then
|
||||||
|
@ -717,9 +645,9 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void canPlaceInTreeUnderExistingNode() {
|
public void canPlaceInTreeUnderExistingNode() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot(null, "root");
|
||||||
val child = new NodeItem<String>("child data", "child");
|
val child = Nodes.namedRoot("child data", "child");
|
||||||
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
|
val grandchild = Nodes.namedRoot("grandchild data", "grandchild");
|
||||||
//when
|
//when
|
||||||
node.insertInPath(child); // as root/child
|
node.insertInPath(child); // as root/child
|
||||||
node.insertInPath(grandchild, "child"); // as root/child/grandchild
|
node.insertInPath(grandchild, "child"); // as root/child/grandchild
|
||||||
|
@ -734,9 +662,9 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void canPlaceInTreeAboveExistingNode() {
|
public void canPlaceInTreeAboveExistingNode() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot(null, "root");
|
||||||
val child = new NodeItem<String>("child data", "child");
|
val child = Nodes.namedRoot("child data", "child");
|
||||||
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
|
val grandchild = Nodes.namedRoot("grandchild data", "grandchild");
|
||||||
//when
|
//when
|
||||||
node.insertInPath(grandchild, "child");
|
node.insertInPath(grandchild, "child");
|
||||||
node.insertInPath(child);
|
node.insertInPath(child);
|
||||||
|
@ -752,7 +680,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void removingParentFromNodeWithNoParentIsNoop() {
|
public void removingParentFromNodeWithNoParentIsNoop() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
node.removeParent();
|
node.removeParent();
|
||||||
}
|
}
|
||||||
|
@ -760,8 +688,8 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void removingParentFromNodeWithParentRemovesParent() {
|
public void removingParentFromNodeWithParentRemovesParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
val child = new NodeItem<String>(null, node);
|
val child = Nodes.unnamedChild("child data", node);
|
||||||
//when
|
//when
|
||||||
child.removeParent();
|
child.removeParent();
|
||||||
//then
|
//then
|
||||||
|
@ -775,22 +703,22 @@ public class NodeItemTest {
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage(
|
exception.expectMessage(
|
||||||
"A non-empty node named 'grandchild' already exists here");
|
"A non-empty node named 'grandchild' already exists here");
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
val child = new NodeItem<String>(null, "child", node);
|
val child = Nodes.namedChild("child data", "child", node);
|
||||||
new NodeItem<>("data", "grandchild", child);
|
Nodes.namedChild("data", "grandchild", child);
|
||||||
// root -> child -> grandchild
|
// root -> child -> grandchild
|
||||||
// only grandchild has data
|
// only grandchild has data
|
||||||
//when
|
//when
|
||||||
// attempt to add another node called 'grandchild' to 'child'
|
// attempt to add another node called 'grandchild' to 'child'
|
||||||
node.insertInPath(new NodeItem<>("cuckoo", "grandchild"), "child");
|
node.insertInPath(Nodes.namedRoot("cuckoo", "grandchild"), "child");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void placeNodeInTreeWhenAddedNodeIsUnnamed() {
|
public void placeNodeInTreeWhenAddedNodeIsUnnamed() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
final Node<String> newNode = new NodeItem<>(null);
|
final Node<String> newNode = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
node.insertInPath(newNode);
|
node.insertInPath(newNode);
|
||||||
//then
|
//then
|
||||||
|
@ -801,12 +729,12 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void placeNodeInTreeWhenEmptyChildWithTargetNameExists() {
|
public void placeNodeInTreeWhenEmptyChildWithTargetNameExists() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
final NodeItem<String> child = new NodeItem<>(null, "child");
|
final Node<String> child = Nodes.namedRoot(null, "child");
|
||||||
final NodeItem<String> target = new NodeItem<>(null, "target");
|
final Node<String> target = Nodes.namedRoot(null, "target");
|
||||||
node.addChild(child);
|
node.addChild(child);
|
||||||
child.addChild(target);
|
child.addChild(target);
|
||||||
final NodeItem<String> addMe = new NodeItem<>("I'm new", "target");
|
val addMe = Nodes.namedRoot("I'm new", "target");
|
||||||
assertThat(addMe.getParent()).isEmpty();
|
assertThat(addMe.getParent()).isEmpty();
|
||||||
assertThat(child.getChildByName("target").isEmpty()).as(
|
assertThat(child.getChildByName("target").isEmpty()).as(
|
||||||
"target starts empty").isTrue();
|
"target starts empty").isTrue();
|
||||||
|
@ -823,7 +751,7 @@ public class NodeItemTest {
|
||||||
//given
|
//given
|
||||||
exception.expect(NullPointerException.class);
|
exception.expect(NullPointerException.class);
|
||||||
exception.expectMessage("name");
|
exception.expectMessage("name");
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
node.findChildByName(null);
|
node.findChildByName(null);
|
||||||
}
|
}
|
||||||
|
@ -831,7 +759,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void isNamedNull() {
|
public void isNamedNull() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//then
|
//then
|
||||||
assertThat(node.isNamed()).isFalse();
|
assertThat(node.isNamed()).isFalse();
|
||||||
}
|
}
|
||||||
|
@ -839,7 +767,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void isNamedEmpty() {
|
public void isNamedEmpty() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "");
|
node = Nodes.namedRoot(null, "");
|
||||||
//then
|
//then
|
||||||
assertThat(node.isNamed()).isFalse();
|
assertThat(node.isNamed()).isFalse();
|
||||||
}
|
}
|
||||||
|
@ -847,32 +775,16 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void isNamedNamed() {
|
public void isNamedNamed() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "named");
|
node = Nodes.namedRoot(null, "named");
|
||||||
//then
|
//then
|
||||||
assertThat(node.isNamed()).isTrue();
|
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());
|
|
||||||
final NodeItem<String> child = new NodeItem<>("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
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void removeChildRemovesTheChild() {
|
public void removeChildRemovesTheChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
Node<String> child = node.createChild("child");
|
Node<String> child = node.createChild("child");
|
||||||
assertThat(node.getChildren()).containsExactly(child);
|
assertThat(node.getChildren()).containsExactly(child);
|
||||||
//then
|
//then
|
||||||
|
@ -885,13 +797,14 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void drawTreeIsCorrect() {
|
public void drawTreeIsCorrect() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null, "root");
|
node = Nodes.namedRoot(null, "root");
|
||||||
val bob = new NodeItem<String>(null, "bob", node);
|
val bob = Nodes.namedChild("bob data", "bob", node);
|
||||||
val alice = new NodeItem<String>(null, "alice", node);
|
val alice = Nodes.namedChild("alice data", "alice", node);
|
||||||
new NodeItem<>(null, "dave", alice);
|
Nodes.namedChild("dave data", "dave", alice);
|
||||||
new NodeItem<>(null, bob); // has no name and no children so no included
|
Nodes.unnamedChild("bob's child's data",
|
||||||
val kim = new NodeItem<String>(null, node); // nameless mother
|
bob); // has no name and no children so no included
|
||||||
new NodeItem<>(null, "lucy", kim);
|
val kim = Nodes.unnamedChild("kim data", node); // nameless mother
|
||||||
|
Nodes.namedChild("lucy data", "lucy", kim);
|
||||||
//when
|
//when
|
||||||
val tree = node.drawTree(0);
|
val tree = node.drawTree(0);
|
||||||
//then
|
//then
|
||||||
|
@ -907,7 +820,7 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void canChangeNodeData() {
|
public void canChangeNodeData() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("initial");
|
node = Nodes.unnamedRoot("initial");
|
||||||
//when
|
//when
|
||||||
node.setData("updated");
|
node.setData("updated");
|
||||||
//then
|
//then
|
||||||
|
@ -918,7 +831,7 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void canCreateNamedChild() {
|
public void canCreateNamedChild() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
Node<String> child = node.createChild("child data", "child name");
|
Node<String> child = node.createChild("child data", "child name");
|
||||||
//then
|
//then
|
||||||
|
@ -930,10 +843,10 @@ public class NodeItemTest {
|
||||||
@Test
|
@Test
|
||||||
public void canGetChildWhenFound() {
|
public void canGetChildWhenFound() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>("data");
|
node = Nodes.unnamedRoot("data");
|
||||||
Node<String> child = new NodeItem<>("child data", "child name", node);
|
val child = Nodes.namedChild("child data", "child name", node);
|
||||||
//when
|
//when
|
||||||
Node<String> found = node.getChild("child data");
|
val found = node.getChild("child data");
|
||||||
//then
|
//then
|
||||||
assertThat(found).isSameAs(child);
|
assertThat(found).isSameAs(child);
|
||||||
}
|
}
|
||||||
|
@ -943,7 +856,7 @@ public class NodeItemTest {
|
||||||
//given
|
//given
|
||||||
exception.expect(NodeException.class);
|
exception.expect(NodeException.class);
|
||||||
exception.expectMessage("Child not found");
|
exception.expectMessage("Child not found");
|
||||||
node = new NodeItem<>("data");
|
node = Nodes.unnamedRoot("data");
|
||||||
//when
|
//when
|
||||||
node.getChild("child data");
|
node.getChild("child data");
|
||||||
}
|
}
|
||||||
|
@ -952,99 +865,19 @@ public class NodeItemTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void constructorWithNameSupplierAndParentBeChildOfParent() {
|
public void constructorWithNameSupplierAndParentBeChildOfParent() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
//when
|
//when
|
||||||
NodeItem<String> child = new NodeItem<>(null, node);
|
val child = Nodes.unnamedChild("child data", node);
|
||||||
//then
|
//then
|
||||||
assertThat(child.getParent()).contains(node);
|
assertThat(child.getParent()).contains(node);
|
||||||
assertThat(node.getChildren()).containsExactly(child);
|
assertThat(node.getChildren()).containsExactly(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void removeParentCopiesRootNameSupplier() {
|
|
||||||
//given
|
|
||||||
node = new NodeItem<>("root data", n -> "root supplier");
|
|
||||||
val child = new NodeItem<>("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 = new NodeItem<String>(null, "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<Node<String>, String> pathNameSupplier = node -> {
|
|
||||||
Optional<Node<String>> parent = node.getParent();
|
|
||||||
if (parent.isPresent()) {
|
|
||||||
return parent.get().getName() + "/" + node.getData().get();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
};
|
|
||||||
node = new NodeItem<>(null, pathNameSupplier);
|
|
||||||
val child = new NodeItem<String>("child", node);
|
|
||||||
val grandchild = new NodeItem<String>("grandchild", child);
|
|
||||||
//then
|
|
||||||
assertThat(grandchild.getName()).isEqualTo("/child/grandchild");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void canSafelyHandleFindChildWhenAChildHasNoData() {
|
public void canSafelyHandleFindChildWhenAChildHasNoData() {
|
||||||
//given
|
//given
|
||||||
node = new NodeItem<>(null);
|
node = Nodes.unnamedRoot(null);
|
||||||
new NodeItem<>(null, node);
|
Nodes.unnamedChild(null, node);
|
||||||
//when
|
//when
|
||||||
node.findChild("data");
|
node.findChild("data");
|
||||||
}
|
}
|
||||||
|
|
62
src/test/java/net/kemitix/node/NodesTest.java
Normal file
62
src/test/java/net/kemitix/node/NodesTest.java
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue