Node.getParent(): returns any parent inside an Optional

Root nodes will return an empty Optional.
This commit is contained in:
Paul Campbell 2016-05-26 12:57:56 +01:00
parent 37562941f4
commit 6c13cd2735
3 changed files with 33 additions and 31 deletions

View file

@ -53,13 +53,10 @@ public interface Node<T> {
/** /**
* Fetch the parent node. * Fetch the parent node.
* <p>
* If the node is a root node, i.e. has no parent, then this will return
* null.
* *
* @return the parent node * @return an Optional contain the parent node, or empty if a root node
*/ */
Node<T> getParent(); Optional<Node<T>> getParent();
/** /**
* Make the current node a direct child of the parent. * Make the current node a direct child of the parent.

View file

@ -139,8 +139,8 @@ public class NodeItem<T> implements Node<T> {
} }
@Override @Override
public Node<T> getParent() { public Optional<Node<T>> getParent() {
return parent; return Optional.ofNullable(parent);
} }
@Override @Override
@ -170,7 +170,12 @@ public class NodeItem<T> implements Node<T> {
} }
} }
children.add(child); children.add(child);
if (child.getParent() == null || !child.getParent().equals(this)) { // update the child's parent if they don't have one or it is not this
Optional<Node<T>> childParent = child.getParent();
boolean isOrphan = !childParent.isPresent();
boolean hasDifferentParent = !isOrphan && !childParent.get()
.equals(this);
if (isOrphan || hasDifferentParent) {
child.setParent(this); child.setParent(this);
} }
} }

View file

@ -79,7 +79,7 @@ public class NodeItemTest {
node = new NodeItem<>("data"); node = new NodeItem<>("data");
//then //then
assertThat(node.getParent()).as( assertThat(node.getParent()).as(
"node created without a parent has null as parent").isNull(); "node created without a parent has no parent").isEmpty();
} }
/** /**
@ -94,7 +94,7 @@ public class NodeItemTest {
//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")
.isSameAs(parent); .contains(parent);
} }
/** /**
@ -142,7 +142,7 @@ public class NodeItemTest {
//then //then
assertThat(node.getParent()).as( assertThat(node.getParent()).as(
"when a node is assigned a new parent that parent can be " "when a node is assigned a new parent that parent can be "
+ "returned").isSameAs(parent); + "returned").contains(parent);
} }
/** /**
@ -187,7 +187,7 @@ public class NodeItemTest {
//then //then
assertThat(child.getParent()).as( assertThat(child.getParent()).as(
"when a node is assigned a new parent, the old parent is " "when a node is assigned a new parent, the old parent is "
+ "replaced").isSameAs(newParent); + "replaced").contains(newParent);
assertThat(node.findChild("child").isPresent()).as( assertThat(node.findChild("child").isPresent()).as(
"when a node is assigned a new parent, the old parent no " "when a node is assigned a new parent, the old parent no "
+ "longer has the node among it's children").isFalse(); + "longer has the node among it's children").isFalse();
@ -209,7 +209,7 @@ public class NodeItemTest {
assertThat(child.getParent()).as( assertThat(child.getParent()).as(
"when a node with an existing parent is added as a child " "when a node with an existing parent is added as a child "
+ "to another node, then the old parent is replaced") + "to another node, then the old parent is replaced")
.isSameAs(newParent); .contains(newParent);
assertThat(node.findChild("child").isPresent()).as( assertThat(node.findChild("child").isPresent()).as(
"when a node with an existing parent is added as a child to " "when a node with an existing parent is added as a child to "
+ "another node, then the old parent no longer has " + "another node, then the old parent no longer has "
@ -309,14 +309,14 @@ public class NodeItemTest {
@Test @Test
public void shouldSetParentOnChildWhenAddedAsChild() { public void shouldSetParentOnChildWhenAddedAsChild() {
//given //given
val child = new NodeItem<String>("child");
node = new NodeItem<>("subject"); node = new NodeItem<>("subject");
val child = new NodeItem<String>("child");
//when //when
node.addChild(child); node.addChild(child);
//then //then
assertThat(child.getParent()).as( assertThat(child.getParent()).as(
"when a node is added as a child, the child has the node as " "when a node is added as a child, the child has the node as "
+ "its parent").isSameAs(node); + "its parent").contains(node);
} }
/** /**
@ -411,7 +411,7 @@ public class NodeItemTest {
val alpha = alphaOptional.get(); val alpha = alphaOptional.get();
assertThat(alpha.getParent()).as( assertThat(alpha.getParent()).as(
"when creating a descendant line, the first element has " "when creating a descendant line, the first element has "
+ "the current node as its parent").isSameAs(node); + "the current node as its parent").contains(node);
val betaOptional = alpha.findChild(betaData); val betaOptional = alpha.findChild(betaData);
assertThat(betaOptional.isPresent()).as( assertThat(betaOptional.isPresent()).as(
"when creating a descendant line, the second element is " "when creating a descendant line, the second element is "
@ -421,7 +421,7 @@ public class NodeItemTest {
assertThat(beta.getParent()).as( assertThat(beta.getParent()).as(
"when creating a descendant line, the second element " "when creating a descendant line, the second element "
+ "has the first as its parent") + "has the first as its parent")
.isSameAs(alpha); .contains(alpha);
val gammaOptional = beta.findChild(gammaData); val gammaOptional = beta.findChild(gammaData);
assertThat(gammaOptional.isPresent()).as( assertThat(gammaOptional.isPresent()).as(
"when creating a descendant line, the third element " "when creating a descendant line, the third element "
@ -431,7 +431,7 @@ public class NodeItemTest {
assertThat(gamma.getParent()).as( assertThat(gamma.getParent()).as(
"when creating a descendant line, the third " "when creating a descendant line, the third "
+ "element has the second as its parent") + "element has the second as its parent")
.isSameAs(beta); .contains(beta);
} }
} }
} }
@ -561,7 +561,7 @@ public class NodeItemTest {
//then //then
assertThat(child.getParent()).as( assertThat(child.getParent()).as(
"when creating a child node, the child has the current node " "when creating a child node, the child has the current node "
+ "as its parent").isSameAs(node); + "as its parent").contains(node);
val foundChild = node.findChild(childData); val foundChild = node.findChild(childData);
assertThat(foundChild.isPresent()).as( assertThat(foundChild.isPresent()).as(
"when creating a child node, the child can be found by its " "when creating a child node, the child can be found by its "
@ -698,14 +698,14 @@ public class NodeItemTest {
//when //when
node.insertInPath(four, "one", "two", "three"); node.insertInPath(four, "one", "two", "three");
//then //then
val three = four.getParent(); val three = four.getParent().get();
assertThat(four.getParent()).as("add node to a tree").isNotNull(); assertThat(four.getParent()).as("add node to a tree").isNotNull();
assertThat(three.getName()).isEqualTo("three"); assertThat(three.getName()).isEqualTo("three");
val two = three.getParent(); val two = three.getParent().get();
assertThat(two.getName()).isEqualTo("two"); assertThat(two.getName()).isEqualTo("two");
val one = two.getParent(); val one = two.getParent().get();
assertThat(one.getName()).isEqualTo("one"); assertThat(one.getName()).isEqualTo("one");
assertThat(one.getParent()).isSameAs(node); assertThat(one.getParent().get()).isSameAs(node);
assertThat(node.getChildByName("one") assertThat(node.getChildByName("one")
.getChildByName("two") .getChildByName("two")
.getChildByName("three") .getChildByName("three")
@ -764,7 +764,7 @@ public class NodeItemTest {
//when //when
child.removeParent(); child.removeParent();
//then //then
assertThat(child.getParent()).isNull(); assertThat(child.getParent()).isEmpty();
} }
@Test @Test
@ -805,7 +805,7 @@ public class NodeItemTest {
node.addChild(child); node.addChild(child);
child.addChild(target); child.addChild(target);
final NodeItem<String> addMe = new NodeItem<>("I'm new", "target"); final NodeItem<String> addMe = new NodeItem<>("I'm new", "target");
assertThat(addMe.getParent()).isNull(); assertThat(addMe.getParent()).isEmpty();
assertThat(child.getChildByName("target").isEmpty()).as( assertThat(child.getChildByName("target").isEmpty()).as(
"target starts empty").isTrue(); "target starts empty").isTrue();
//when //when
@ -920,7 +920,7 @@ public class NodeItemTest {
Node<String> child = node.createChild("child data", "child name"); Node<String> child = node.createChild("child data", "child name");
//then //then
assertThat(child.getName()).isEqualTo("child name"); assertThat(child.getName()).isEqualTo("child name");
assertThat(child.getParent()).isSameAs(node); assertThat(child.getParent()).contains(node);
assertThat(node.getChildren()).containsExactly(child); assertThat(node.getChildren()).containsExactly(child);
} }
@ -953,7 +953,7 @@ public class NodeItemTest {
//when //when
NodeItem<String> child = new NodeItem<>(null, node); NodeItem<String> child = new NodeItem<>(null, node);
//then //then
assertThat(child.getParent()).isSameAs(node); assertThat(child.getParent()).contains(node);
assertThat(node.getChildren()).containsExactly(child); assertThat(node.getChildren()).containsExactly(child);
} }
@ -1024,11 +1024,11 @@ public class NodeItemTest {
public void canUseNameSupplierToBuildFullPath() { public void canUseNameSupplierToBuildFullPath() {
//given //given
final Function<Node<String>, String> pathNameSupplier = node -> { final Function<Node<String>, String> pathNameSupplier = node -> {
Node<String> parent = node.getParent(); Optional<Node<String>> parent = node.getParent();
if (parent == null) { if (parent.isPresent()) {
return ""; return parent.get().getName() + "/" + node.getData().get();
} }
return parent.getName() + "/" + node.getData().get(); return "";
}; };
node = new NodeItem<>(null, pathNameSupplier); node = new NodeItem<>(null, pathNameSupplier);
val child = new NodeItem<String>("child", node); val child = new NodeItem<String>("child", node);