Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor common methods in in-memory data providers #9308

Merged
merged 2 commits into from
May 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion all/src/main/templates/release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ <h2 id="incompatible">Incompatible or Behavior-altering Changes in @version@</h2

<li>The <tt>TreeGrid</tt> component replaces <tt>TreeTable</tt> component</li>
<li>The <tt>Tree</tt> component replaces old <tt>Tree</tt> component</li>
<li>The <tt>HierarchicalDataProvider</tt> interface replaces <tt>Container.Hierarchical</tt> and <<tt>InMemoryHierarchicalDataProvider</tt> replaces <tt>HierarchicalContainer</tt></li>
<li>The <tt>HierarchicalDataProvider</tt> interface replaces <tt>Container.Hierarchical</tt> and <<tt>TreeDataProvider</tt> replaces <tt>HierarchicalContainer</tt></li>
<li>The <tt>DragSourceExtension</tt> and <tt>DropTargetExtension</tt> extensions replace the old DnD features</li>
<li>OSGi bundle manifests of Vaadin Framework JARs no longer export <tt>/VAADIN</tt>, and there are new mechanisms for publishing static resources for OSGi</li>

Expand Down
28 changes: 14 additions & 14 deletions documentation/components/components-tree.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,32 @@ image::img/tree-basic.png[width=70%, scaledwidth=100%]
[[components.tree.data]]
== Binding to Data

[classname]#Tree# is used by binding it to a hierarchical data provider. The data provider can be based on in-memory or back end data. For in-memory data, the [classname]#InMemoryHierarchicalDataProvider# can be used, and for loading data from a back end, you need to implement three methods from the [interfacename]#HierarchicalDataProvider# interface. Usage of both data providers is described in
[classname]#Tree# is used by binding it to a hierarchical data provider. The data provider can be based on in-memory or back end data. For in-memory data, the [classname]#TreeDataProvider# can be used, and for loading data from a back end, you need to implement three methods from the [interfacename]#HierarchicalDataProvider# interface. Usage of both data providers is described in
<<dummy/../../../framework/datamodel/datamodel-hierarchical.asciidoc#datamodel.hierarchical,"Hierarchical Data">>.


The [classname]#HierarchyData# class can be used to build the hierarchical data structure,
and it can then be passed on to [classname]#InMemoryHierarchicalDataProvider#. It is simply a hierarchical
The [classname]#TreeData# class can be used to build the hierarchical data structure,
and it can then be passed on to [classname]#TreeDataProvider#. It is simply a hierarchical
collection, that the data provider uses to populate the [classname]#Tree#.

The [methodname]#setItems# method in [classname]#Tree# can be used to set the root level items. Internally
an [classname]#InMemoryHierarchicalDataProvider# with [classname]#HierarchyData# is used.
an [classname]#TreeDataProvider# with [classname]#TreeData# is used.

[source, java]
----
// An initial planet tree
Tree<String> tree = new Tree<>();
HierarchyData<String> hierarchyData = new HierarchyData<>();
TreeData<String> treeData = new TreeData<>();

// Couple of childless root items
hierarchyData.addItem(null,"Mercury");
hierarchyData.addItem(null,"Venus");
treeData.addItem(null,"Mercury");
treeData.addItem(null,"Venus");

// Items with hierarchy
hierarchyData.addItem(null,"Earth");
hierarchyData.addItem("Earth","The Moon");
treeData.addItem(null,"Earth");
treeData.addItem("Earth","The Moon");

inMemoryDataProvider = new InMemoryHierarchicalDataProvider<>(hierarchyData);
inMemoryDataProvider = new TreeDataProvider<>(treeData);
tree.setDataProvider(inMemoryDataProvider);
tree.expand("Earth"); // Expand programmatically
----
Expand All @@ -67,9 +67,9 @@ the in-memory data in the tree, you may do it as follows:
[source, java]
----
// Add Mars with satellites
hierarchyData.addItem(null, "Mars");
hierarchyData.addItem("Mars", "Phobos");
hierarchyData.addItem("Mars", "Deimos");
treeData.addItem(null, "Mars");
treeData.addItem("Mars", "Phobos");
treeData.addItem("Mars", "Deimos");
inMemoryDataProvider.refreshAll();

----
Expand Down Expand Up @@ -208,4 +208,4 @@ You could thereby define the item styling as follows:
font-style: italic;
}
----
////
////
16 changes: 8 additions & 8 deletions documentation/components/components-treegrid.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ image::img/tree-grid-basic.png[width=70%, scaledwidth=100%]
[[components.treegrid.data]]
== Binding to Data

[classname]#TreeGrid# is used by binding it to a hierarchical data provider. The data provider can be based on in-memory or back end data. For in-memory data, the [classname]#InMemoryHierarchicalDataProvider# can be used, and for loading data from a back end, you need to implement three methods from the [interfacename]#HierarchicalDataProvider# interface. Usage of both data providers is described in
[classname]#TreeGrid# is used by binding it to a hierarchical data provider. The data provider can be based on in-memory or back end data. For in-memory data, the [classname]#TreeDataProvider# can be used, and for loading data from a back end, you need to implement three methods from the [interfacename]#HierarchicalDataProvider# interface. Usage of both data providers is described in
<<dummy/../../../framework/datamodel/datamodel-hierarchical.asciidoc#datamodel.hierarchical,"Hierarchical Data">>.

Populating a [classname]#TreeGrid# with in-memory data can be done as follows
Expand All @@ -39,7 +39,7 @@ Populating a [classname]#TreeGrid# with in-memory data can be done as follows
----
Project rootProject = getRootRroject();

HierarchyData<Project> data = new HierarchyData<>();
TreeData<Project> data = new TreeData<>();
// add a root level item with null parent
data.addItem(null, rootProject);

Expand All @@ -48,26 +48,26 @@ rootProject.flattened().forEach(
project -> data.addItems(project, project.getSubProjects()));

TreeGrid<Project> treeGrid = new TreeGrid<>();
treeGrid.setDataProvider(new InMemoryHierarchicalDataProvider<>(data));
treeGrid.setDataProvider(new TreeDataProvider<>(data));

// the first column gets the hierarchy indicator by default
treeGrid.addColumn(Project::getName).setCaption("Project Name");
treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done");
treeGrid.addColumn(Project::getLastModified).setCaption("Last Modified");
----

The [classname]#HierarchyData# class can be used to build the hierarchical data structure,
and it can then be passed on to [classname]#InMemoryHierarchicalDataProvider#. It is simply a hierarchical
The [classname]#TreeData# class can be used to build the hierarchical data structure,
and it can then be passed on to [classname]#TreeDataProvider#. It is simply a hierarchical
collection, that the data provider uses to populate the [classname]#TreeGrid#.

The [methodname]#setItems# method in [classname]#TreeGrid# can be used to set the root level items. Internally
an [classname]#InMemoryHierarchicalDataProvider# with [classname]#HierarchyData# is used. If at any time you want to modify the in-memory data in the grid, you may do it as follows
an [classname]#TreeDataProvider# with [classname]#TreeData# is used. If at any time you want to modify the in-memory data in the grid, you may do it as follows

[source, java]
----
InMemoryHierarchicalDataProvider<Project> dataProvider = (InMemoryHierarchicalDataProvider<Project>) treeGrid.getDataProvider();
TreeDataProvider<Project> dataProvider = (TreeDataProvider<Project>) treeGrid.getDataProvider();

HierarchyData<Project> data = dataProvider.getData();
TreeData<Project> data = dataProvider.getData();
// add new items
data.addItem(null, newProject);
data.addItems(newProject, newProject.getChildren());
Expand Down
22 changes: 11 additions & 11 deletions documentation/datamodel/datamodel-hierarchical.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,38 @@ IMPORTANT: The [interfacename]#HierarchicalDataProvider# is currently being deve

The [classname]#Tree# and the [classname]#TreeGrid# components allow you to show data with hierarchical relationships between items.
That data can be populated by on-demand from a back end by implementing the [interfacename]#HierarchicalDataProvider# interface. If you have the data available in-memory on the server,
you use the collection style API of [classname]#HierarchyData# and then pass it to a [classname]#InMemoryHierarchicalDataProvider#. This chapter introduces the hierarchical data providers and how they work.
you use the collection style API of [classname]#TreeData# and then pass it to a [classname]#TreeDataProvider#. This chapter introduces the hierarchical data providers and how they work.
For using them with the components you should see <<dummy/../../../framework/components/components-tree.asciidoc#components.tree,"Tree">>
and <<dummy/../../../framework/components/components-treegrid.asciidoc#components.treegrid,"TreeGrid">> documentation.

== In-memory Hierarchical Data

When the hierarchical data is available in the server side memory, you can use it to populate the [classname]#HierarchyData# that is the source of data for an [classname]#InMemoryHierarchicalDataProvider#. It contains collection style API to construct the hierarchical structure of your data, and also verifies that the hierarchy structure is valid.
When the hierarchical data is available in the server side memory, you can use it to populate the [classname]#TreeData# that is the source of data for an [classname]#TreeDataProvider#. It contains collection style API to construct the hierarchical structure of your data, and also verifies that the hierarchy structure is valid.

The following example populates a [classname]#HierarchyData# with two levels of data:
The following example populates a [classname]#TreeData# with two levels of data:

[source, java]
----
Collection<Project> projects = service.getProjects();

HierarchyData<Project> data = new HierarchyData<>();
TreeData<Project> data = new TreeData<>();
// add root level items
data.addItems(null, projects);

// add children for the root level items
projects.forEach(project -> data.addItems(project, project.getChildren()));

// construct the data provider for the hierarchical data we've built
InMemoryHierarchicalDataProvider<Project> dataProvider = new InMemoryHierarchicalDataProvider<>(data);
TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(data);
----

=== Updating data

When adding or removing items from the [classname]#HierarchyData#, you need to always notify the data provider that it should refresh its data. This can be done with the [methodname]#refreshAll# method in the data provider.
When adding or removing items from the [classname]#TreeData#, you need to always notify the data provider that it should refresh its data. This can be done with the [methodname]#refreshAll# method in the data provider.

[source, java]
----
HierarchyData<Project> data = dataProvider.getHierarchyData();
TreeData<Project> data = dataProvider.getData();
data.addItem(null, newProject);
data.addItems(newProject, newProject.getChildren());

Expand All @@ -55,14 +55,14 @@ dataProvider.refreshAll();

=== Sorting and Filtering

For [classname]#InMemoryHierarchicalDataProvider#, both the sorting and filtering API is the same as in [classname]#ListDataProvider#. Sorting and filtering are applied separately for each hierarchy level, meaning e.g. that for a node that has not passed the filter there are no children shown.
For [classname]#TreeDataProvider#, both the sorting and filtering API is the same as in [classname]#ListDataProvider#. Sorting and filtering are applied separately for each hierarchy level, meaning e.g. that for a node that has not passed the filter there are no children shown.

[source, java]
----
// setting sorting or filtering automatically refreshes the data
dataProvider.setSortComparator((projectA, projectB) ->
projectA.getHours().compareTo(projectB.getHours()));

dataProvider.setFilter(project -> project.getHours() > 100);
----

Expand All @@ -72,7 +72,7 @@ The lazy loading hierarchical data, same concepts apply as with the non-hierarch

To load hierarchical data on-demand from your back end, you should extend the [classname]#AbstractHierarchicalDataProvider# class. Then you just have to implement the following three methods:

* `boolean hasChildren(T item)`
* `boolean hasChildren(T item)`
** This tells the data provider whether the given item has children and should be expandable. Note that this method is called frequently and should not do any costly operations.

* `int getChildCount(HierarchicalQuery<T, F> query)`
Expand All @@ -87,7 +87,7 @@ To load hierarchical data on-demand from your back end, you should extend the [c
** The parent node is available in the [classname]#HierarchicalQuery# via the [methodname]#getParent# method, which returns `null` for the root level.
** This method is called whenever the data should be displayed in the UI

Note that the [classname]#HierarchicalQuery# query object contains the relevant information regarding the sorting and filtering.
Note that the [classname]#HierarchicalQuery# query object contains the relevant information regarding the sorting and filtering.

The following code snippet shows a simple example on how to building a lazy hierarchical data provider based on file system structure:

Expand Down
Loading