Merge pull request #16 from kemitix/upgrade-kemitix-parent-to-2.0.0

Upgrade kemitix-parent to 2.0.0
This commit is contained in:
Paul Campbell 2016-09-04 22:32:52 +01:00 committed by GitHub
commit 600eb94616
9 changed files with 146 additions and 346 deletions

View file

@ -1,192 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the sun coding conventions from:
- the Java Language Specification at
http://java.sun.com/docs/books/jls/second_edition/html/index.html
- the Sun Code Conventions at http://java.sun.com/docs/codeconv/
- the Javadoc guidelines at
http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
- the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
- some best practices
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
Most Checks are configurable, be sure to consult the documentation.
To completely disable a check, just comment it out or delete it from the file.
Finally, it is worth reading the documentation.
-->
<module name="Checker">
<!--
If you set the basedir property below, then all reported file
names will be relative to the specified directory. See
http://checkstyle.sourceforge.net/5.x/config.html#Checker
<property name="basedir" value="${basedir}"/>
-->
<!-- Checks that a package-info.java file exists for each package. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
<module name="JavadocPackage"/>
<!-- Checks whether files end with a new line. -->
<!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
<module name="NewlineAtEndOfFile"/>
<!-- Checks that property files contain the same keys. -->
<!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
<module name="Translation"/>
<!-- Checks for Size Violations. -->
<!-- See http://checkstyle.sf.net/config_sizes.html -->
<module name="FileLength"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter"/>
<!-- Miscellaneous other checks. -->
<!-- See http://checkstyle.sf.net/config_misc.html -->
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="minimum" value="0"/>
<property name="maximum" value="0"/>
<property name="message" value="Line has trailing spaces."/>
</module>
<!-- Checks for Headers -->
<!-- See http://checkstyle.sf.net/config_header.html -->
<!-- <module name="Header"> -->
<!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
<!-- <property name="fileExtensions" value="java"/> -->
<!-- </module> -->
<module name="TreeWalker">
<!-- Support @SuppressWarnings annotation -->
<!-- See http://checkstyle.sourceforge.net/config.html -->
<module name="SuppressWarningsHolder"/>
<module name="FileContentsHolder"/>
<!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
<module name="JavadocMethod">
<property name="scope" value="public"/>
</module>
<module name="JavadocType"/>
<!--<module name="JavadocVariable"/>-->
<module name="JavadocStyle"/>
<!-- Checks for Naming Conventions. -->
<!-- See http://checkstyle.sf.net/config_naming.html -->
<module name="ConstantName"/>
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName"/>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<!-- Checks for imports -->
<!-- See http://checkstyle.sf.net/config_import.html -->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
<module name="RedundantImport"/>
<module name="UnusedImports"/>
<!-- Checks for Size Violations. -->
<!-- See http://checkstyle.sf.net/config_sizes.html -->
<module name="LineLength"/>
<module name="MethodLength"/>
<module name="ParameterNumber"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="EmptyForIteratorPad"/>
<module name="GenericWhitespace"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter"/>
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
<!-- Modifier Checks -->
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<!-- Checks for blocks. You know, those {}'s -->
<!-- See http://checkstyle.sf.net/config_blocks.html -->
<module name="AvoidNestedBlocks"/>
<module name="EmptyBlock"/>
<module name="LeftCurly"/>
<module name="NeedBraces"/>
<module name="RightCurly"/>
<!-- Checks for common coding problems -->
<!-- See http://checkstyle.sf.net/config_coding.html -->
<module name="AvoidInlineConditionals"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="HiddenField">
<property name="ignoreConstructorParameter" value="true"/>
<property name="ignoreSetter" value="true"/>
<property name="setterCanReturnItsClass" value="true"/>
</module>
<module name="IllegalInstantiation"/>
<module name="InnerAssignment"/>
<module name="MagicNumber"/>
<module name="MissingSwitchDefault"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<!-- Checks for class design -->
<!-- See http://checkstyle.sf.net/config_design.html -->
<!--<module name="DesignForExtension"/>-->
<module name="FinalClass"/>
<module name="HideUtilityClassConstructor"/>
<module name="InterfaceIsType"/>
<module name="VisibilityModifier"/>
<!-- Miscellaneous other checks. -->
<!-- See http://checkstyle.sf.net/config_misc.html -->
<module name="ArrayTypeStyle"/>
<module name="FinalParameters"/>
<module name="TodoComment"/>
<module name="UpperEll"/>
</module>
<module name="SuppressWarningsFilter"/>
<module name="SuppressionCommentFilter"/>
</module>

View file

@ -11,7 +11,7 @@
<parent> <parent>
<groupId>net.kemitix</groupId> <groupId>net.kemitix</groupId>
<artifactId>kemitix-parent</artifactId> <artifactId>kemitix-parent</artifactId>
<version>0.6.0</version> <version>2.0.0</version>
</parent> </parent>
<properties> <properties>
@ -50,7 +50,6 @@
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.16.8</version> <version>1.16.8</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View file

@ -1,5 +1,7 @@
package net.kemitix.node; package net.kemitix.node;
import lombok.NonNull;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -9,9 +11,9 @@ import java.util.Set;
* An abstract node item, providing default implementations for most read-only * An abstract node item, providing default implementations for most read-only
* operations. * operations.
* *
* @param <T> the type of data stored in each node * @author Paul Campbell
* *
* @author pcampbell * @param <T> the type of data stored in each node
*/ */
abstract class AbstractNodeItem<T> implements Node<T> { abstract class AbstractNodeItem<T> implements Node<T> {
@ -65,10 +67,7 @@ abstract class AbstractNodeItem<T> implements Node<T> {
* @return an {@link Optional} containing the child node if found * @return an {@link Optional} containing the child node if found
*/ */
@Override @Override
public Optional<Node<T>> findChild(final T child) { public Optional<Node<T>> findChild(@NonNull final T child) {
if (child == null) {
throw new NullPointerException("child");
}
return children.stream().filter(node -> { return children.stream().filter(node -> {
final Optional<T> d = node.getData(); final Optional<T> d = node.getData();
return d.isPresent() && d.get().equals(child); return d.isPresent() && d.get().equals(child);
@ -102,27 +101,25 @@ abstract class AbstractNodeItem<T> implements Node<T> {
* @return the child or null * @return the child or null
*/ */
@Override @Override
public Optional<Node<T>> findInPath(final List<T> path) { public Optional<Node<T>> findInPath(@NonNull final List<T> path) {
if (path == null) { if (path.isEmpty()) {
throw new NullPointerException("path"); return Optional.empty();
} }
if (path.size() > 0) { Node<T> current = this;
Optional<Node<T>> found = findChild(path.get(0)); for (T item : path) {
if (found.isPresent()) { final Optional<Node<T>> child = current.findChild(item);
if (path.size() > 1) { if (child.isPresent()) {
return found.get().findInPath(path.subList(1, path.size())); current = child.get();
} } else {
return found; current = null;
break;
} }
} }
return Optional.empty(); return Optional.ofNullable(current);
} }
@Override @Override
public Optional<Node<T>> findChildByName(final String named) { public Optional<Node<T>> findChildByName(@NonNull final String named) {
if (named == null) {
throw new NullPointerException("name");
}
return children.stream() return children.stream()
.filter(n -> n.getName().equals(named)) .filter(n -> n.getName().equals(named))
.findAny(); .findAny();
@ -139,17 +136,18 @@ abstract class AbstractNodeItem<T> implements Node<T> {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final String unnamed = "(unnamed)"; final String unnamed = "(unnamed)";
if (isNamed()) { if (isNamed()) {
sb.append(String.format("[%1$" + (depth + name.length()) + "s]\n", sb.append(formatByDepth(name, depth));
name));
} else if (!children.isEmpty()) { } else if (!children.isEmpty()) {
sb.append( sb.append(formatByDepth(unnamed, depth));
String.format("[%1$" + (depth + unnamed.length()) + "s]\n",
unnamed));
} }
getChildren().forEach(c -> sb.append(c.drawTree(depth + 1))); getChildren().forEach(c -> sb.append(c.drawTree(depth + 1)));
return sb.toString(); return sb.toString();
} }
private String formatByDepth(final String value, final int depth) {
return String.format("[%1$" + (depth + value.length()) + "s]\n", value);
}
@Override @Override
public boolean isNamed() { public boolean isNamed() {
return name != null && name.length() > 0; return name != null && name.length() > 0;

View file

@ -11,9 +11,9 @@ import java.util.Set;
* getData()} they could then modify the original data within the node. This * getData()} they could then modify the original data within the node. This
* wouldn't affect the integrity of the node tree structure, however.</p> * wouldn't affect the integrity of the node tree structure, however.</p>
* *
* @param <T> the type of data stored in each node * @author Paul Campbell
* *
* @author pcampbell * @param <T> the type of data stored in each node
*/ */
final class ImmutableNodeItem<T> extends AbstractNodeItem<T> { final class ImmutableNodeItem<T> extends AbstractNodeItem<T> {

View file

@ -7,9 +7,9 @@ import java.util.Set;
/** /**
* An interface for tree node items. * An interface for tree node items.
* *
* @param <T> the type of data held in each node * @author Paul Campbell
* *
* @author pcampbell * @param <T> the type of data held in each node
*/ */
public interface Node<T> { public interface Node<T> {
@ -113,6 +113,9 @@ public interface Node<T> {
* @param child the child's data to search or create with * @param child the child's data to search or create with
* *
* @return the found or created child node * @return the found or created child node
*
* @deprecated use node.findChild(child).orElseGet(() ->
* node.createChild(child));
*/ */
@Deprecated @Deprecated
Node<T> findOrCreateChild(T child); Node<T> findOrCreateChild(T child);

View file

@ -1,18 +1,20 @@
package net.kemitix.node; package net.kemitix.node;
import lombok.NonNull;
import lombok.val;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
/** /**
* Represents a tree of nodes. * Represents a tree of nodes.
* *
* @param <T> the type of data stored in each node * @author Paul Campbell
* *
* @author pcampbell * @param <T> the type of data stored in each node
*/ */
class NodeItem<T> implements Node<T> { class NodeItem<T> implements Node<T> {
@ -20,8 +22,6 @@ class NodeItem<T> implements Node<T> {
private final Set<Node<T>> children = new HashSet<>(); private final Set<Node<T>> children = new HashSet<>();
private Function<Node<T>, String> nameSupplier;
private Node<T> parent; private Node<T> parent;
private String name; private String name;
@ -44,7 +44,6 @@ class NodeItem<T> implements Node<T> {
*/ */
NodeItem(final T data) { NodeItem(final T data) {
this.data = data; this.data = data;
this.nameSupplier = (n) -> null;
} }
/** /**
@ -71,24 +70,8 @@ class NodeItem<T> implements Node<T> {
setParent(parent); setParent(parent);
} }
private String generateName() {
return getNameSupplier().apply(this);
}
private Function<Node<T>, String> getNameSupplier() {
if (nameSupplier != null) {
return nameSupplier;
}
// no test for parent as root nodes will always have a default name
// supplier
return ((NodeItem<T>) parent).getNameSupplier();
}
@Override @Override
public String getName() { public String getName() {
if (name == null) {
return generateName();
}
return name; return name;
} }
@ -128,32 +111,35 @@ class NodeItem<T> implements Node<T> {
* @param child the node to add * @param child the node to add
*/ */
@Override @Override
public void addChild(final Node<T> child) { public void addChild(@NonNull final Node<T> child) {
if (child == null) { verifyChildIsNotAnAncestor(child);
throw new NullPointerException("child"); verifyChildWithSameNameDoesNotAlreadyExist(child);
}
if (this.equals(child) || isDescendantOf(child)) {
throw new NodeException("Child is an ancestor");
}
if (child.isNamed()) {
final Optional<Node<T>> existingChild = findChildByName(
child.getName());
if (existingChild.isPresent() && existingChild.get() != child) {
throw new NodeException(
"Node with that name already exists here");
}
}
children.add(child); children.add(child);
// update the child's parent if they don't have one or it is not this // update the child's parent if they don't have one or it is not this
Optional<Node<T>> childParent = child.getParent(); val childParent = child.getParent();
boolean isOrphan = !childParent.isPresent(); if (!childParent.isPresent() || !childParent.get().equals(this)) {
boolean hasDifferentParent = !isOrphan && !childParent.get()
.equals(this);
if (isOrphan || hasDifferentParent) {
child.setParent(this); child.setParent(this);
} }
} }
private void verifyChildWithSameNameDoesNotAlreadyExist(
final @NonNull Node<T> child) {
if (child.isNamed()) {
findChildByName(child.getName())
.filter(existingChild -> existingChild != child)
.ifPresent(existingChild -> {
throw new NodeException(
"Node with that name already exists here");
});
}
}
private void verifyChildIsNotAnAncestor(final @NonNull Node<T> child) {
if (this.equals(child) || isDescendantOf(child)) {
throw new NodeException("Child is an ancestor");
}
}
/** /**
* Creates a new node and adds it as a child of the current node. * Creates a new node and adds it as a child of the current node.
* *
@ -162,10 +148,7 @@ class NodeItem<T> implements Node<T> {
* @return the new child node * @return the new child node
*/ */
@Override @Override
public Node<T> createChild(final T child) { public Node<T> createChild(@NonNull final T child) {
if (child == null) {
throw new NullPointerException("child");
}
return new NodeItem<>(child, this); return new NodeItem<>(child, this);
} }
@ -184,10 +167,7 @@ class NodeItem<T> implements Node<T> {
* @param descendants the line of descendants from the current node * @param descendants the line of descendants from the current node
*/ */
@Override @Override
public void createDescendantLine(final List<T> descendants) { public void createDescendantLine(@NonNull final List<T> descendants) {
if (descendants == null) {
throw new NullPointerException("descendants");
}
if (!descendants.isEmpty()) { if (!descendants.isEmpty()) {
findOrCreateChild(descendants.get(0)).createDescendantLine( findOrCreateChild(descendants.get(0)).createDescendantLine(
descendants.subList(1, descendants.size())); descendants.subList(1, descendants.size()));
@ -201,13 +181,13 @@ class NodeItem<T> implements Node<T> {
* @param child the child's data to search or create with * @param child the child's data to search or create with
* *
* @return the found or created child node * @return the found or created child node
*
* @deprecated use node.findChild(child).orElseGet(() -> node.createChild
* (child));
*/ */
@Override @Override
@Deprecated @Deprecated
public Node<T> findOrCreateChild(final T child) { public Node<T> findOrCreateChild(@NonNull final T child) {
if (child == null) {
throw new NullPointerException("child");
}
return findChild(child).orElseGet(() -> createChild(child)); return findChild(child).orElseGet(() -> createChild(child));
} }
@ -219,10 +199,7 @@ class NodeItem<T> implements Node<T> {
* @return an {@link Optional} containing the child node if found * @return an {@link Optional} containing the child node if found
*/ */
@Override @Override
public Optional<Node<T>> findChild(final T child) { public Optional<Node<T>> findChild(@NonNull final T child) {
if (child == null) {
throw new NullPointerException("child");
}
return children.stream().filter(node -> { return children.stream().filter(node -> {
final Optional<T> d = node.getData(); final Optional<T> d = node.getData();
return d.isPresent() && d.get().equals(child); return d.isPresent() && d.get().equals(child);
@ -257,10 +234,7 @@ class NodeItem<T> implements Node<T> {
* @param parent the new parent node * @param parent the new parent node
*/ */
@Override @Override
public final void setParent(final Node<T> parent) { public final void setParent(@NonNull final Node<T> parent) {
if (parent == null) {
throw new NullPointerException("parent");
}
if (this.equals(parent) || parent.isDescendantOf(this)) { if (this.equals(parent) || parent.isDescendantOf(this)) {
throw new NodeException("Parent is a descendant"); throw new NodeException("Parent is a descendant");
} }
@ -279,64 +253,68 @@ class NodeItem<T> implements Node<T> {
* @return the child or null * @return the child or null
*/ */
@Override @Override
public Optional<Node<T>> findInPath(final List<T> path) { public Optional<Node<T>> findInPath(@NonNull final List<T> path) {
if (path == null) { if (path.isEmpty()) {
throw new NullPointerException("path"); return Optional.empty();
} }
if (path.size() > 0) { Node<T> current = this;
Optional<Node<T>> found = findChild(path.get(0)); for (T item : path) {
if (found.isPresent()) { final Optional<Node<T>> child = current.findChild(item);
if (path.size() > 1) { if (child.isPresent()) {
return found.get().findInPath(path.subList(1, path.size())); current = child.get();
} } else {
return found; current = null;
break;
} }
} }
return Optional.empty(); return Optional.ofNullable(current);
} }
@Override @Override
public void insertInPath(final Node<T> nodeItem, final String... path) { public void insertInPath(final Node<T> nodeItem, final String... path) {
if (path.length == 0) { if (path.length == 0) {
if (!nodeItem.isNamed()) { // nothing to conflict with insertChild(nodeItem);
addChild(nodeItem);
return;
}
String nodeName = nodeItem.getName();
final Optional<Node<T>> childNamed = findChildByName(nodeName);
if (!childNamed.isPresent()) { // nothing with the same name exists
addChild(nodeItem);
return;
}
// we have an existing node with the same name
final Node<T> existing = childNamed.get();
if (!existing.isEmpty()) {
throw new NodeException("A non-empty node named '" + nodeName
+ "' already exists here");
} else {
nodeItem.getData().ifPresent(existing::setData);
}
return;
}
String item = path[0];
final Optional<Node<T>> childNamed = findChildByName(item);
Node<T> child;
if (!childNamed.isPresent()) {
child = new NodeItem<>(null, item, this);
} else { } else {
child = childNamed.get(); val item = path[0];
findChildByName(item)
.orElseGet(() -> new NodeItem<>(null, item, this))
.insertInPath(nodeItem,
Arrays.copyOfRange(path, 1, path.length));
}
}
private void insertChild(final Node<T> nodeItem) {
if (nodeItem.isNamed()) {
insertNamedChild(nodeItem);
} else {
// nothing to conflict with
addChild(nodeItem);
}
}
private void insertNamedChild(final Node<T> nodeItem) {
val childByName = findChildByName(nodeItem.getName());
if (childByName.isPresent()) {
// we have an existing node with the same name
val existing = childByName.get();
if (existing.isEmpty()) {
// place any data in the new node into the existing empty node
nodeItem.getData().ifPresent(existing::setData);
} else {
throw new NodeException("A non-empty node named '"
+ nodeItem.getName() + "' already exists here");
}
} else {
// nothing with the same name exists
addChild(nodeItem);
} }
child.insertInPath(nodeItem, Arrays.copyOfRange(path, 1, path.length));
} }
@Override @Override
public Optional<Node<T>> findChildByName(final String named) { public Optional<Node<T>> findChildByName(@NonNull final String named) {
if (named == null) {
throw new NullPointerException("name");
}
return children.stream() return children.stream()
.filter((Node<T> t) -> t.getName().equals(named)) .filter((Node<T> t) -> t.getName().equals(named))
.findAny(); .findAny();
} }
@Override @Override
@ -353,17 +331,18 @@ class NodeItem<T> implements Node<T> {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final String unnamed = "(unnamed)"; final String unnamed = "(unnamed)";
if (isNamed()) { if (isNamed()) {
sb.append(String.format("[%1$" + (depth + name.length()) + "s]\n", sb.append(formatByDepth(name, depth));
name));
} else if (!children.isEmpty()) { } else if (!children.isEmpty()) {
sb.append( sb.append(formatByDepth(unnamed, depth));
String.format("[%1$" + (depth + unnamed.length()) + "s]\n",
unnamed));
} }
getChildren().stream().forEach(c -> sb.append(c.drawTree(depth + 1))); getChildren().forEach(c -> sb.append(c.drawTree(depth + 1)));
return sb.toString(); return sb.toString();
} }
private String formatByDepth(final String value, final int depth) {
return String.format("[%1$" + (depth + value.length()) + "s]\n", value);
}
@Override @Override
public boolean isNamed() { public boolean isNamed() {
String currentName = getName(); String currentName = getName();
@ -381,14 +360,8 @@ class NodeItem<T> implements Node<T> {
public void removeParent() { public void removeParent() {
if (parent != null) { if (parent != null) {
Node<T> oldParent = parent; Node<T> oldParent = parent;
Function<Node<T>, String> supplier = getNameSupplier();
parent = null; parent = null;
oldParent.removeChild(this); oldParent.removeChild(this);
if (this.nameSupplier == null) {
// this is now a root node, so must provide a default name
// supplier
this.nameSupplier = supplier;
}
} }
} }

View file

@ -4,14 +4,15 @@ import lombok.val;
import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.SoftAssertions;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
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 static org.assertj.core.api.Assertions.assertThat;
/** /**
* Test for {@link ImmutableNodeItem}. * Test for {@link ImmutableNodeItem}.
* *
@ -141,6 +142,7 @@ public class ImmutableNodeItemTest {
* Test that we can walk a tree to the target node. * Test that we can walk a tree to the target node.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldWalkTreeToNode() { public void shouldWalkTreeToNode() {
//given //given
val root = Nodes.unnamedRoot("root"); val root = Nodes.unnamedRoot("root");
@ -160,6 +162,7 @@ public class ImmutableNodeItemTest {
* doesn't exist. * doesn't exist.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldNotFindNonExistentChildNode() { public void shouldNotFindNonExistentChildNode() {
//given //given
val root = Nodes.unnamedRoot("root"); val root = Nodes.unnamedRoot("root");
@ -176,6 +179,7 @@ public class ImmutableNodeItemTest {
* Test that when we pass null we get an exception. * Test that when we pass null we get an exception.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldThrowNEWhenWalkTreeNull() { public void shouldThrowNEWhenWalkTreeNull() {
//given //given
immutableNode = Nodes.asImmutable(Nodes.unnamedRoot("subject")); immutableNode = Nodes.asImmutable(Nodes.unnamedRoot("subject"));
@ -190,6 +194,7 @@ public class ImmutableNodeItemTest {
* a result. * a result.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldReturnEmptyForEmptyWalkTreePath() { public void shouldReturnEmptyForEmptyWalkTreePath() {
//given //given
immutableNode = Nodes.asImmutable(Nodes.unnamedRoot("subject")); immutableNode = Nodes.asImmutable(Nodes.unnamedRoot("subject"));

View file

@ -0,0 +1,9 @@
package net.kemitix.node;
/**
* Category marker for tests relating to implementations of Node.findInPath(...).
*
* @author Paul Campbell
*/
public interface NodeFindInPathTestsCategory {
}

View file

@ -4,14 +4,15 @@ import lombok.val;
import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.SoftAssertions;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
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 static org.assertj.core.api.Assertions.assertThat;
/** /**
* Test for {@link NodeItem}. * Test for {@link NodeItem}.
* *
@ -309,6 +310,7 @@ public class NodeItemTest {
* Test that we can walk a tree to the target node. * Test that we can walk a tree to the target node.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldWalkTreeToNode() { public void shouldWalkTreeToNode() {
//given //given
val grandparent = "grandparent"; val grandparent = "grandparent";
@ -334,6 +336,7 @@ public class NodeItemTest {
* doesn't exist. * doesn't exist.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldNotFindNonExistentChildNode() { public void shouldNotFindNonExistentChildNode() {
//given //given
val parent = "parent"; val parent = "parent";
@ -352,6 +355,7 @@ public class NodeItemTest {
* Test that when we pass null we get an exception. * Test that when we pass null we get an exception.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldThrowNEWhenWalkTreeNull() { public void shouldThrowNEWhenWalkTreeNull() {
//given //given
node = Nodes.unnamedRoot("subject"); node = Nodes.unnamedRoot("subject");
@ -366,6 +370,7 @@ public class NodeItemTest {
* a result. * a result.
*/ */
@Test @Test
@Category(NodeFindInPathTestsCategory.class)
public void shouldReturnEmptyForEmptyWalkTreePath() { public void shouldReturnEmptyForEmptyWalkTreePath() {
//given //given
node = Nodes.unnamedRoot("subject"); node = Nodes.unnamedRoot("subject");