From 510379c92485303787e0198a67eae8a6993754d1 Mon Sep 17 00:00:00 2001 From: Stephan Classen Date: Thu, 12 Mar 2026 18:23:27 +0100 Subject: [PATCH 1/4] feat: extract interface HierarchicalTreeData from TreeData TreeDataProvider currently takes a TreeData as its source. But it relies only on a few methods of TreeData. This change extracts those methods into an interface. It then introduces a super class to TreeDataProvider which accepts a HierarchicalTreeData instead of a TreeData. A client has now the choice to either use the TreeData and the TreeDataProvider, or it can implement the HierarchicalTreeData interface and use the HierarchicalTreeDataProvider. This change introduces a new interface and a class but does not change or break any existing API. Fixes #9808 --- .../hierarchy/HierarchicalTreeData.java | 68 ++++++ .../HierarchicalTreeDataProvider.java | 227 ++++++++++++++++++ .../data/provider/hierarchy/TreeData.java | 34 +-- .../provider/hierarchy/TreeDataProvider.java | 168 +------------ 4 files changed, 303 insertions(+), 194 deletions(-) create mode 100644 flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java create mode 100644 flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java new file mode 100644 index 00000000000..e9cefbc4a86 --- /dev/null +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.data.provider.hierarchy; + +import java.io.Serializable; +import java.util.List; + +/** + * Represents hierarchical data. + *

+ * Typically used as a backing data source for {@link TreeDataProvider}. + * + * @author Vaadin Ltd + * @since 25.2 + * + * @param + * data type + */ +public interface HierarchicalTreeData extends Serializable { + + /** + * Get the immediate child items for the given item. + * + * @param item + * the item for which to retrieve child items for, null to + * retrieve all root items + * @return an unmodifiable list of child items for the given item + * + * @throws IllegalArgumentException + * if the item does not exist in this structure + */ + List getChildren(T item); + + /** + * Get the parent item for the given item. + * + * @param item + * the item for which to retrieve the parent item for + * @return parent item for the given item or {@code null} if the item is a + * root item. + * @throws IllegalArgumentException + * if the item does not exist in this structure + */ + T getParent(T item); + + /** + * Check whether the given item is in this hierarchy. + * + * @param item + * the item to check + * @return {@code true} if the item is in this hierarchy, {@code false} if + * not + */ + boolean contains(T item); +} diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java new file mode 100644 index 00000000000..fe812b0f899 --- /dev/null +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java @@ -0,0 +1,227 @@ +/* + * Copyright 2000-2026 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.flow.data.provider.hierarchy; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; + +import com.vaadin.flow.data.provider.InMemoryDataProvider; +import com.vaadin.flow.function.SerializableComparator; +import com.vaadin.flow.function.SerializablePredicate; + +/** + * An in-memory data provider for listing components that display hierarchical + * data. Uses an instance of {@link HierarchicalTreeData} as its source of data. + * + * @author Vaadin Ltd + * @since 25.2 + * + * @param + * data type + */ +public class HierarchicalTreeDataProvider + extends AbstractHierarchicalDataProvider> + implements InMemoryDataProvider { + + private final HierarchicalTreeData treeData; + + private SerializablePredicate filter = null; + + private SerializableComparator sortOrder = null; + + private HierarchyFormat hierarchyFormat = HierarchyFormat.NESTED; + + /** + * Constructs a new TreeDataProvider. + *

+ * The data provider should be refreshed after making changes to the + * underlying {@link HierarchicalTreeData} instance. + * + * @param treeData + * the backing {@link TreeData} for this provider, not + * {@code null} + */ + public HierarchicalTreeDataProvider(HierarchicalTreeData treeData) { + this.treeData = Objects.requireNonNull(treeData, + "treeData cannot be null"); + } + + /** + * Creates a new TreeDataProvider and configures it to return the + * hierarchical data in the specified format: {@link HierarchyFormat#NESTED} + * or {@link HierarchyFormat#FLATTENED}. + *

+ * The data provider should be refreshed after making changes to the + * underlying {@link HierarchicalTreeData} instance. + * + * @param treeData + * the backing {@link TreeData} for this provider, not + * {@code null} + * @param hierarchyFormat + * the hierarchy format to return data in, not {@code null} + */ + public HierarchicalTreeDataProvider(HierarchicalTreeData treeData, + HierarchyFormat hierarchyFormat) { + this(treeData); + this.hierarchyFormat = Objects.requireNonNull(hierarchyFormat, + "hierarchyFormat cannot be null"); + } + + @Override + public HierarchyFormat getHierarchyFormat() { + return hierarchyFormat; + } + + /** + * Return the underlying hierarchical data of this provider. + * + * @return the underlying data of this provider + */ + public HierarchicalTreeData getTreeData() { + return treeData; + } + + @Override + public boolean hasChildren(T item) { + if (!treeData.contains(item)) { + // The item might be dropped from the tree already + return false; + } + return !treeData.getChildren(item).isEmpty(); + } + + @Override + public T getParent(T item) { + Objects.requireNonNull(item, "Item cannot be null."); + try { + return getTreeData().getParent(item); + } catch (IllegalArgumentException e) { + return null; + } + } + + @Override + public int getDepth(T item) { + int depth = 0; + while ((item = treeData.getParent(item)) != null) { + depth++; + } + return depth; + } + + @Override + public int getChildCount( + HierarchicalQuery> query) { + Optional> combinedFilter = getCombinedFilter( + query.getFilter()); + + return (int) flatten(query.getParent(), query.getExpandedItemIds(), + combinedFilter, Optional.empty()).stream() + .skip(query.getOffset()).limit(query.getLimit()).count(); + } + + @Override + public Stream fetchChildren( + HierarchicalQuery> query) { + if (!treeData.contains(query.getParent())) { + throw new IllegalArgumentException("The queried item " + + query.getParent() + + " could not be found in the backing HierarchicalTreeData. " + + "Did you forget to refresh this data provider after item removal?"); + } + + Optional> combinedFilter = getCombinedFilter( + query.getFilter()); + + Optional> comparator = Stream + .of(query.getInMemorySorting(), sortOrder) + .filter(Objects::nonNull) + .reduce((c1, c2) -> c1.thenComparing(c2)); + + return flatten(query.getParent(), query.getExpandedItemIds(), + combinedFilter, comparator).stream().skip(query.getOffset()) + .limit(query.getLimit()); + } + + @Override + public SerializablePredicate getFilter() { + return filter; + } + + @Override + public void setFilter(SerializablePredicate filter) { + this.filter = filter; + refreshAll(); + } + + @Override + public SerializableComparator getSortComparator() { + return sortOrder; + } + + @Override + public void setSortComparator(SerializableComparator comparator) { + sortOrder = comparator; + refreshAll(); + } + + private Optional> getCombinedFilter( + Optional> queryFilter) { + return filter != null + ? Optional.of(queryFilter.map(filter::and).orElse(filter)) + : queryFilter; + } + + private List flatten(T parent, Set expandedItemIds, + Optional> combinedFilter, + Optional> comparator) { + List result = new ArrayList<>(); + List children = getTreeData().getChildren(parent); + + if (comparator.isPresent()) { + children = children.stream().sorted(comparator.get()).toList(); + } + + for (T child : children) { + boolean isExpanded = expandedItemIds.contains(getId(child)); + List descendants = Collections.emptyList(); + if (getHierarchyFormat().equals(HierarchyFormat.NESTED) + || isExpanded || combinedFilter.isPresent()) { + descendants = flatten(child, expandedItemIds, combinedFilter, + comparator); + } + + boolean matchesFilter = combinedFilter.map(f -> f.test(child)) + .orElse(true) || !descendants.isEmpty(); + if (matchesFilter) { + result.add(child); + } + if (matchesFilter + && getHierarchyFormat().equals(HierarchyFormat.FLATTENED) + && isExpanded) { + result.addAll(descendants); + } + } + + return result; + } +} diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java index 10701920a17..b864aa821ec 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java @@ -40,7 +40,7 @@ * @param * data type */ -public class TreeData implements Serializable { +public class TreeData implements HierarchicalTreeData { private static class HierarchyWrapper implements Serializable { private T parent; @@ -333,17 +333,7 @@ public List getRootItems() { return getChildren(null); } - /** - * Get the immediate child items for the given item. - * - * @param item - * the item for which to retrieve child items for, null to - * retrieve all root items - * @return an unmodifiable list of child items for the given item - * - * @throws IllegalArgumentException - * if the item does not exist in this structure - */ + @Override public List getChildren(T item) { if (!contains(item)) { throw new IllegalArgumentException( @@ -353,16 +343,7 @@ public List getChildren(T item) { .unmodifiableList(itemToWrapperMap.get(item).getChildren()); } - /** - * Get the parent item for the given item. - * - * @param item - * the item for which to retrieve the parent item for - * @return parent item for the given item or {@code null} if the item is a - * root item. - * @throws IllegalArgumentException - * if the item does not exist in this structure - */ + @Override public T getParent(T item) { if (!contains(item)) { throw new IllegalArgumentException( @@ -468,14 +449,7 @@ public void moveAfterSibling(T item, T sibling) { } } - /** - * Check whether the given item is in this hierarchy. - * - * @param item - * the item to check - * @return {@code true} if the item is in this hierarchy, {@code false} if - * not - */ + @Override public boolean contains(T item) { return itemToWrapperMap.containsKey(item); } diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java index 5344918491e..a266afa3936 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java @@ -15,19 +15,6 @@ */ package com.vaadin.flow.data.provider.hierarchy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Stream; - -import com.vaadin.flow.data.provider.InMemoryDataProvider; -import com.vaadin.flow.function.SerializableComparator; -import com.vaadin.flow.function.SerializablePredicate; - /** * An in-memory data provider for listing components that display hierarchical * data. Uses an instance of {@link TreeData} as its source of data. @@ -38,17 +25,7 @@ * @param * data type */ -public class TreeDataProvider - extends AbstractHierarchicalDataProvider> - implements InMemoryDataProvider { - - private final TreeData treeData; - - private SerializablePredicate filter = null; - - private SerializableComparator sortOrder = null; - - private HierarchyFormat hierarchyFormat = HierarchyFormat.NESTED; +public class TreeDataProvider extends HierarchicalTreeDataProvider { /** * Constructs a new TreeDataProvider. @@ -61,8 +38,7 @@ public class TreeDataProvider * {@code null} */ public TreeDataProvider(TreeData treeData) { - this.treeData = Objects.requireNonNull(treeData, - "treeData cannot be null"); + super(treeData); } /** @@ -81,147 +57,11 @@ public TreeDataProvider(TreeData treeData) { */ public TreeDataProvider(TreeData treeData, HierarchyFormat hierarchyFormat) { - this(treeData); - this.hierarchyFormat = Objects.requireNonNull(hierarchyFormat, - "hierarchyFormat cannot be null"); + super(treeData, hierarchyFormat); } @Override - public HierarchyFormat getHierarchyFormat() { - return hierarchyFormat; - } - - /** - * Return the underlying hierarchical data of this provider. - * - * @return the underlying data of this provider - */ public TreeData getTreeData() { - return treeData; - } - - @Override - public boolean hasChildren(T item) { - if (!treeData.contains(item)) { - // The item might be dropped from the tree already - return false; - } - return !treeData.getChildren(item).isEmpty(); - } - - @Override - public T getParent(T item) { - Objects.requireNonNull(item, "Item cannot be null."); - try { - return getTreeData().getParent(item); - } catch (IllegalArgumentException e) { - return null; - } - } - - @Override - public int getDepth(T item) { - int depth = 0; - while ((item = treeData.getParent(item)) != null) { - depth++; - } - return depth; - } - - @Override - public int getChildCount( - HierarchicalQuery> query) { - Optional> combinedFilter = getCombinedFilter( - query.getFilter()); - - return (int) flatten(query.getParent(), query.getExpandedItemIds(), - combinedFilter, Optional.empty()).stream() - .skip(query.getOffset()).limit(query.getLimit()).count(); - } - - @Override - public Stream fetchChildren( - HierarchicalQuery> query) { - if (!treeData.contains(query.getParent())) { - throw new IllegalArgumentException("The queried item " - + query.getParent() - + " could not be found in the backing TreeData. " - + "Did you forget to refresh this data provider after item removal?"); - } - - Optional> combinedFilter = getCombinedFilter( - query.getFilter()); - - Optional> comparator = Stream - .of(query.getInMemorySorting(), sortOrder) - .filter(Objects::nonNull) - .reduce((c1, c2) -> c1.thenComparing(c2)); - - return flatten(query.getParent(), query.getExpandedItemIds(), - combinedFilter, comparator).stream().skip(query.getOffset()) - .limit(query.getLimit()); - } - - @Override - public SerializablePredicate getFilter() { - return filter; - } - - @Override - public void setFilter(SerializablePredicate filter) { - this.filter = filter; - refreshAll(); - } - - @Override - public SerializableComparator getSortComparator() { - return sortOrder; - } - - @Override - public void setSortComparator(SerializableComparator comparator) { - sortOrder = comparator; - refreshAll(); - } - - private Optional> getCombinedFilter( - Optional> queryFilter) { - return filter != null - ? Optional.of(queryFilter.map(filter::and).orElse(filter)) - : queryFilter; - } - - private List flatten(T parent, Set expandedItemIds, - Optional> combinedFilter, - Optional> comparator) { - List result = new ArrayList<>(); - List children = getTreeData().getChildren(parent); - - if (comparator.isPresent()) { - children = children.stream().sorted(comparator.get()).toList(); - } - - for (T child : children) { - boolean isExpanded = expandedItemIds.contains(getId(child)); - List descendants = Collections.emptyList(); - if (getHierarchyFormat().equals(HierarchyFormat.NESTED) - || isExpanded || combinedFilter.isPresent()) { - descendants = flatten(child, expandedItemIds, combinedFilter, - comparator); - } - - boolean matchesFilter = combinedFilter.map(f -> f.test(child)) - .orElse(true) || !descendants.isEmpty(); - if (matchesFilter) { - result.add(child); - } - if (matchesFilter - && getHierarchyFormat().equals(HierarchyFormat.FLATTENED) - && isExpanded) { - result.addAll(descendants); - } - } - - return result; + return (TreeData) super.getTreeData(); } } From 1224857dceb68901cf2f7d5bb2f7f2e529d08637 Mon Sep 17 00:00:00 2001 From: Stephan Classen Date: Fri, 20 Mar 2026 10:11:55 +0100 Subject: [PATCH 2/4] feature: introduce second generic param in HierarchicalTreeDataProvider This second gerenic parameter represents the concrete type of the HierarchicalTreeData. Having this as a generic parameter allows for better type safty. The client of the provider can get the underlying data structure in a type safe manner. This eases writing stable code. --- .../HierarchicalTreeDataProvider.java | 34 ++++++++++--------- .../provider/hierarchy/TreeDataProvider.java | 8 ++--- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java index fe812b0f899..1237ab90950 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java @@ -37,12 +37,15 @@ * * @param * data type + * @param + * concrete type of the {@link HierarchicalTreeData} used in this + * provider. */ -public class HierarchicalTreeDataProvider +public class HierarchicalTreeDataProvider> extends AbstractHierarchicalDataProvider> implements InMemoryDataProvider { - private final HierarchicalTreeData treeData; + private final U treeData; private SerializablePredicate filter = null; @@ -51,35 +54,35 @@ public class HierarchicalTreeDataProvider private HierarchyFormat hierarchyFormat = HierarchyFormat.NESTED; /** - * Constructs a new TreeDataProvider. + * Constructs a new HierarchicalTreeDataProvider. *

* The data provider should be refreshed after making changes to the * underlying {@link HierarchicalTreeData} instance. * * @param treeData - * the backing {@link TreeData} for this provider, not - * {@code null} + * the backing {@link HierarchicalTreeData} for this provider, + * not {@code null} */ - public HierarchicalTreeDataProvider(HierarchicalTreeData treeData) { + public HierarchicalTreeDataProvider(U treeData) { this.treeData = Objects.requireNonNull(treeData, "treeData cannot be null"); } /** - * Creates a new TreeDataProvider and configures it to return the - * hierarchical data in the specified format: {@link HierarchyFormat#NESTED} - * or {@link HierarchyFormat#FLATTENED}. + * Creates a new HierarchicalTreeDataProvider and configures it to return + * the hierarchical data in the specified format: + * {@link HierarchyFormat#NESTED} or {@link HierarchyFormat#FLATTENED}. *

* The data provider should be refreshed after making changes to the * underlying {@link HierarchicalTreeData} instance. * * @param treeData - * the backing {@link TreeData} for this provider, not - * {@code null} + * the backing {@link HierarchicalTreeData} for this provider, + * not {@code null} * @param hierarchyFormat * the hierarchy format to return data in, not {@code null} */ - public HierarchicalTreeDataProvider(HierarchicalTreeData treeData, + public HierarchicalTreeDataProvider(U treeData, HierarchyFormat hierarchyFormat) { this(treeData); this.hierarchyFormat = Objects.requireNonNull(hierarchyFormat, @@ -92,11 +95,11 @@ public HierarchyFormat getHierarchyFormat() { } /** - * Return the underlying hierarchical data of this provider. + * Return the underlying {@link HierarchicalTreeData} of this provider. * * @return the underlying data of this provider */ - public HierarchicalTreeData getTreeData() { + public U getTreeData() { return treeData; } @@ -154,8 +157,7 @@ public Stream fetchChildren( Optional> comparator = Stream .of(query.getInMemorySorting(), sortOrder) - .filter(Objects::nonNull) - .reduce((c1, c2) -> c1.thenComparing(c2)); + .filter(Objects::nonNull).reduce(Comparator::thenComparing); return flatten(query.getParent(), query.getExpandedItemIds(), combinedFilter, comparator).stream().skip(query.getOffset()) diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java index a266afa3936..196b2297a9a 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java @@ -25,7 +25,8 @@ * @param * data type */ -public class TreeDataProvider extends HierarchicalTreeDataProvider { +public class TreeDataProvider + extends HierarchicalTreeDataProvider> { /** * Constructs a new TreeDataProvider. @@ -59,9 +60,4 @@ public TreeDataProvider(TreeData treeData, HierarchyFormat hierarchyFormat) { super(treeData, hierarchyFormat); } - - @Override - public TreeData getTreeData() { - return (TreeData) super.getTreeData(); - } } From 10d4ab6b065d3163f8339b5bcd332128557acfed Mon Sep 17 00:00:00 2001 From: Stephan Classen Date: Fri, 20 Mar 2026 22:45:32 +0100 Subject: [PATCH 3/4] refactor: renaming classes and parameters - rename HierarchicalTreeDataProvider.java -> InMemoryHierarchicalDataProvider.java - rename HierarchicalTreeData.java -> HierarchicalData.java - add method InMemoryHierarchicalDataProvider.getHierarchicalData() --- ...calTreeData.java => HierarchicalData.java} | 5 +- ... => InMemoryHierarchicalDataProvider.java} | 69 +++++++++++-------- .../data/provider/hierarchy/TreeData.java | 2 +- .../provider/hierarchy/TreeDataProvider.java | 14 +++- 4 files changed, 57 insertions(+), 33 deletions(-) rename flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/{HierarchicalTreeData.java => HierarchicalData.java} (92%) rename flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/{HierarchicalTreeDataProvider.java => InMemoryHierarchicalDataProvider.java} (76%) diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalData.java similarity index 92% rename from flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java rename to flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalData.java index e9cefbc4a86..f8b21cbc2bc 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeData.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalData.java @@ -21,7 +21,8 @@ /** * Represents hierarchical data. *

- * Typically used as a backing data source for {@link TreeDataProvider}. + * Typically used as a backing data source for + * {@link InMemoryHierarchicalDataProvider}. * * @author Vaadin Ltd * @since 25.2 @@ -29,7 +30,7 @@ * @param * data type */ -public interface HierarchicalTreeData extends Serializable { +public interface HierarchicalData extends Serializable { /** * Get the immediate child items for the given item. diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java similarity index 76% rename from flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java rename to flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java index 1237ab90950..d22b9166c30 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/HierarchicalTreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java @@ -30,7 +30,7 @@ /** * An in-memory data provider for listing components that display hierarchical - * data. Uses an instance of {@link HierarchicalTreeData} as its source of data. + * data. Uses an instance of {@link HierarchicalData} as its source of data. * * @author Vaadin Ltd * @since 25.2 @@ -38,14 +38,14 @@ * @param * data type * @param - * concrete type of the {@link HierarchicalTreeData} used in this + * concrete type of the {@link HierarchicalData} used in this * provider. */ -public class HierarchicalTreeDataProvider> +public class InMemoryHierarchicalDataProvider> extends AbstractHierarchicalDataProvider> implements InMemoryDataProvider { - private final U treeData; + private final U hierarchicalData; private SerializablePredicate filter = null; @@ -54,37 +54,37 @@ public class HierarchicalTreeDataProvider> private HierarchyFormat hierarchyFormat = HierarchyFormat.NESTED; /** - * Constructs a new HierarchicalTreeDataProvider. + * Constructs a new InMemoryHierarchicalDataProvider. *

* The data provider should be refreshed after making changes to the - * underlying {@link HierarchicalTreeData} instance. + * underlying {@link HierarchicalData} instance. * - * @param treeData - * the backing {@link HierarchicalTreeData} for this provider, - * not {@code null} + * @param hierarchicalData + * the backing {@link HierarchicalData} for this provider, not + * {@code null} */ - public HierarchicalTreeDataProvider(U treeData) { - this.treeData = Objects.requireNonNull(treeData, - "treeData cannot be null"); + public InMemoryHierarchicalDataProvider(U hierarchicalData) { + this.hierarchicalData = Objects.requireNonNull(hierarchicalData, + "hierarchicalData cannot be null"); } /** - * Creates a new HierarchicalTreeDataProvider and configures it to return - * the hierarchical data in the specified format: + * Creates a new InMemoryHierarchicalDataProvider and configures it to + * return the hierarchical data in the specified format: * {@link HierarchyFormat#NESTED} or {@link HierarchyFormat#FLATTENED}. *

* The data provider should be refreshed after making changes to the - * underlying {@link HierarchicalTreeData} instance. + * underlying {@link HierarchicalData} instance. * - * @param treeData - * the backing {@link HierarchicalTreeData} for this provider, - * not {@code null} + * @param hierarchicalData + * the backing {@link HierarchicalData} for this provider, not + * {@code null} * @param hierarchyFormat * the hierarchy format to return data in, not {@code null} */ - public HierarchicalTreeDataProvider(U treeData, + public InMemoryHierarchicalDataProvider(U hierarchicalData, HierarchyFormat hierarchyFormat) { - this(treeData); + this(hierarchicalData); this.hierarchyFormat = Objects.requireNonNull(hierarchyFormat, "hierarchyFormat cannot be null"); } @@ -95,28 +95,39 @@ public HierarchyFormat getHierarchyFormat() { } /** - * Return the underlying {@link HierarchicalTreeData} of this provider. + * Return the underlying {@link HierarchicalData} of this provider. * * @return the underlying data of this provider */ + public U getHierarchicalData() { + return hierarchicalData; + } + + /** + * Return the underlying {@link HierarchicalData} of this provider. + * + * @return the underlying data of this provider + * @deprecated use {@link #getHierarchicalData()} instead. + */ + @Deprecated public U getTreeData() { - return treeData; + return hierarchicalData; } @Override public boolean hasChildren(T item) { - if (!treeData.contains(item)) { + if (!hierarchicalData.contains(item)) { // The item might be dropped from the tree already return false; } - return !treeData.getChildren(item).isEmpty(); + return !hierarchicalData.getChildren(item).isEmpty(); } @Override public T getParent(T item) { Objects.requireNonNull(item, "Item cannot be null."); try { - return getTreeData().getParent(item); + return hierarchicalData.getParent(item); } catch (IllegalArgumentException e) { return null; } @@ -125,7 +136,7 @@ public T getParent(T item) { @Override public int getDepth(T item) { int depth = 0; - while ((item = treeData.getParent(item)) != null) { + while ((item = hierarchicalData.getParent(item)) != null) { depth++; } return depth; @@ -145,10 +156,10 @@ public int getChildCount( @Override public Stream fetchChildren( HierarchicalQuery> query) { - if (!treeData.contains(query.getParent())) { + if (!hierarchicalData.contains(query.getParent())) { throw new IllegalArgumentException("The queried item " + query.getParent() - + " could not be found in the backing HierarchicalTreeData. " + + " could not be found in the backing HierarchicalData. " + "Did you forget to refresh this data provider after item removal?"); } @@ -197,7 +208,7 @@ private List flatten(T parent, Set expandedItemIds, Optional> combinedFilter, Optional> comparator) { List result = new ArrayList<>(); - List children = getTreeData().getChildren(parent); + List children = hierarchicalData.getChildren(parent); if (comparator.isPresent()) { children = children.stream().sorted(comparator.get()).toList(); diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java index b864aa821ec..c8758c76f88 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeData.java @@ -40,7 +40,7 @@ * @param * data type */ -public class TreeData implements HierarchicalTreeData { +public class TreeData implements HierarchicalData { private static class HierarchyWrapper implements Serializable { private T parent; diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java index 196b2297a9a..3ab63a1dbd9 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java @@ -26,7 +26,7 @@ * data type */ public class TreeDataProvider - extends HierarchicalTreeDataProvider> { + extends InMemoryHierarchicalDataProvider> { /** * Constructs a new TreeDataProvider. @@ -60,4 +60,16 @@ public TreeDataProvider(TreeData treeData, HierarchyFormat hierarchyFormat) { super(treeData, hierarchyFormat); } + + /** + * Return the underlying {@link TreeData} of this provider. + * + * @return the underlying data of this provider + * @deprecated use {@link #getHierarchicalData()} instead. + */ + @Deprecated + @Override + public TreeData getTreeData() { + return super.getTreeData(); + } } From e557af2850148973c0c787759cff59695ea1541a Mon Sep 17 00:00:00 2001 From: Stephan Classen Date: Wed, 25 Mar 2026 23:43:27 +0100 Subject: [PATCH 4/4] feat: remove unnecessary deprecated method --- .../hierarchy/InMemoryHierarchicalDataProvider.java | 11 ----------- .../data/provider/hierarchy/TreeDataProvider.java | 5 ++--- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java index d22b9166c30..a9d71b51640 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/InMemoryHierarchicalDataProvider.java @@ -103,17 +103,6 @@ public U getHierarchicalData() { return hierarchicalData; } - /** - * Return the underlying {@link HierarchicalData} of this provider. - * - * @return the underlying data of this provider - * @deprecated use {@link #getHierarchicalData()} instead. - */ - @Deprecated - public U getTreeData() { - return hierarchicalData; - } - @Override public boolean hasChildren(T item) { if (!hierarchicalData.contains(item)) { diff --git a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java index 3ab63a1dbd9..54489e1b82b 100644 --- a/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java +++ b/flow-data/src/main/java/com/vaadin/flow/data/provider/hierarchy/TreeDataProvider.java @@ -67,9 +67,8 @@ public TreeDataProvider(TreeData treeData, * @return the underlying data of this provider * @deprecated use {@link #getHierarchicalData()} instead. */ - @Deprecated - @Override + @Deprecated(forRemoval = true, since = "25.2") public TreeData getTreeData() { - return super.getTreeData(); + return getHierarchicalData(); } }