Skip to content

Commit dc064d6

Browse files
committed
code comments
1 parent 65749bd commit dc064d6

File tree

1 file changed

+196
-189
lines changed

1 file changed

+196
-189
lines changed
Lines changed: 196 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -1,189 +1,196 @@
1-
package example;
2-
3-
import static java.util.stream.Collectors.toList;
4-
import static org.apache.commons.lang3.StringUtils.rightPad;
5-
import static org.junit.Assert.assertEquals;
6-
import static org.junit.Assert.assertTrue;
7-
8-
import java.math.BigDecimal;
9-
import java.util.List;
10-
import java.util.function.Consumer;
11-
import java.util.function.Function;
12-
import java.util.stream.Collectors;
13-
import java.util.stream.Stream;
14-
15-
import org.junit.Test;
16-
17-
import example.genericJ8.ExtendedTreeNode;
18-
import example.genericJ8.TreePathUtil;
19-
import example.genericJ8.TreeUtil_2_GenericJava8;
20-
import example.simple.TreeUtilSimple;
21-
22-
public class TreeTest {
23-
24-
@Test
25-
public void test() {
26-
27-
// ----------------
28-
// Build tree
29-
// ----------------
30-
31-
TreeNode<ExampleData> tree = new TreeNode<ExampleData>(new ExampleData("root", 0));
32-
tree.addChild(new ExampleData("plants", 1));
33-
34-
tree.getChildren().get(0).addChild(new ExampleData("tree", 548));
35-
tree.getChildren().get(0).getChildren().get(0).addChild(new ExampleData("birch tree", 123));
36-
tree.getChildren().get(0).getChildren().get(0).addChild(new ExampleData("oak tree", 5));
37-
38-
tree.getChildren().get(0).addChild(new ExampleData("flower", 567));
39-
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("sun flower", 3));
40-
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("amaryllis", 9));
41-
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("begonia", 2));
42-
43-
tree.addChild(new ExampleData("animals", 2));
44-
tree.getChildren().get(1).addChild(new ExampleData("lion", 345));
45-
tree.getChildren().get(1).addChild(new ExampleData("monkey", 239));
46-
47-
// ----------------
48-
// Print tree
49-
// ----------------
50-
51-
System.out.println("------------------------------------------------");
52-
System.out.println("-- simple version");
53-
System.out.println("------------------------------------------------");
54-
System.out.println(TreeUtilSimple.printTree(tree));
55-
56-
// Ok, but what if I want another attribute than name or several attributes?
57-
// The simple version cannot easily be converted to a generic one,
58-
// because it has hard access to ExampleData#getName().
59-
// Furthermore it has hard coded system dependent line break "\n".
60-
61-
System.out.println("------------------------------------------------");
62-
System.out.println("-- advanced version with Generics and Java 8");
63-
System.out.println("------------------------------------------------");
64-
65-
// output tree using name attribute
66-
System.out.println(TreeUtil_2_GenericJava8.printTree(tree, d -> String.valueOf(d.getData().getName()) + "\n"));
67-
68-
// output tree using num attribute
69-
System.out.println(TreeUtil_2_GenericJava8.printTree(tree, d -> String.valueOf(d.getData().getNum()) + "\n"));
70-
71-
System.out.println("------------------------------------------------");
72-
System.out.println("-- advanced version with tree path");
73-
System.out.println("------------------------------------------------");
74-
75-
System.out.println(TreeUtil_2_GenericJava8.printTree(tree,
76-
d -> rightPad(d.getData().getName(), 20) //
77-
+ rightPad(String.valueOf(d.getData().getNum()), 20) //
78-
+ rightPad(String.valueOf(d.getData().getFoo()), 20) //
79-
+ TreePathUtil.getTreePath(d, ExampleData::getName, " / ") + "\n"));
80-
81-
System.out.println("------------------------------------------------");
82-
System.out.println("-- some asserts");
83-
System.out.println("------------------------------------------------");
84-
85-
// Passing extractor functions around helps also in testing:
86-
// We can easily sum over any numeric attribute.
87-
// Stream API helps to easily select and filter tree.
88-
89-
// Some asserts summing attributes
90-
List<TreeNode<ExampleData>> level1 = nextLevelStream(tree).collect(Collectors.toList());
91-
assertEquals(new BigDecimal("3"), calculateSum(level1, d -> BigDecimal.valueOf(d.getData().getNum())));
92-
assertEquals(new BigDecimal("30"), calculateSum(level1, d -> d.getData().getFoo()));
93-
94-
// Assert counting on one level of the tree
95-
System.out.println();
96-
assertEquals(4,
97-
level2Stream(tree)
98-
// peek for debug output...
99-
.peek(printName()) //
100-
.count());
101-
102-
// Asserting that there are only the given values as names on level 2
103-
System.out.println();
104-
assertAllowedVals(
105-
level2Stream(tree)
106-
// peek for debug only
107-
.peek(printName()) //
108-
.collect(Collectors.toList()),
109-
n -> n.getData().getName(),
110-
// allowed names on level 2
111-
"tree", "flower", "lion", "monkey");
112-
113-
// same but letting it fail for demo purpose
114-
System.out.println();
115-
try {
116-
assertAllowedVals(
117-
level2Stream(tree)
118-
// peek for debug only
119-
.peek(printName()) //
120-
.collect(Collectors.toList()),
121-
n -> n.getData().getName(),
122-
// allowed names on level 2
123-
"tree", "flower", "foo", "bar");
124-
} catch (AssertionError e) {
125-
// ignore
126-
System.out.println(e.getMessage());
127-
}
128-
129-
// Assert counting on one level of the tree
130-
System.out.println();
131-
assertEquals(5,
132-
level3Stream(tree)
133-
// peek for debug output...
134-
.peek(printName()) //
135-
.count());
136-
137-
System.out.println("\nall values in the tree:");
138-
flattenedStream(tree).map(ExampleData::getName).forEach(System.out::println);
139-
140-
assertEquals(new BigDecimal("1844"),
141-
calculateSum(
142-
flattenedStream(tree)
143-
// for debug only
144-
.peek(r -> System.out.println(r.getNum())) //
145-
// collect
146-
.collect(toList()),
147-
// extract (method reference better than lambda because more explicit, type is visible)
148-
ExampleData::getNumAsBigDecimal));
149-
150-
}
151-
152-
private Stream<ExampleData> flattenedStream(TreeNode<ExampleData> tree) {
153-
return new ExtendedTreeNode<ExampleData>(tree).flattened().map(TreeNode::getData);
154-
}
155-
156-
private Consumer<? super TreeNode<ExampleData>> printName() {
157-
return n -> System.out.println(n.getData().getName());
158-
}
159-
160-
private Stream<TreeNode<ExampleData>> level3Stream(TreeNode<ExampleData> tree) {
161-
return level2Stream(tree).flatMap(l2 -> nextLevelStream(l2));
162-
}
163-
164-
private Stream<TreeNode<ExampleData>> level2Stream(TreeNode<ExampleData> tree) {
165-
return nextLevelStream(tree).flatMap(l1 -> nextLevelStream(l1));
166-
}
167-
168-
private Stream<TreeNode<ExampleData>> nextLevelStream(TreeNode<ExampleData> tree) {
169-
return tree.getChildren().stream();
170-
}
171-
172-
public static <T> BigDecimal calculateSum(final List<T> result,
173-
final Function<? super T, BigDecimal> colExtracter) {
174-
return result.stream().map(colExtracter)
175-
// Ignore null values
176-
.filter(col -> col != null)
177-
// Summing BigDecimal
178-
.reduce(BigDecimal.ZERO, BigDecimal::add);
179-
}
180-
181-
public <T> void assertAllowedVals(final List<T> result, final Function<? super T, ? extends String> colExtracter,
182-
final String... allowedVals) {
183-
// Value must match any of the allowed values
184-
result.stream().map(colExtracter)
185-
.forEach(value -> assertTrue(String.format("value \"%s\" does not match allowed values", value),
186-
Stream.of(allowedVals).anyMatch(allowed -> allowed.equals(value))));
187-
}
188-
189-
}
1+
package example;
2+
3+
import static java.util.stream.Collectors.toList;
4+
import static org.apache.commons.lang3.StringUtils.rightPad;
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertTrue;
7+
8+
import java.math.BigDecimal;
9+
import java.util.List;
10+
import java.util.function.Consumer;
11+
import java.util.function.Function;
12+
import java.util.stream.Collectors;
13+
import java.util.stream.Stream;
14+
15+
import org.junit.Test;
16+
17+
import example.genericJ8.ExtendedTreeNode;
18+
import example.genericJ8.TreePathUtil;
19+
import example.genericJ8.TreeUtil_2_GenericJava8;
20+
import example.simple.TreeUtilSimple;
21+
22+
public class TreeTest {
23+
24+
@Test
25+
public void test() {
26+
27+
// ----------------
28+
// Build tree
29+
// ----------------
30+
31+
TreeNode<ExampleData> tree = new TreeNode<ExampleData>(new ExampleData("root", 0));
32+
tree.addChild(new ExampleData("plants", 1));
33+
34+
tree.getChildren().get(0).addChild(new ExampleData("tree", 548));
35+
tree.getChildren().get(0).getChildren().get(0).addChild(new ExampleData("birch tree", 123));
36+
tree.getChildren().get(0).getChildren().get(0).addChild(new ExampleData("oak tree", 5));
37+
38+
tree.getChildren().get(0).addChild(new ExampleData("flower", 567));
39+
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("sun flower", 3));
40+
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("amaryllis", 9));
41+
tree.getChildren().get(0).getChildren().get(1).addChild(new ExampleData("begonia", 2));
42+
43+
tree.addChild(new ExampleData("animals", 2));
44+
tree.getChildren().get(1).addChild(new ExampleData("lion", 345));
45+
tree.getChildren().get(1).addChild(new ExampleData("monkey", 239));
46+
47+
// ----------------
48+
// Print tree
49+
// ----------------
50+
51+
System.out.println("------------------------------------------------");
52+
System.out.println("-- simple version");
53+
System.out.println("------------------------------------------------");
54+
System.out.println(TreeUtilSimple.printTree(tree));
55+
56+
// Ok, but what if I want another attribute than name or several attributes?
57+
// The simple version cannot easily be converted to a generic one,
58+
// because it has hard access to ExampleData#getName().
59+
// Furthermore it has hard coded system dependent line break "\n".
60+
61+
System.out.println("------------------------------------------------");
62+
System.out.println("-- advanced version with Generics and Java 8");
63+
System.out.println("------------------------------------------------");
64+
65+
// output tree using name attribute
66+
System.out.println(TreeUtil_2_GenericJava8.printTree(tree, d -> String.valueOf(d.getData().getName()) + "\n"));
67+
68+
// output tree using num attribute
69+
System.out.println(TreeUtil_2_GenericJava8.printTree(tree, d -> String.valueOf(d.getData().getNum()) + "\n"));
70+
71+
System.out.println("------------------------------------------------");
72+
System.out.println("-- advanced version with tree path");
73+
System.out.println("------------------------------------------------");
74+
75+
System.out.println(TreeUtil_2_GenericJava8.printTree(tree,
76+
d -> rightPad(d.getData().getName(), 20) //
77+
+ rightPad(String.valueOf(d.getData().getNum()), 20) //
78+
+ rightPad(String.valueOf(d.getData().getFoo()), 20) //
79+
+ TreePathUtil.getTreePath(d, ExampleData::getName, " / ") + "\n"));
80+
81+
System.out.println("------------------------------------------------");
82+
System.out.println("-- some asserts");
83+
System.out.println("------------------------------------------------");
84+
85+
// Passing extractor functions around helps also in testing:
86+
// We can easily sum over any numeric attribute.
87+
// Stream API helps to easily select and filter tree.
88+
89+
// Some asserts summing attributes
90+
List<TreeNode<ExampleData>> level1 = nextLevelStream(tree).collect(Collectors.toList());
91+
assertEquals(new BigDecimal("3"), calculateSum(level1, d -> BigDecimal.valueOf(d.getData().getNum())));
92+
assertEquals(new BigDecimal("30"), calculateSum(level1, d -> d.getData().getFoo()));
93+
94+
// Assert counting on one level of the tree
95+
System.out.println();
96+
assertEquals(4,
97+
level2Stream(tree)
98+
// peek for debug output...
99+
.peek(printName()) //
100+
.count());
101+
102+
// Asserting that there are only the given values as names on level 2
103+
System.out.println();
104+
assertAllowedVals(
105+
level2Stream(tree)
106+
// peek for debug only
107+
.peek(printName()) //
108+
.collect(Collectors.toList()),
109+
n -> n.getData().getName(),
110+
// allowed names on level 2
111+
"tree", "flower", "lion", "monkey");
112+
113+
// same but letting it fail for demo purpose
114+
System.out.println();
115+
try {
116+
assertAllowedVals(
117+
level2Stream(tree)
118+
// peek for debug only
119+
.peek(printName()) //
120+
.collect(Collectors.toList()),
121+
n -> n.getData().getName(),
122+
// allowed names on level 2
123+
"tree", "flower", "foo", "bar");
124+
} catch (AssertionError e) {
125+
// ignore
126+
System.out.println(e.getMessage());
127+
}
128+
129+
// Assert counting on one level of the tree
130+
System.out.println();
131+
assertEquals(5,
132+
level3Stream(tree)
133+
// peek for debug output...
134+
.peek(printName()) //
135+
.count());
136+
137+
// Flattened tree using streams and recursion
138+
System.out.println("\nall values in the tree:");
139+
flattenedStream(tree).map(ExampleData::getName).forEach(System.out::println);
140+
141+
assertEquals(new BigDecimal("1844"),
142+
calculateSum(
143+
flattenedStream(tree)
144+
// for debug only
145+
.peek(r -> System.out.println(r.getNum())) //
146+
// collect
147+
.collect(toList()),
148+
// extract (method reference better than lambda because more explicit, type is visible)
149+
ExampleData::getNumAsBigDecimal));
150+
151+
}
152+
153+
private Stream<ExampleData> flattenedStream(TreeNode<ExampleData> tree) {
154+
return
155+
// extending tree node by flatten functionality
156+
new ExtendedTreeNode<ExampleData>(tree)
157+
// flatten
158+
.flattened()
159+
// extract data from node
160+
.map(TreeNode::getData);
161+
}
162+
163+
private Consumer<? super TreeNode<ExampleData>> printName() {
164+
return n -> System.out.println(n.getData().getName());
165+
}
166+
167+
private Stream<TreeNode<ExampleData>> level3Stream(TreeNode<ExampleData> tree) {
168+
return level2Stream(tree).flatMap(l2 -> nextLevelStream(l2));
169+
}
170+
171+
private Stream<TreeNode<ExampleData>> level2Stream(TreeNode<ExampleData> tree) {
172+
return nextLevelStream(tree).flatMap(l1 -> nextLevelStream(l1));
173+
}
174+
175+
private Stream<TreeNode<ExampleData>> nextLevelStream(TreeNode<ExampleData> tree) {
176+
return tree.getChildren().stream();
177+
}
178+
179+
public static <T> BigDecimal calculateSum(final List<T> result,
180+
final Function<? super T, BigDecimal> colExtracter) {
181+
return result.stream().map(colExtracter)
182+
// Ignore null values
183+
.filter(col -> col != null)
184+
// Summing BigDecimal
185+
.reduce(BigDecimal.ZERO, BigDecimal::add);
186+
}
187+
188+
public <T> void assertAllowedVals(final List<T> result, final Function<? super T, ? extends String> colExtracter,
189+
final String... allowedVals) {
190+
// Value must match any of the allowed values
191+
result.stream().map(colExtracter)
192+
.forEach(value -> assertTrue(String.format("value \"%s\" does not match allowed values", value),
193+
Stream.of(allowedVals).anyMatch(allowed -> allowed.equals(value))));
194+
}
195+
196+
}

0 commit comments

Comments
 (0)