From 8cd57711b84ea7dcf5150c9dbd853165b7cc6474 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:08:52 +0000 Subject: [PATCH 1/8] Initial commit --- .gitignore | 2 + checkstyle.xml | 192 +++++++ pom.xml | 53 ++ src/main/java/net/kemitix/node/Node.java | 108 ++++ .../java/net/kemitix/node/NodeException.java | 20 + src/main/java/net/kemitix/node/NodeItem.java | 186 +++++++ .../java/net/kemitix/node/package-info.java | 4 + .../net/kemitix/node/NodeExceptionTest.java | 35 ++ .../java/net/kemitix/node/NodeItemTest.java | 496 ++++++++++++++++++ 9 files changed, 1096 insertions(+) create mode 100644 .gitignore create mode 100644 checkstyle.xml create mode 100644 pom.xml create mode 100644 src/main/java/net/kemitix/node/Node.java create mode 100644 src/main/java/net/kemitix/node/NodeException.java create mode 100644 src/main/java/net/kemitix/node/NodeItem.java create mode 100644 src/main/java/net/kemitix/node/package-info.java create mode 100644 src/test/java/net/kemitix/node/NodeExceptionTest.java create mode 100644 src/test/java/net/kemitix/node/NodeItemTest.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c89b474 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/nbproject diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..e54bdb6 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9675f0f --- /dev/null +++ b/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + net.kemitix + node + 0.1.0-SNAPSHOT + jar + + Node + A parent/children data structure + + + net.kemitix + kemitix-parent + 0.6.0 + + + + https://github.com/kemitix/node/issues + GitHub Issues + + + + scm:git:git@github.com:kemitix/node.git + scm:git:git@github.com:kemitix/node.git + git@github.com:kemitix/node.git + + + https://github.com/kemitix/node + + 2016 + + + + org.projectlombok + lombok + 1.16.6 + + + + junit + junit + 4.12 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + \ No newline at end of file diff --git a/src/main/java/net/kemitix/node/Node.java b/src/main/java/net/kemitix/node/Node.java new file mode 100644 index 0000000..2dae709 --- /dev/null +++ b/src/main/java/net/kemitix/node/Node.java @@ -0,0 +1,108 @@ +package net.kemitix.node; + +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * An interface for tree node items. + * + * @author pcampbell + * @param the type of data held in each node + */ +public interface Node { + + /** + * Fetch the data held within the node. + * + * @return the node's data + */ + T getData(); + + /** + * Fetch the parent node. + * + *

+ * If the node is a root node, i.e. has no parent, then this will return + * null. + * + * @return the parent node + */ + Node getParent(); + + /** + * Fetches the child nodes. + * + * @return the set of child nodes + */ + Set> getChildren(); + + /** + * Adds the child to the node. + * + * @param child the node to add + */ + void addChild(final Node child); + + /** + * Creates a new node and adds it as a child of the current node. + * + * @param child the child node's data + * + * @return the new child node + */ + Node createChild(final T child); + + /** + * Populates the tree with the path of nodes, each being a child of the + * previous node in the path. + * + * @param descendants the line of descendants from the current node + */ + void createDescendantLine(final List descendants); + + /** + * Looks for a child node and returns it, creating a new child node if one + * isn't found. + * + * @param child the child's data to search or create with + * + * @return the found or created child node + */ + Node findOrCreateChild(final T child); + + /** + * Fetches the node for the child if present. + * + * @param child the child's data to search for + * + * @return an {@link Optional} containing the child node if found + */ + Optional> getChild(final T child); + + /** + * Checks if the node is an ancestor. + * + * @param node the potential ancestor + * + * @return true if the node is an ancestor + */ + boolean isChildOf(final Node node); + + /** + * Make the current node a direct child of the parent. + * + * @param parent the new parent node + */ + void setParent(final Node parent); + + /** + * Walks the node tree using the path to select each child. + * + * @param path the path to the desired child + * + * @return the child or null + */ + Optional> walkTree(final List path); + +} diff --git a/src/main/java/net/kemitix/node/NodeException.java b/src/main/java/net/kemitix/node/NodeException.java new file mode 100644 index 0000000..7f84643 --- /dev/null +++ b/src/main/java/net/kemitix/node/NodeException.java @@ -0,0 +1,20 @@ +package net.kemitix.node; + +/** + * Represents an error within the tree node. + * + * @author pcampbell + */ +@SuppressWarnings("serial") +public class NodeException extends RuntimeException { + + /** + * Constructor with message. + * + * @param message the message + */ + public NodeException(final String message) { + super(message); + } + +} diff --git a/src/main/java/net/kemitix/node/NodeItem.java b/src/main/java/net/kemitix/node/NodeItem.java new file mode 100644 index 0000000..d35366a --- /dev/null +++ b/src/main/java/net/kemitix/node/NodeItem.java @@ -0,0 +1,186 @@ +package net.kemitix.node; + +import lombok.Getter; +import lombok.NonNull; + +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * Represents a tree of nodes. + * + * @param the type of data stored in each node + * + * @author pcampbell + */ +public class NodeItem implements Node { + + @Getter + private final T data; + + @Getter + private Node parent; + + @Getter + private Set> children; + + /** + * Creates a root node. + * + * @param data the value of the node + */ + public NodeItem(@NonNull final T data) { + this(data, null); + } + + /** + * Creates a node with a parent. + * + * @param data the value of the node + * @param parent the parent node + */ + public NodeItem(final T data, final Node parent) { + this.data = data; + if (parent != null) { + setParent(parent); + } + this.children = new HashSet<>(); + } + + /** + * Make the current node a direct child of the parent. + * + * @param parent the new parent node + */ + @Override + public final void setParent(@NonNull final Node parent) { + if (this.equals(parent) || parent.isChildOf(this)) { + throw new NodeException("Parent is a descendant"); + } + if (this.parent != null) { + this.parent.getChildren().remove(this); + } + this.parent = parent; + parent.addChild(this); + } + + /** + * Adds the child to the node. + * + * @param child the node to add + */ + @Override + public void addChild(@NonNull final Node child) { + if (this.equals(child) || isChildOf(child)) { + throw new NodeException("Child is an ancestor"); + } + children.add(child); + if (child.getParent() == null || !child.getParent().equals(this)) { + child.setParent(this); + } + } + + /** + * Checks if the node is an ancestor. + * + * @param node the potential ancestor + * + * @return true if the node is an ancestor + */ + @Override + public boolean isChildOf(final Node node) { + if (node.equals(parent)) { + return true; + } + if (parent != null) { + return parent.isChildOf(node); + } + return false; + } + + /** + * Walks the node tree using the path to select each child. + * + * @param path the path to the desired child + * + * @return the child or null + */ + @Override + public Optional> walkTree(@NonNull final List path) { + if (path.size() > 0) { + Optional> found = children.stream() + .filter((Node child) -> path.get(0) + .equals(child.getData())) + .findFirst(); + if (found.isPresent()) { + if (path.size() > 1) { + return found.get().walkTree(path.subList(1, path.size())); + } + return found; + } + } + return Optional.empty(); + } + + /** + * Populates the tree with the path of nodes, each being a child of the + * previous node in the path. + * + * @param descendants the line of descendants from the current node + */ + @Override + public void createDescendantLine(@NonNull final List descendants) { + if (!descendants.isEmpty()) { + findOrCreateChild(descendants.get(0)) + .createDescendantLine( + descendants.subList(1, descendants.size())); + } + } + + /** + * Looks for a child node and returns it, creating a new child node if one + * isn't found. + * + * @param child the child's data to search or create with + * + * @return the found or created child node + */ + @Override + public Node findOrCreateChild(@NonNull final T child) { + Optional> found = getChild(child); + if (found.isPresent()) { + return found.get(); + } else { + return createChild(child); + } + } + + /** + * Fetches the node for the child if present. + * + * @param child the child's data to search for + * + * @return an {@link Optional} containing the child node if found + */ + @Override + public Optional> getChild(@NonNull final T child) { + return children.stream() + .filter((Node t) -> t.getData().equals(child)) + .findAny(); + } + + /** + * Creates a new node and adds it as a child of the current node. + * + * @param child the child node's data + * + * @return the new child node + */ + @Override + public Node createChild(@NonNull final T child) { + return new NodeItem<>(child, this); + } + +} diff --git a/src/main/java/net/kemitix/node/package-info.java b/src/main/java/net/kemitix/node/package-info.java new file mode 100644 index 0000000..382684c --- /dev/null +++ b/src/main/java/net/kemitix/node/package-info.java @@ -0,0 +1,4 @@ +/** + * Tree Node implementation. + */ +package net.kemitix.node; diff --git a/src/test/java/net/kemitix/node/NodeExceptionTest.java b/src/test/java/net/kemitix/node/NodeExceptionTest.java new file mode 100644 index 0000000..5e9f7ac --- /dev/null +++ b/src/test/java/net/kemitix/node/NodeExceptionTest.java @@ -0,0 +1,35 @@ +package net.kemitix.node; + +import net.kemitix.node.NodeException; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link NodeException}. + * + * @author pcampbell + */ +public class NodeExceptionTest { + + /** + * Class under test. + */ + private NodeException nodeException; + + /** + * Test that message provided to constructor is returned. + */ + @Test + public void shouldReturnConstructorMessage() { + //given + final String message = "this is the message"; + //when + nodeException = new NodeException(message); + //then + assertThat(nodeException.getMessage(), is(message)); + } + +} diff --git a/src/test/java/net/kemitix/node/NodeItemTest.java b/src/test/java/net/kemitix/node/NodeItemTest.java new file mode 100644 index 0000000..c271ac3 --- /dev/null +++ b/src/test/java/net/kemitix/node/NodeItemTest.java @@ -0,0 +1,496 @@ +package net.kemitix.node; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Optional; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * Test for {@link NodeItem}. + * + * @author pcampbell + */ +public class NodeItemTest { + + /** + * Class under test. + */ + private Node node; + + /** + * Test {@link NodeItem#Node(java.lang.Object) } that node data is + * recoverable. + */ + @Test + public void shouldReturnNodeData() { + //given + final String data = "this node data"; + //when + node = new NodeItem<>(data); + //then + assertThat(node.getData(), is(data)); + } + + /** + * Test {@link NodeItem#Node(java.lang.Object) } that passing null as node + * data throws exception. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenDataIsNull() { + //when + node = new NodeItem<>(null); + } + + /** + * Test {@link NodeItem#Node(java.lang.Object) } that default node parent is + * null. + */ + @Test + public void shouldHaveNullForDefaulParent() { + //given + node = new NodeItem<>("data"); + //then + assertNull(node.getParent()); + } + + /** + * Test {@link NodeItem#Node(java.lang.Object, net.kemitix.node.Node) } that + * provided node parent is returned. + */ + @Test + public void shouldReturnNodeParent() { + //given + Node parent = new NodeItem<>("parent"); + //when + node = new NodeItem<>("subject", parent); + //then + assertThat(node.getParent(), is(parent)); + } + + /** + * Test {@link NodeItem#Node(java.lang.Object, net.kemitix.node.Node) } that + * setting the parent on a node where the proposed parent is a child of the + * node throws an exception. + */ + @Test(expected = NodeException.class) + public void shouldThrowNEWhenSettingParentToAChild() { + //given + node = new NodeItem<>("subject"); + Node child = new NodeItem<>("child", node); + //when + node.setParent(child); + } + + /** + * Test {@link NodeItem#Node(java.lang.Object, net.kemitix.node.Node) } that + * when parent is added to created node, the created node is now a child of + * the parent. + */ + @Test + public void shouldAddNewNodeAsChildToParent() { + //given + Node parent = new NodeItem<>("parent"); + //when + node = new NodeItem<>("subject", parent); + //then + assertThat(parent.getChildren(), hasItem(node)); + } + + /** + * Test {@link NodeItem#setParent(net.kemitix.node.Node) } that we return + * the same parent when set. + */ + @Test + public void shouldReturnSetParent() { + //given + node = new NodeItem<>("subject"); + Node parent = new NodeItem<>("parent"); + //when + node.setParent(parent); + //then + assertThat(node.getParent(), is(parent)); + } + + /** + * Test {@link NodeItem#setParent(net.kemitix.node.Node) } that we throw an + * exception when passed null. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenSetParentNull() { + //given + node = new NodeItem<>("subject"); + //when + node.setParent(null); + } + + /** + * Test {@link NodeItem#setParent(net.kemitix.node.Node) } that we throw an + * exceptions when attempting to node as its own parent. + */ + @Test(expected = NodeException.class) + public void shouldThrowNEWhenSetParentSelf() { + //given + node = new NodeItem<>("subject"); + //when + node.setParent(node); + } + + /** + * Test {@link NodeItem#setParent(net.kemitix.node.Node) } that when a node + * with an existing parent is assigned a new parent, that the old parent no + * longer sees it as one of its children. + */ + @Test + public void shouldUpdateOldParentWhenNodeSetToNewParent() { + //given + node = new NodeItem<>("subject"); + Node child = node.createChild("child"); + Node newParent = new NodeItem<>("newParent"); + //when + child.setParent(newParent); + //then + assertThat(child.getParent(), is(newParent)); + assertFalse(node.getChild("child").isPresent()); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that when a node + * is added as a child to another node, that it's previous parent no longer + * has it as a child. + */ + @Test + public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() { + //given + node = new NodeItem<>("subject"); + Node child = node.createChild("child"); + Node newParent = new NodeItem<>("newParent"); + //when + newParent.addChild(child); + //then + assertThat(child.getParent(), is(newParent)); + assertFalse(node.getChild("child").isPresent()); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding null + * as a child throws an exception. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenAddingNullAsChild() { + //given + node = new NodeItem<>("subject"); + //when + node.addChild(null); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding a + * child is returned. + */ + @Test + public void shouldReturnAddedChild() { + //given + Node child = new NodeItem<>("child"); + node = new NodeItem<>("subject"); + //when + node.addChild(child); + //then + assertThat(node.getChildren(), hasItem(child)); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding a node + * as it's own child throws an exception. + */ + @Test(expected = NodeException.class) + public void shouldThrowNEWhenAddingANodeAsOwnChild() { + //given + node = new NodeItem<>("subject"); + //then + node.addChild(node); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding a node + * to itself as a child causes an exception. + */ + @Test(expected = NodeException.class) + public void shouldThrowWhenAddingSelfAsChild() { + //given + node = new NodeItem<>("subject"); + //when + node.addChild(node); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding the + * parent to node causes an exception. + */ + @Test(expected = NodeException.class) + public void shouldThrowWhenAddingParentAsChild() { + //given + Node parent = new NodeItem<>("parent"); + node = new NodeItem<>("subject", parent); + //when + node.addChild(parent); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding the + * grandparent to node causes an exception. + */ + @Test(expected = NodeException.class) + public void shouldThrowWhenAddingGrandParentAsChild() { + //given + Node grandParent = new NodeItem<>("grandparent"); + Node parent = new NodeItem<>("parent", grandParent); + node = new NodeItem<>("subject", parent); + //when + node.addChild(grandParent); + } + + /** + * Test {@link NodeItem#addChild(net.kemitix.node.Node) } that adding a + * child to a node, sets the child's parent node. + */ + @Test + public void shouldSetParentOnChildWhenAddedAsChild() { + //given + Node child = new NodeItem<>("child"); + node = new NodeItem<>("subject"); + //when + node.addChild(child); + //then + assertThat(child.getParent(), is(node)); + } + + /** + * Test {@link NodeItem#walkTree(java.util.List) } that we can walk a tree + * to the target node. + */ + @Test + public void shouldWalkTreeToNode() { + //given + final String grandparent = "grandparent"; + Node grandParentNode = new NodeItem<>(grandparent); + final String parent = "parent"; + Node parentNode = new NodeItem<>(parent, grandParentNode); + final String subject = "subject"; + node = new NodeItem<>(subject, parentNode); + //when + Optional> result = grandParentNode.walkTree(Arrays.asList( + parent, subject)); + //then + assertTrue(result.isPresent()); + assertThat(result.get(), is(node)); + } + + /** + * Test {@link NodeItem#walkTree(java.util.List) } that we get an empty + * {@link Optional} when walking a path that doesn't exist. + */ + @Test + public void shouldNotFindNonExistantChildNode() { + //given + final String parent = "parent"; + Node parentNode = new NodeItem<>(parent); + final String subject = "subject"; + node = new NodeItem<>(subject, parentNode); + //when + Optional> result = parentNode.walkTree(Arrays.asList( + subject, "no child")); + //then + assertFalse(result.isPresent()); + } + + /** + * Test {@link NodeItem#walkTree(java.util.List) } that when we pass null we + * get an exception. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNEWhenWalkTreeNull() { + //given + node = new NodeItem<>("subject"); + //when + node.walkTree(null); + } + + /** + * Test {@link NodeItem#walkTree(java.util.List) } that when we pass an + * empty path we get and empty {@link Optional} as a result. + */ + @Test + public void shouldReturnEmptyForEmptyWalkTreePath() { + //given + node = new NodeItem<>("subject"); + //when + node.walkTree(Collections.emptyList()); + } + + /** + * Test {@link NodeItem#createDescendantLine(java.util.List) } that we can + * create a chain of descendant nodes. + */ + @Test + public void shouldCreateDescendantNodes() { + //given + node = new NodeItem<>("subject"); + final String alphaData = "alpha"; + final String betaData = "beta"; + final String gammaData = "gamma"; + //when + node.createDescendantLine( + Arrays.asList(alphaData, betaData, gammaData)); + //then + final Optional> alphaOptional = node.getChild(alphaData); + assertTrue(alphaOptional.isPresent()); + Node alpha = alphaOptional.get(); + assertThat(alpha.getParent(), is(node)); + final Optional> betaOptional = alpha.getChild(betaData); + assertTrue(betaOptional.isPresent()); + Node beta = betaOptional.get(); + assertThat(beta.getParent(), is(alpha)); + final Optional> gammaOptional = beta.getChild(gammaData); + assertTrue(gammaOptional.isPresent()); + Node gamma = gammaOptional.get(); + assertThat(gamma.getParent(), is(beta)); + } + + /** + * Test {@link NodeItem#createDescendantLine(java.util.List) } that if we + * pass null to create a chain of descendant nodes we get an exception. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenCreateDescendantNull() { + //given + node = new NodeItem<>("subject"); + //when + node.createDescendantLine(null); + } + + /** + * Test {@link NodeItem#createDescendantLine(java.util.List) } that if we + * pass an empty list nothing is changed. + */ + @Test + public void shouldChangeNothingWhenCreateDescendantEmpty() { + //given + node = new NodeItem<>("subject"); + //when + node.createDescendantLine(Collections.emptyList()); + //then + assertThat(node.getChildren().size(), is(0)); + } + + /** + * Test {@link NodeItem#findOrCreateChild(java.lang.Object) } that we can + * find a child of a node. + */ + @Test + public void shouldFindExistingChildNode() { + //given + node = new NodeItem<>("subject"); + final String childData = "child"; + Node child = new NodeItem<>(childData, node); + //when + Node found = node.findOrCreateChild(childData); + //then + assertThat(found, is(child)); + } + + /** + * Test {@link NodeItem#findOrCreateChild(java.lang.Object) } that we create + * a missing child of a node. + */ + @Test + public void shouldFindCreateNewChildNode() { + //given + node = new NodeItem<>("subject"); + final String childData = "child"; + //when + Node found = node.findOrCreateChild(childData); + //then + assertThat(found.getData(), is(childData)); + } + + /** + * Test {@link NodeItem#findOrCreateChild(java.lang.Object) } that if we + * pass null we get an exception. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEFWhenFindOrCreateChildNull() { + //given + node = new NodeItem<>("subject"); + //when + node.findOrCreateChild(null); + } + + /** + * Test {@link NodeItem#getChild(java.lang.Object) } that we can get the + * node for a child. + */ + @Test + public void shouldGetChild() { + //given + node = new NodeItem<>("subject"); + final String childData = "child"; + Node child = new NodeItem<>(childData); + node.addChild(child); + //when + Optional> found = node.getChild(childData); + //then + assertTrue(found.isPresent()); + assertThat(found.get(), is(child)); + } + + /** + * Test {@link NodeItem#getChild(java.lang.Object) } that we throw an + * exception when passed null. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenGetChildNull() { + //given + node = new NodeItem<>("subject"); + //when + node.getChild(null); + } + + /** + * Test {@link NodeItem#createChild(java.lang.Object) } that we create a + * child as a child of the current node and with the current node as its + * parent. + */ + @Test + public void shoudCreateChild() { + //given + node = new NodeItem<>("subject"); + final String childData = "child"; + //when + Node child = node.createChild(childData); + //then + assertThat(child.getParent(), is(node)); + final Optional> foundChild = node.getChild(childData); + assertTrue(foundChild.isPresent()); + assertThat(foundChild.get(), is(child)); + } + + /** + * Test that we throw an exception when passed null. + */ + @Test(expected = NullPointerException.class) + public void shouldThrowNPEWhenCreateChildNull() { + //given + node = new NodeItem<>("subject"); + //when + node.createChild(null); + } + +} From e977725fbf613cddea3c6d8d475079d468975498 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:14:30 +0000 Subject: [PATCH 2/8] CHANGELOG: added Signed-off-by: Paul Campbell --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..de26b1f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,3 @@ +CHANGELOG +========= + From 10a0ff71dd49d13728957cbf30c8e53b722e06d3 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:19:54 +0000 Subject: [PATCH 3/8] .travis.yml: added Signed-off-by: Paul Campbell --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..968917c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: java +jdk: + - oraclejdk8 From 271679e00647f0f806623d44f03099ce2813bd7e Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:51:36 +0000 Subject: [PATCH 4/8] README.md: add usage and examples Signed-off-by: Paul Campbell --- README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/README.md b/README.md index c6297e0..e5b9073 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,59 @@ # node A parent/children data structure + +# Usage + +Add as a dependency in your `pom.xml`: + + + net.kemitix + node + ${node.version} + + +The library consits of an interface `Node` and an implementation `NodeItem`. + +## Create a root node + + Node root = new NodeItem<>("[root]"); + +## Get the contents of the node + + String rootData = root.getData(); // returns "[root]" + +## Add a child node + + root.addChild("child"); + +The tree now looks like: + + "[root]" + \-> "child" + +## Get the child node + + Node childNode = root.getChild("child"); + +## Create a chain of nodes + + root.createDescendantLine(Arrays.asList("alpha", "beta", "gamma")); + + "[root]" + |-> "child" + \-> "alpha" + \-> "beta" + \-> "gamma" + +## Walk the tree to find a node + + Optional> foundNode = root.walkTree(Arrays.asList( + "alpha", "beta", "gamma")); + if (foundNode.isPresent()) { + String betaData = foundNode.get().getParent().getData(); + // returns "beta" + } + +## Get all children of a node + + Set> children = root.getChildren(); + children.size(); // returns 2 ("child" and "alpha") From 749dd506ad1591f99ba609422e57fed891fb6cc4 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:53:46 +0000 Subject: [PATCH 5/8] README.md: fix typo Signed-off-by: Paul Campbell --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e5b9073..77c8100 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,11 @@ The library consits of an interface `Node` and an implementation `NodeItem`. ## Add a child node - root.addChild("child"); + root.createChild("child"); + +Which is shorthand for: + + root.addChild(new NodeItem<>("child")); The tree now looks like: From 1f508bc3d2705ea615e3e346d75aed4237f21c27 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 17:55:24 +0000 Subject: [PATCH 6/8] README.md: fix typo Signed-off-by: Paul Campbell --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77c8100..b80d2ec 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,12 @@ The library consits of an interface `Node` and an implementation `NodeItem`. ## Add a child node - root.createChild("child"); + Node child = root.createChild("child"); Which is shorthand for: - root.addChild(new NodeItem<>("child")); + Node child = new NodeItem<>("child"); + root.addChild(child); The tree now looks like: From d74d44ba9d1cfe34750f21f4e8f44618b12608e8 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 18:00:33 +0000 Subject: [PATCH 7/8] pom.xml: version set to 0.1.0 Signed-off-by: Paul Campbell --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9675f0f..59ab9da 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.kemitix node - 0.1.0-SNAPSHOT + 0.1.0 jar Node @@ -50,4 +50,4 @@ test - \ No newline at end of file + From 06a2890325fe27053e2857f4c2e9a23d900b1fca Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sat, 9 Jan 2016 18:00:33 +0000 Subject: [PATCH 8/8] CHANGELOG Signed-off-by: Paul Campbell --- CHANGELOG | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index de26b1f..ea41f65 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ CHANGELOG ========= +0.1.0 +------ + +* Initial Release +