You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HierarchyMapperWithDataTest.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. package com.vaadin.data.provider.hierarchical;
  2. import static org.junit.Assert.assertEquals;
  3. import static org.junit.Assert.assertTrue;
  4. import java.util.ArrayList;
  5. import java.util.Comparator;
  6. import java.util.List;
  7. import java.util.Objects;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.IntStream;
  10. import java.util.stream.Stream;
  11. import org.junit.Before;
  12. import org.junit.BeforeClass;
  13. import org.junit.Test;
  14. import com.vaadin.data.TreeData;
  15. import com.vaadin.data.provider.HierarchyMapper;
  16. import com.vaadin.data.provider.TreeDataProvider;
  17. import com.vaadin.server.SerializablePredicate;
  18. import com.vaadin.shared.Range;
  19. public class HierarchyMapperWithDataTest {
  20. private static final int ROOT_COUNT = 5;
  21. private static final int PARENT_COUNT = 4;
  22. private static final int LEAF_COUNT = 2;
  23. private static TreeData<Node> data = new TreeData<>();
  24. private TreeDataProvider<Node> provider;
  25. private HierarchyMapper<Node, SerializablePredicate<Node>> mapper;
  26. private static List<Node> testData;
  27. private static List<Node> roots;
  28. private int mapSize = ROOT_COUNT;
  29. @BeforeClass
  30. public static void setupData() {
  31. testData = generateTestData(ROOT_COUNT, PARENT_COUNT, LEAF_COUNT);
  32. roots = testData.stream().filter(item -> item.getParent() == null)
  33. .collect(Collectors.toList());
  34. data.addItems(roots,
  35. parent -> testData.stream().filter(
  36. item -> Objects.equals(item.getParent(), parent))
  37. .collect(Collectors.toList()));
  38. }
  39. @Before
  40. public void setup() {
  41. provider = new TreeDataProvider<>(data);
  42. mapper = new HierarchyMapper<>(provider);
  43. }
  44. @Test
  45. public void expandRootNode() {
  46. assertEquals("Map size should be equal to root node count", ROOT_COUNT,
  47. mapper.getTreeSize());
  48. expand(testData.get(0));
  49. assertEquals("Should be root count + once parent count",
  50. ROOT_COUNT + PARENT_COUNT, mapper.getTreeSize());
  51. checkMapSize();
  52. }
  53. @Test
  54. public void expandAndCollapseLastRootNode() {
  55. assertEquals("Map size should be equal to root node count", ROOT_COUNT,
  56. mapper.getTreeSize());
  57. expand(roots.get(roots.size() - 1));
  58. assertEquals("Should be root count + once parent count",
  59. ROOT_COUNT + PARENT_COUNT, mapper.getTreeSize());
  60. checkMapSize();
  61. collapse(roots.get(roots.size() - 1));
  62. assertEquals("Map size should be equal to root node count again",
  63. ROOT_COUNT, mapper.getTreeSize());
  64. checkMapSize();
  65. }
  66. @Test
  67. public void expandHiddenNode() {
  68. assertEquals("Map size should be equal to root node count", ROOT_COUNT,
  69. mapper.getTreeSize());
  70. expand(testData.get(1));
  71. assertEquals("Map size should not change when expanding a hidden node",
  72. ROOT_COUNT, mapper.getTreeSize());
  73. checkMapSize();
  74. expand(roots.get(0));
  75. assertEquals("Hidden node should now be expanded as well",
  76. ROOT_COUNT + PARENT_COUNT + LEAF_COUNT, mapper.getTreeSize());
  77. checkMapSize();
  78. collapse(roots.get(0));
  79. assertEquals("Map size should be equal to root node count", ROOT_COUNT,
  80. mapper.getTreeSize());
  81. checkMapSize();
  82. }
  83. @Test
  84. public void expandLeafNode() {
  85. assertEquals("Map size should be equal to root node count", ROOT_COUNT,
  86. mapper.getTreeSize());
  87. expand(testData.get(0));
  88. expand(testData.get(1));
  89. assertEquals("Root and parent node expanded",
  90. ROOT_COUNT + PARENT_COUNT + LEAF_COUNT, mapper.getTreeSize());
  91. checkMapSize();
  92. expand(testData.get(2));
  93. assertEquals("Expanding a leaf node should have no effect",
  94. ROOT_COUNT + PARENT_COUNT + LEAF_COUNT, mapper.getTreeSize());
  95. checkMapSize();
  96. }
  97. @Test
  98. public void findParentIndexOfLeaf() {
  99. expand(testData.get(0));
  100. assertEquals("Could not find the root node of a parent",
  101. Integer.valueOf(0), mapper.getParentIndex(testData.get(1)));
  102. expand(testData.get(1));
  103. assertEquals("Could not find the parent of a leaf", Integer.valueOf(1),
  104. mapper.getParentIndex(testData.get(2)));
  105. }
  106. @Test
  107. public void fetchRangeOfRows() {
  108. expand(testData.get(0));
  109. expand(testData.get(1));
  110. List<Node> expectedResult = testData.stream()
  111. .filter(n -> roots.contains(n)
  112. || n.getParent().equals(testData.get(0))
  113. || n.getParent().equals(testData.get(1)))
  114. .collect(Collectors.toList());
  115. // Range containing deepest level of expanded nodes without their
  116. // parents in addition to root nodes at the end.
  117. Range range = Range.between(3, mapper.getTreeSize());
  118. verifyFetchIsCorrect(expectedResult, range);
  119. // Only the expanded two nodes, nothing more.
  120. range = Range.between(0, 2);
  121. verifyFetchIsCorrect(expectedResult, range);
  122. // Fetch everything
  123. range = Range.between(0, mapper.getTreeSize());
  124. verifyFetchIsCorrect(expectedResult, range);
  125. }
  126. @Test
  127. public void fetchRangeOfRowsWithSorting() {
  128. // Expand before sort
  129. expand(testData.get(0));
  130. expand(testData.get(1));
  131. // Construct a sorted version of test data with correct filters
  132. List<List<Node>> levels = new ArrayList<>();
  133. Comparator<Node> comparator = Comparator.comparing(Node::getNumber)
  134. .reversed();
  135. levels.add(testData.stream().filter(n -> n.getParent() == null)
  136. .sorted(comparator).collect(Collectors.toList()));
  137. levels.add(
  138. testData.stream().filter(n -> n.getParent() == testData.get(0))
  139. .sorted(comparator).collect(Collectors.toList()));
  140. levels.add(
  141. testData.stream().filter(n -> n.getParent() == testData.get(1))
  142. .sorted(comparator).collect(Collectors.toList()));
  143. List<Node> expectedResult = levels.get(0).stream().flatMap(root -> {
  144. Stream<Node> nextLevel = levels.get(1).stream()
  145. .filter(n -> n.getParent() == root)
  146. .flatMap(node -> Stream.concat(Stream.of(node),
  147. levels.get(2).stream()
  148. .filter(n -> n.getParent() == node)));
  149. return Stream.concat(Stream.of(root), nextLevel);
  150. }).collect(Collectors.toList());
  151. // Apply sorting
  152. mapper.setInMemorySorting(comparator::compare);
  153. // Range containing deepest level of expanded nodes without their
  154. // parents in addition to root nodes at the end.
  155. Range range = Range.between(8, mapper.getTreeSize());
  156. verifyFetchIsCorrect(expectedResult, range);
  157. // Only the root nodes, nothing more.
  158. range = Range.between(0, ROOT_COUNT);
  159. verifyFetchIsCorrect(expectedResult, range);
  160. // Fetch everything
  161. range = Range.between(0, mapper.getTreeSize());
  162. verifyFetchIsCorrect(expectedResult, range);
  163. }
  164. @Test
  165. public void fetchWithFilter() {
  166. expand(testData.get(0));
  167. Node expandedNode = testData.get(2 + LEAF_COUNT); // Expand second node
  168. expand(expandedNode);
  169. SerializablePredicate<Node> filter = n -> n.getNumber() % 2 == 0;
  170. // Root nodes plus children of expanded nodes 0 and 4 that match the
  171. // filter
  172. List<Node> expectedResult = IntStream
  173. .of(0, 1, 4, 6, 7, 10, 13, 26, 39, 52).mapToObj(testData::get)
  174. .collect(Collectors.toList());
  175. mapper.setFilter(filter);
  176. // Fetch everything
  177. Range range = Range.between(0, mapper.getTreeSize());
  178. verifyFetchIsCorrect(expectedResult, range);
  179. }
  180. private void expand(Node node) {
  181. insertRows(mapper.expand(node, mapper.getIndexOf(node).orElse(null)));
  182. }
  183. private void collapse(Node node) {
  184. removeRows(mapper.collapse(node, mapper.getIndexOf(node).orElse(null)));
  185. }
  186. private void verifyFetchIsCorrect(List<Node> expectedResult, Range range) {
  187. List<Node> collect = mapper.fetchItems(range)
  188. .collect(Collectors.toList());
  189. for (int i = 0; i < range.length(); ++i) {
  190. assertEquals("Unexpected fetch results.",
  191. expectedResult.get(i + range.getStart()), collect.get(i));
  192. }
  193. }
  194. static List<Node> generateTestData(int rootCount, int parentCount,
  195. int leafCount) {
  196. int nodeCounter = 0;
  197. List<Node> nodes = new ArrayList<>();
  198. for (int i = 0; i < rootCount; ++i) {
  199. Node root = new Node(nodeCounter++);
  200. nodes.add(root);
  201. for (int j = 0; j < parentCount; ++j) {
  202. Node parent = new Node(root, nodeCounter++);
  203. nodes.add(parent);
  204. for (int k = 0; k < leafCount; ++k) {
  205. nodes.add(new Node(parent, nodeCounter++));
  206. }
  207. }
  208. }
  209. return nodes;
  210. }
  211. private void checkMapSize() {
  212. assertEquals("Map size not properly updated", mapper.getTreeSize(),
  213. mapSize);
  214. }
  215. public void removeRows(Range range) {
  216. assertTrue("Index not in range",
  217. 0 <= range.getStart() && range.getStart() < mapSize);
  218. assertTrue("Removing more items than in map",
  219. range.getEnd() <= mapSize);
  220. mapSize -= range.length();
  221. }
  222. public void insertRows(Range range) {
  223. assertTrue("Index not in range",
  224. 0 <= range.getStart() && range.getStart() <= mapSize);
  225. mapSize += range.length();
  226. }
  227. }