HierarchyMapperWithDataTest.java (vaadin-flow-4.0.5) | : | HierarchyMapperWithDataTest.java (vaadin-flow-4.0.6) | ||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* | * | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | * License for the specific language governing permissions and limitations under | |||
* the License. | * the License. | |||
*/ | */ | |||
package com.vaadin.flow.data.provider.hierarchy; | package com.vaadin.flow.data.provider.hierarchy; | |||
import java.util.ArrayList; | import java.util.ArrayList; | |||
import java.util.Arrays; | ||||
import java.util.Collection; | ||||
import java.util.Collections; | ||||
import java.util.Comparator; | import java.util.Comparator; | |||
import java.util.HashSet; | ||||
import java.util.List; | import java.util.List; | |||
import java.util.Objects; | import java.util.Objects; | |||
import java.util.stream.Collectors; | import java.util.stream.Collectors; | |||
import java.util.stream.IntStream; | import java.util.stream.IntStream; | |||
import java.util.stream.Stream; | import java.util.stream.Stream; | |||
import org.junit.Assert; | ||||
import org.junit.Before; | import org.junit.Before; | |||
import org.junit.Rule; | ||||
import org.junit.Test; | import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | ||||
import com.vaadin.flow.function.SerializablePredicate; | import com.vaadin.flow.function.SerializablePredicate; | |||
import com.vaadin.flow.internal.Range; | import com.vaadin.flow.internal.Range; | |||
import static org.junit.Assert.assertEquals; | import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | import static org.junit.Assert.assertTrue; | |||
public class HierarchyMapperWithDataTest { | public class HierarchyMapperWithDataTest { | |||
private static final int ROOT_COUNT = 5; | private static final int ROOT_COUNT = 5; | |||
private static final int PARENT_COUNT = 4; | private static final int PARENT_COUNT = 4; | |||
private static final int LEAF_COUNT = 2; | private static final int LEAF_COUNT = 2; | |||
private TreeData<Node> data; | private TreeData<Node> data; | |||
private TreeDataProvider<Node> provider; | private TreeDataProvider<Node> provider; | |||
private HierarchyMapper<Node, SerializablePredicate<Node>> mapper; | private HierarchyMapper<Node, SerializablePredicate<Node>> mapper; | |||
private List<Node> testData; | private List<Node> testData; | |||
private List<Node> roots; | private List<Node> roots; | |||
private int mapSize; | private int mapSize; | |||
@Rule | ||||
public ExpectedException exceptionRule = ExpectedException.none(); | ||||
private void setupData() { | private void setupData() { | |||
mapSize = ROOT_COUNT; | mapSize = ROOT_COUNT; | |||
data = new TreeData<>(); | data = new TreeData<>(); | |||
testData = generateTestData(ROOT_COUNT, PARENT_COUNT, LEAF_COUNT); | testData = generateTestData(ROOT_COUNT, PARENT_COUNT, LEAF_COUNT); | |||
roots = testData.stream().filter(item -> item.getParent() == null) | roots = testData.stream().filter(item -> item.getParent() == null) | |||
.collect(Collectors.toList()); | .collect(Collectors.toList()); | |||
data.addItems(roots, | data.addItems(roots, | |||
parent -> testData.stream().filter( | parent -> testData.stream().filter( | |||
item -> Objects.equals(item.getParent(), parent)) | item -> Objects.equals(item.getParent(), parent)) | |||
.collect(Collectors.toList())); | .collect(Collectors.toList())); | |||
skipping to change at line 227 | skipping to change at line 237 | |||
.of(0, 1, 4, 6, 7, 10, 13, 26, 39, 52).mapToObj(testData::get) | .of(0, 1, 4, 6, 7, 10, 13, 26, 39, 52).mapToObj(testData::get) | |||
.collect(Collectors.toList()); | .collect(Collectors.toList()); | |||
mapper.setFilter(filter); | mapper.setFilter(filter); | |||
// Fetch everything | // Fetch everything | |||
Range range = Range.between(0, mapper.getTreeSize()); | Range range = Range.between(0, mapper.getTreeSize()); | |||
verifyFetchIsCorrect(expectedResult, range); | verifyFetchIsCorrect(expectedResult, range); | |||
} | } | |||
@Test | ||||
public void getExpandedItems_expandSomeItems_returnsCorrectExpandedItems() { | ||||
TreeNode root = new TreeNode("root", null); | ||||
TreeNode second1 = new TreeNode("second-1", root); | ||||
TreeNode second2 = new TreeNode("second-2", root); | ||||
TreeNode third11 = new TreeNode("third-1-1", second1); | ||||
TreeNode third21 = new TreeNode("third-2-1", second2); | ||||
HierarchicalDataProvider<TreeNode, Void> dataProvider = | ||||
new ThreeLevelStaticHierarchicalDataProvider(root, | ||||
new TreeNode[]{second1, second2}, | ||||
new TreeNode[]{third11, third21}); | ||||
HierarchyMapper<TreeNode, Void> hierarchyMapper = new HierarchyMapper<>( | ||||
dataProvider | ||||
); | ||||
Collection<TreeNode> expandedItems = | ||||
getHierarchyMapperExpandedItems(hierarchyMapper); | ||||
Assert.assertNotNull(expandedItems); | ||||
Assert.assertEquals(0L, expandedItems.size()); | ||||
hierarchyMapper.expand(root); | ||||
hierarchyMapper.expand(second2); | ||||
expandedItems = getHierarchyMapperExpandedItems(hierarchyMapper); | ||||
Assert.assertNotNull(expandedItems); | ||||
Assert.assertEquals(2L, expandedItems.size()); | ||||
Assert.assertArrayEquals(new Object[]{"root", "second-2"}, | ||||
expandedItems.stream() | ||||
.map(TreeNode::getName) | ||||
.sorted().toArray()); | ||||
} | ||||
@Test | ||||
public void getExpandedItems_tryToAddItemsToCollection_shouldThrowException( | ||||
) { | ||||
exceptionRule.expect(UnsupportedOperationException.class); | ||||
TreeNode root = new TreeNode("root", null); | ||||
TreeNode second1 = new TreeNode("second-1", root); | ||||
TreeNode second2 = new TreeNode("second-2", root); | ||||
TreeNode third11 = new TreeNode("third-1-1", second1); | ||||
TreeNode third21 = new TreeNode("third-2-1", second2); | ||||
HierarchicalDataProvider<TreeNode, Void> dataProvider = | ||||
new ThreeLevelStaticHierarchicalDataProvider(root, | ||||
new TreeNode[]{second1, second2}, | ||||
new TreeNode[]{third11, third21}); | ||||
HierarchyMapper<TreeNode, Void> hierarchyMapper = new HierarchyMapper<>( | ||||
dataProvider | ||||
); | ||||
hierarchyMapper.expand(root); | ||||
hierarchyMapper.expand(second1); | ||||
Collection<TreeNode> expandedItems = | ||||
getHierarchyMapperExpandedItems(hierarchyMapper); | ||||
expandedItems.add(new TreeNode("third-1")); | ||||
} | ||||
private void expand(Node node) { | private void expand(Node node) { | |||
insertRows(mapper.expand(node, mapper.getIndexOf(node).orElse(null))); | insertRows(mapper.expand(node, mapper.getIndexOf(node).orElse(null))); | |||
} | } | |||
private void collapse(Node node) { | private void collapse(Node node) { | |||
removeRows(mapper.collapse(node, mapper.getIndexOf(node).orElse(null))); | removeRows(mapper.collapse(node, mapper.getIndexOf(node).orElse(null))); | |||
} | } | |||
private void verifyFetchIsCorrect(List<Node> expectedResult, Range range) { | private void verifyFetchIsCorrect(List<Node> expectedResult, Range range) { | |||
List<Node> collect = mapper.fetchHierarchyItems(range) | List<Node> collect = mapper.fetchHierarchyItems(range) | |||
skipping to change at line 280 | skipping to change at line 353 | |||
assertTrue("Removing more items than in map", | assertTrue("Removing more items than in map", | |||
range.getEnd() <= mapSize); | range.getEnd() <= mapSize); | |||
mapSize -= range.length(); | mapSize -= range.length(); | |||
} | } | |||
public void insertRows(Range range) { | public void insertRows(Range range) { | |||
assertTrue("Index not in range", | assertTrue("Index not in range", | |||
0 <= range.getStart() && range.getStart() <= mapSize); | 0 <= range.getStart() && range.getStart() <= mapSize); | |||
mapSize += range.length(); | mapSize += range.length(); | |||
} | } | |||
private Collection<TreeNode> getHierarchyMapperExpandedItems( | ||||
HierarchyMapper<TreeNode, ?> hierarchyMapper) { | ||||
if (!hierarchyMapper.hasExpandedItems()) { | ||||
return Collections.emptySet(); | ||||
} | ||||
Collection<TreeNode> expandedItems = new HashSet<>(); | ||||
hierarchyMapper.fetchRootItems(null) | ||||
.forEach(root -> expandedItems.addAll( | ||||
getExpandedItems(root, hierarchyMapper))); | ||||
return Collections.unmodifiableCollection(expandedItems); | ||||
} | ||||
private Collection<TreeNode> getExpandedItems( | ||||
TreeNode parent, HierarchyMapper<TreeNode, ?> hierarchyMapper) { | ||||
Collection<TreeNode> expandedItems = new HashSet<>(); | ||||
if (hierarchyMapper.isExpanded(parent)) { | ||||
expandedItems.add(parent); | ||||
} | ||||
hierarchyMapper.fetchChildItems(parent, null) | ||||
.forEach(child -> expandedItems.addAll( | ||||
getExpandedItems(child, hierarchyMapper))); | ||||
return expandedItems; | ||||
} | ||||
private static class TreeNode { | ||||
private String name; | ||||
private TreeNode parent; | ||||
public TreeNode(String name) { | ||||
this.name = name; | ||||
} | ||||
public TreeNode(String name, TreeNode parent) { | ||||
this.name = name; | ||||
this.parent = parent; | ||||
} | ||||
public String getName() { | ||||
return name; | ||||
} | ||||
public void setName(String name) { | ||||
this.name = name; | ||||
} | ||||
public TreeNode getParent() { | ||||
return parent; | ||||
} | ||||
public void setParent(TreeNode parent) { | ||||
this.parent = parent; | ||||
} | ||||
} | ||||
private static class ThreeLevelStaticHierarchicalDataProvider | ||||
extends AbstractBackEndHierarchicalDataProvider<TreeNode, Void> { | ||||
private TreeNode root; | ||||
private TreeNode[] secondLevelNodes; | ||||
private TreeNode[] thirdLevelNodes; | ||||
public ThreeLevelStaticHierarchicalDataProvider( | ||||
TreeNode root, | ||||
TreeNode[] secondLevelNodes, | ||||
TreeNode[] thirdLevelNodes) { | ||||
this.root = root; | ||||
this.secondLevelNodes = secondLevelNodes; | ||||
this.thirdLevelNodes = thirdLevelNodes; | ||||
} | ||||
@Override | ||||
public int getChildCount(HierarchicalQuery<TreeNode, Void> query) { | ||||
// query node is the root: | ||||
if (query.getParent() == null) { | ||||
return secondLevelNodes.length; | ||||
} | ||||
// query node is among the last(third) layer: | ||||
if (Arrays.stream(secondLevelNodes) | ||||
.anyMatch(node -> node == query.getParent())) { | ||||
return 0; | ||||
} | ||||
// count nodes of last(third) layer that are children of query's | ||||
// parent: | ||||
return (int) Arrays.stream(thirdLevelNodes) | ||||
.filter(node -> node.getParent() == query.getParent()) | ||||
.count(); | ||||
} | ||||
@Override | ||||
public boolean hasChildren(TreeNode item) { | ||||
return item.getParent() == null || | ||||
Arrays.stream(secondLevelNodes) | ||||
.anyMatch(node -> node == item); | ||||
} | ||||
@Override | ||||
protected Stream<TreeNode> fetchChildrenFromBackEnd( | ||||
HierarchicalQuery<TreeNode, Void> query) { | ||||
if (query.getParent() == null) { | ||||
return Arrays.stream(new TreeNode[] {root}); | ||||
} | ||||
if(query.getParent() == root) { | ||||
return Arrays.stream(secondLevelNodes); | ||||
} | ||||
return Arrays.stream(thirdLevelNodes) | ||||
.filter(node -> node.getParent() == query.getParent()); | ||||
} | ||||
} | ||||
} | } | |||
End of changes. 8 change blocks. | ||||
0 lines changed or deleted | 186 lines changed or added |