commit
c0bbadf119
3 changed files with 156 additions and 61 deletions
|
@ -34,6 +34,13 @@ public interface Node<T> {
|
|||
*/
|
||||
T getData();
|
||||
|
||||
/**
|
||||
* Set the data held within the node.
|
||||
*
|
||||
* @param data the node's data
|
||||
*/
|
||||
void setData(T data);
|
||||
|
||||
/**
|
||||
* Returns true if the node is empty (has no data).
|
||||
*
|
||||
|
@ -56,7 +63,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @param parent the new parent node
|
||||
*/
|
||||
void setParent(final Node<T> parent);
|
||||
void setParent(Node<T> parent);
|
||||
|
||||
/**
|
||||
* Fetches the child nodes.
|
||||
|
@ -70,16 +77,26 @@ public interface Node<T> {
|
|||
*
|
||||
* @param child the node to add
|
||||
*/
|
||||
void addChild(final Node<T> child);
|
||||
void addChild(Node<T> child);
|
||||
|
||||
/**
|
||||
* Creates a new node and adds it as a child of the current node.
|
||||
* Creates a new unnamed node and adds it as a child of the current node.
|
||||
*
|
||||
* @param child the child node's data
|
||||
*
|
||||
* @return the new child node
|
||||
*/
|
||||
Node<T> createChild(final T child);
|
||||
Node<T> createChild(T child);
|
||||
|
||||
/**
|
||||
* Creates a new named node and adds it as a child of the current node.
|
||||
*
|
||||
* @param child the child node's data
|
||||
* @param name the name
|
||||
*
|
||||
* @return the new child node
|
||||
*/
|
||||
Node<T> createChild(T child, String name);
|
||||
|
||||
/**
|
||||
* Populates the tree with the path of nodes, each being a child of the
|
||||
|
@ -87,7 +104,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @param descendants the line of descendants from the current node
|
||||
*/
|
||||
void createDescendantLine(final List<T> descendants);
|
||||
void createDescendantLine(List<T> descendants);
|
||||
|
||||
/**
|
||||
* Looks for a child node and returns it, creating a new child node if one
|
||||
|
@ -97,7 +114,8 @@ public interface Node<T> {
|
|||
*
|
||||
* @return the found or created child node
|
||||
*/
|
||||
Node<T> findOrCreateChild(final T child);
|
||||
@Deprecated
|
||||
Node<T> findOrCreateChild(T child);
|
||||
|
||||
/**
|
||||
* Fetches the node for the child if present.
|
||||
|
@ -106,7 +124,18 @@ public interface Node<T> {
|
|||
*
|
||||
* @return an {@link Optional} containing the child node if found
|
||||
*/
|
||||
Optional<Node<T>> getChild(final T child);
|
||||
Optional<Node<T>> findChild(T child);
|
||||
|
||||
/**
|
||||
* Fetches the node for the child if present.
|
||||
*
|
||||
* @param child the child's data to search for
|
||||
*
|
||||
* @return the child node if found
|
||||
*
|
||||
* @throws NodeException if the node is not found
|
||||
*/
|
||||
Node<T> getChild(T child);
|
||||
|
||||
/**
|
||||
* Checks if the node is an ancestor.
|
||||
|
@ -115,7 +144,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @return true if the node is an ancestor
|
||||
*/
|
||||
boolean isChildOf(final Node<T> node);
|
||||
boolean isDescendantOf(Node<T> node);
|
||||
|
||||
/**
|
||||
* Walks the node tree using the path to select each child.
|
||||
|
@ -124,7 +153,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @return the child or null
|
||||
*/
|
||||
Optional<Node<T>> walkTree(final List<T> path);
|
||||
Optional<Node<T>> findInPath(List<T> path);
|
||||
|
||||
/**
|
||||
* Places the node in the tree under by the path. Intervening empty
|
||||
|
@ -133,7 +162,7 @@ public interface Node<T> {
|
|||
* @param node the node to place
|
||||
* @param path the path to contain the new node
|
||||
*/
|
||||
void placeNodeIn(Node<T> node, String... path);
|
||||
void insertInPath(Node<T> node, String... path);
|
||||
|
||||
/**
|
||||
* Searches for a child with the name given.
|
||||
|
@ -142,7 +171,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @return an Optional containing the child found or empty
|
||||
*/
|
||||
Optional<Node<T>> findChildNamed(String name);
|
||||
Optional<Node<T>> findChildByName(String name);
|
||||
|
||||
/**
|
||||
* Returns the child with the given name. If one can't be found a
|
||||
|
@ -152,7 +181,7 @@ public interface Node<T> {
|
|||
*
|
||||
* @return the node
|
||||
*/
|
||||
Node<T> getChildNamed(String name);
|
||||
Node<T> getChildByName(String name);
|
||||
|
||||
/**
|
||||
* Draw a representation of the tree.
|
||||
|
|
|
@ -16,7 +16,7 @@ import java.util.function.Function;
|
|||
*/
|
||||
public class NodeItem<T> implements Node<T> {
|
||||
|
||||
private final T data;
|
||||
private T data;
|
||||
|
||||
private final Set<Node<T>> children = new HashSet<>();
|
||||
|
||||
|
@ -127,6 +127,11 @@ public class NodeItem<T> implements Node<T> {
|
|||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(final T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return data == null;
|
||||
|
@ -152,11 +157,11 @@ public class NodeItem<T> implements Node<T> {
|
|||
if (child == null) {
|
||||
throw new NullPointerException("child");
|
||||
}
|
||||
if (this.equals(child) || isChildOf(child)) {
|
||||
if (this.equals(child) || isDescendantOf(child)) {
|
||||
throw new NodeException("Child is an ancestor");
|
||||
}
|
||||
if (child.isNamed()) {
|
||||
final Optional<Node<T>> existingChild = findChildNamed(
|
||||
final Optional<Node<T>> existingChild = findChildByName(
|
||||
child.getName());
|
||||
if (existingChild.isPresent() && existingChild.get() != child) {
|
||||
throw new NodeException(
|
||||
|
@ -184,6 +189,14 @@ public class NodeItem<T> implements Node<T> {
|
|||
return new NodeItem<>(child, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("hiddenfield")
|
||||
public Node<T> createChild(final T child, final String name) {
|
||||
Node<T> node = createChild(child);
|
||||
node.setName(name);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the tree with the path of nodes, each being a child of the
|
||||
* previous node in the path.
|
||||
|
@ -214,7 +227,7 @@ public class NodeItem<T> implements Node<T> {
|
|||
if (child == null) {
|
||||
throw new NullPointerException("child");
|
||||
}
|
||||
return getChild(child).orElseGet(() -> createChild(child));
|
||||
return findChild(child).orElseGet(() -> createChild(child));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,7 +238,7 @@ public class NodeItem<T> implements Node<T> {
|
|||
* @return an {@link Optional} containing the child node if found
|
||||
*/
|
||||
@Override
|
||||
public Optional<Node<T>> getChild(final T child) {
|
||||
public Optional<Node<T>> findChild(final T child) {
|
||||
if (child == null) {
|
||||
throw new NullPointerException("child");
|
||||
}
|
||||
|
@ -234,6 +247,15 @@ public class NodeItem<T> implements Node<T> {
|
|||
.findAny();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node<T> getChild(final T child) {
|
||||
Optional<Node<T>> optional = findChild(child);
|
||||
if (optional.isPresent()) {
|
||||
return optional.get();
|
||||
}
|
||||
throw new NodeException("Child not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the node is an ancestor.
|
||||
*
|
||||
|
@ -242,8 +264,8 @@ public class NodeItem<T> implements Node<T> {
|
|||
* @return true if the node is an ancestor
|
||||
*/
|
||||
@Override
|
||||
public boolean isChildOf(final Node<T> node) {
|
||||
return parent != null && (node.equals(parent) || parent.isChildOf(
|
||||
public boolean isDescendantOf(final Node<T> node) {
|
||||
return parent != null && (node.equals(parent) || parent.isDescendantOf(
|
||||
node));
|
||||
}
|
||||
|
||||
|
@ -257,7 +279,7 @@ public class NodeItem<T> implements Node<T> {
|
|||
if (parent == null) {
|
||||
throw new NullPointerException("parent");
|
||||
}
|
||||
if (this.equals(parent) || parent.isChildOf(this)) {
|
||||
if (this.equals(parent) || parent.isDescendantOf(this)) {
|
||||
throw new NodeException("Parent is a descendant");
|
||||
}
|
||||
if (this.parent != null) {
|
||||
|
@ -275,15 +297,15 @@ public class NodeItem<T> implements Node<T> {
|
|||
* @return the child or null
|
||||
*/
|
||||
@Override
|
||||
public Optional<Node<T>> walkTree(final List<T> path) {
|
||||
public Optional<Node<T>> findInPath(final List<T> path) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("path");
|
||||
}
|
||||
if (path.size() > 0) {
|
||||
Optional<Node<T>> found = getChild(path.get(0));
|
||||
Optional<Node<T>> found = findChild(path.get(0));
|
||||
if (found.isPresent()) {
|
||||
if (path.size() > 1) {
|
||||
return found.get().walkTree(path.subList(1, path.size()));
|
||||
return found.get().findInPath(path.subList(1, path.size()));
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
@ -292,13 +314,13 @@ public class NodeItem<T> implements Node<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void placeNodeIn(final Node<T> nodeItem, final String... path) {
|
||||
public void insertInPath(final Node<T> nodeItem, final String... path) {
|
||||
if (path.length == 0) {
|
||||
if (!nodeItem.isNamed()) { // nothing to conflict with
|
||||
addChild(nodeItem);
|
||||
return;
|
||||
}
|
||||
final Optional<Node<T>> childNamed = findChildNamed(
|
||||
final Optional<Node<T>> childNamed = findChildByName(
|
||||
nodeItem.getName());
|
||||
if (!childNamed.isPresent()) { // nothing with the same name exists
|
||||
addChild(nodeItem);
|
||||
|
@ -317,18 +339,18 @@ public class NodeItem<T> implements Node<T> {
|
|||
return;
|
||||
}
|
||||
String item = path[0];
|
||||
final Optional<Node<T>> childNamed = findChildNamed(item);
|
||||
final Optional<Node<T>> childNamed = findChildByName(item);
|
||||
Node<T> child;
|
||||
if (!childNamed.isPresent()) {
|
||||
child = new NodeItem<>(null, item, this);
|
||||
} else {
|
||||
child = childNamed.get();
|
||||
}
|
||||
child.placeNodeIn(nodeItem, Arrays.copyOfRange(path, 1, path.length));
|
||||
child.insertInPath(nodeItem, Arrays.copyOfRange(path, 1, path.length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Node<T>> findChildNamed(final String named) {
|
||||
public Optional<Node<T>> findChildByName(final String named) {
|
||||
if (named == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
|
@ -338,8 +360,8 @@ public class NodeItem<T> implements Node<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Node<T> getChildNamed(final String named) {
|
||||
final Optional<Node<T>> optional = findChildNamed(named);
|
||||
public Node<T> getChildByName(final String named) {
|
||||
final Optional<Node<T>> optional = findChildByName(named);
|
||||
if (optional.isPresent()) {
|
||||
return optional.get();
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ public class NodeItemTest {
|
|||
assertThat(child.getParent()).as(
|
||||
"when a node is assigned a new parent, the old parent is "
|
||||
+ "replaced").isSameAs(newParent);
|
||||
assertThat(node.getChild("child").isPresent()).as(
|
||||
assertThat(node.findChild("child").isPresent()).as(
|
||||
"when a node is assigned a new parent, the old parent no "
|
||||
+ "longer has the node among it's children").isFalse();
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ public class NodeItemTest {
|
|||
"when a node with an existing parent is added as a child "
|
||||
+ "to another node, then the old parent is replaced")
|
||||
.isSameAs(newParent);
|
||||
assertThat(node.getChild("child").isPresent()).as(
|
||||
assertThat(node.findChild("child").isPresent()).as(
|
||||
"when a node with an existing parent is added as a child to "
|
||||
+ "another node, then the old parent no longer has "
|
||||
+ "the node among it's children").isFalse();
|
||||
|
@ -330,7 +330,7 @@ public class NodeItemTest {
|
|||
val subject = "subject";
|
||||
node = new NodeItem<>(subject, parentNode);
|
||||
//when
|
||||
val result = grandParentNode.walkTree(Arrays.asList(parent, subject));
|
||||
val result = grandParentNode.findInPath(Arrays.asList(parent, subject));
|
||||
//then
|
||||
assertThat(result.isPresent()).as(
|
||||
"when we walk the tree to a node it is found").isTrue();
|
||||
|
@ -353,7 +353,7 @@ public class NodeItemTest {
|
|||
val subject = "subject";
|
||||
node = new NodeItem<>(subject, parentNode);
|
||||
//when
|
||||
val result = parentNode.walkTree(Arrays.asList(subject, "no child"));
|
||||
val result = parentNode.findInPath(Arrays.asList(subject, "no child"));
|
||||
//then
|
||||
assertThat(result.isPresent()).as(
|
||||
"when we walk the tree to a node that doesn't exists, nothing"
|
||||
|
@ -370,7 +370,7 @@ public class NodeItemTest {
|
|||
exception.expect(NullPointerException.class);
|
||||
exception.expectMessage("path");
|
||||
//when
|
||||
node.walkTree(null);
|
||||
node.findInPath(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -382,7 +382,7 @@ public class NodeItemTest {
|
|||
//given
|
||||
node = new NodeItem<>("subject", Node::getData);
|
||||
//when
|
||||
val result = node.walkTree(Collections.emptyList());
|
||||
val result = node.findInPath(Collections.emptyList());
|
||||
//then
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ public class NodeItemTest {
|
|||
node.createDescendantLine(
|
||||
Arrays.asList(alphaData, betaData, gammaData));
|
||||
//then
|
||||
val alphaOptional = node.getChild(alphaData);
|
||||
val alphaOptional = node.findChild(alphaData);
|
||||
assertThat(alphaOptional.isPresent()).as(
|
||||
"when creating a descendant line, the first element is found")
|
||||
.isTrue();
|
||||
|
@ -410,7 +410,7 @@ public class NodeItemTest {
|
|||
assertThat(alpha.getParent()).as(
|
||||
"when creating a descendant line, the first element has "
|
||||
+ "the current node as its parent").isSameAs(node);
|
||||
val betaOptional = alpha.getChild(betaData);
|
||||
val betaOptional = alpha.findChild(betaData);
|
||||
assertThat(betaOptional.isPresent()).as(
|
||||
"when creating a descendant line, the second element is "
|
||||
+ "found").isTrue();
|
||||
|
@ -420,7 +420,7 @@ public class NodeItemTest {
|
|||
"when creating a descendant line, the second element "
|
||||
+ "has the first as its parent")
|
||||
.isSameAs(alpha);
|
||||
val gammaOptional = beta.getChild(gammaData);
|
||||
val gammaOptional = beta.findChild(gammaData);
|
||||
assertThat(gammaOptional.isPresent()).as(
|
||||
"when creating a descendant line, the third element "
|
||||
+ "is found").isTrue();
|
||||
|
@ -521,7 +521,7 @@ public class NodeItemTest {
|
|||
val child = new NodeItem<String>(childData, Node::getData);
|
||||
node.addChild(child);
|
||||
//when
|
||||
val found = node.getChild(childData);
|
||||
val found = node.findChild(childData);
|
||||
//then
|
||||
assertThat(found.isPresent()).as(
|
||||
"when retrieving a child by its data, it is found").isTrue();
|
||||
|
@ -542,7 +542,7 @@ public class NodeItemTest {
|
|||
exception.expect(NullPointerException.class);
|
||||
exception.expectMessage("child");
|
||||
//when
|
||||
node.getChild(null);
|
||||
node.findChild(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -560,7 +560,7 @@ public class NodeItemTest {
|
|||
assertThat(child.getParent()).as(
|
||||
"when creating a child node, the child has the current node "
|
||||
+ "as its parent").isSameAs(node);
|
||||
val foundChild = node.getChild(childData);
|
||||
val foundChild = node.findChild(childData);
|
||||
assertThat(foundChild.isPresent()).as(
|
||||
"when creating a child node, the child can be found by its "
|
||||
+ "data").isTrue();
|
||||
|
@ -651,7 +651,7 @@ public class NodeItemTest {
|
|||
node.addChild(alpha);
|
||||
node.addChild(beta);
|
||||
//when
|
||||
val result = node.getChildNamed("alpha");
|
||||
val result = node.getChildByName("alpha");
|
||||
//then
|
||||
assertThat(result).isSameAs(alpha);
|
||||
}
|
||||
|
@ -667,7 +667,7 @@ public class NodeItemTest {
|
|||
exception.expect(NodeException.class);
|
||||
exception.expectMessage("Named child not found");
|
||||
//when
|
||||
node.getChildNamed("gamma");
|
||||
node.getChildByName("gamma");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -689,7 +689,7 @@ public class NodeItemTest {
|
|||
node = new NodeItem<>(null, "root"); // create a root
|
||||
val four = new NodeItem<String>("data", "four");
|
||||
//when
|
||||
node.placeNodeIn(four, "one", "two", "three");
|
||||
node.insertInPath(four, "one", "two", "three");
|
||||
//then
|
||||
val three = four.getParent();
|
||||
assertThat(four.getParent()).as("add node to a tree").isNotNull();
|
||||
|
@ -699,10 +699,10 @@ public class NodeItemTest {
|
|||
val one = two.getParent();
|
||||
assertThat(one.getName()).isEqualTo("one");
|
||||
assertThat(one.getParent()).isSameAs(node);
|
||||
assertThat(node.getChildNamed("one")
|
||||
.getChildNamed("two")
|
||||
.getChildNamed("three")
|
||||
.getChildNamed("four")).isSameAs(four);
|
||||
assertThat(node.getChildByName("one")
|
||||
.getChildByName("two")
|
||||
.getChildByName("three")
|
||||
.getChildByName("four")).isSameAs(four);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -713,11 +713,11 @@ public class NodeItemTest {
|
|||
val child = new NodeItem<String>("child data", "child");
|
||||
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
|
||||
//when
|
||||
node.placeNodeIn(child); // as root/child
|
||||
node.placeNodeIn(grandchild, "child"); // as root/child/grandchild
|
||||
node.insertInPath(child); // as root/child
|
||||
node.insertInPath(grandchild, "child"); // as root/child/grandchild
|
||||
//then
|
||||
assertThat(node.getChildNamed("child")).as("child").isSameAs(child);
|
||||
assertThat(node.getChildNamed("child").getChildNamed("grandchild")).as(
|
||||
assertThat(node.getChildByName("child")).as("child").isSameAs(child);
|
||||
assertThat(node.getChildByName("child").getChildByName("grandchild")).as(
|
||||
"grandchild").isSameAs(grandchild);
|
||||
}
|
||||
|
||||
|
@ -729,11 +729,11 @@ public class NodeItemTest {
|
|||
val child = new NodeItem<String>("child data", "child");
|
||||
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
|
||||
//when
|
||||
node.placeNodeIn(grandchild, "child");
|
||||
node.placeNodeIn(child);
|
||||
node.insertInPath(grandchild, "child");
|
||||
node.insertInPath(child);
|
||||
//then
|
||||
assertThat(node.getChildNamed("child")).as("child").isSameAs(child);
|
||||
assertThat(node.getChildNamed("child").getChildNamed("grandchild")).as(
|
||||
assertThat(node.getChildByName("child")).as("child").isSameAs(child);
|
||||
assertThat(node.getChildByName("child").getChildByName("grandchild")).as(
|
||||
"grandchild").isSameAs(grandchild);
|
||||
}
|
||||
|
||||
|
@ -758,7 +758,7 @@ public class NodeItemTest {
|
|||
// only grandchild has data
|
||||
//when
|
||||
// attempt to add another node called 'grandchild' to 'child'
|
||||
node.placeNodeIn(new NodeItem<>("cuckoo", "grandchild"), "child");
|
||||
node.insertInPath(new NodeItem<>("cuckoo", "grandchild"), "child");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -768,7 +768,7 @@ public class NodeItemTest {
|
|||
node = new NodeItem<>(null);
|
||||
final Node<String> newNode = new NodeItem<>(null);
|
||||
//when
|
||||
node.placeNodeIn(newNode);
|
||||
node.insertInPath(newNode);
|
||||
//then
|
||||
assertThat(node.getChildren()).containsOnly(newNode);
|
||||
}
|
||||
|
@ -786,7 +786,7 @@ public class NodeItemTest {
|
|||
assertThat(addMe.getParent()).isNull();
|
||||
//when
|
||||
// addMe should replace target as the sole descendant of child
|
||||
node.placeNodeIn(addMe, "child");
|
||||
node.insertInPath(addMe, "child");
|
||||
//then
|
||||
assertThat(child.getChildren()).as("child only contains new node")
|
||||
.containsOnly(addMe);
|
||||
|
@ -801,7 +801,7 @@ public class NodeItemTest {
|
|||
exception.expectMessage("name");
|
||||
node = new NodeItem<>(null);
|
||||
//when
|
||||
node.findChildNamed(null);
|
||||
node.findChildByName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -878,4 +878,48 @@ public class NodeItemTest {
|
|||
"[ lucy]");
|
||||
assertThat(lines).containsSubsequence("[root]", "[ bob]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canChangeNodeData() {
|
||||
//given
|
||||
node = new NodeItem<>("initial");
|
||||
//when
|
||||
node.setData("updated");
|
||||
//then
|
||||
assertThat(node.getData()).isEqualTo("updated");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void canCreateNamedChild() {
|
||||
//given
|
||||
node = new NodeItem<>(null);
|
||||
//when
|
||||
Node<String> child = node.createChild("child data", "child name");
|
||||
//then
|
||||
assertThat(child.getName()).isEqualTo("child name");
|
||||
assertThat(child.getParent()).isSameAs(node);
|
||||
assertThat(node.getChildren()).containsExactly(child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetChildWhenFound() {
|
||||
//given
|
||||
node = new NodeItem<>("data");
|
||||
Node<String> child = new NodeItem<>("child data", "child name", node);
|
||||
//when
|
||||
Node<String> found = node.getChild("child data");
|
||||
//then
|
||||
assertThat(found).isSameAs(child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetChildWhenNotFound() {
|
||||
//given
|
||||
exception.expect(NodeException.class);
|
||||
exception.expectMessage("Child not found");
|
||||
node = new NodeItem<>("data");
|
||||
//when
|
||||
node.getChild("child data");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue