Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 579303

Summary: HierarchicalHelper dumps parent if children collection is empty
Product: [Technology] NatTable Reporter: Florian Müller <floh.mueller>
Component: CoreAssignee: Dirk Fauth <dirk.fauth>
Status: CLOSED FIXED QA Contact:
Severity: major    
Priority: P3 CC: dirk.fauth
Version: 2.0.2   
Target Milestone: 2.0.3   
Hardware: PC   
OS: Windows 7   
See Also: https://git.eclipse.org/r/c/nattable/org.eclipse.nebula.widgets.nattable/+/193931
https://git.eclipse.org/c/nattable/org.eclipse.nebula.widgets.nattable.git/commit/?id=33b78c3a31ea524a048681fef9095e55ccfbd121
Whiteboard:

Description Florian Müller CLA 2022-03-17 11:08:34 EDT
I expected "HierarchicalHelper.deNormalize(input, false, propertyNames)" to 
1. return no parent objects when there are children
2. return HierarchicalWrappers with "null" objects in lower levels for parents without children.

The method HierarchicalHelper.deNormalizeWithDirectChildren(...) even states it returns "[...] a collection with only the given parent object if that object has not children.".

But this is not true when HierarchicalHelper.getDataValue(...) returns an empty list (instead of null or an object that is no collection) and the parameter "addParentObject" is false.

In that case, the object is discarded completely, and won't be returned by HierarchicalHelper.deNormalize(...).

Maybe a check for isEmpty() should be added in HierarchicalHelper.deNormalizeWithDirectChildren(...) !?
Comment 1 Dirk Fauth CLA 2022-06-03 02:16:15 EDT
IMHO there is a misunderstanding of the behavior of the HierarchicalHelper and the de-normalization.

Your first assumption that there should be "no parent objects when there are children". I can see that this is true from the perspective of the flattened tree structure. Given the following data structure:

Car 1
Car 2
  Motor 1
  Motor 2

calling HierarchicalHelper.deNormalize(input, false, propertyNames) should produce a new collection of HierarchicalWrappers with only three rows instead of four:
Car 1 - null - null
Car 2 - Motor 1 - null
Car 2 - Motor 2 - null

-> This is what flattens means. Creating new wrappers that build list from the tree by combining parent and childs. The result is NOT dropping the parent in the wrappers.


Coming to your second assumption "return HierarchicalWrappers with "null" objects in lower levels for parents without children". Well that happens as shown above. Additionally if you set "addParentObject" to true produces this type of collection with four rows:

Car 1 - null - null
Car 2 - null - null
Car 2 - Motor 1 - null
Car 2 - Motor 2 - null

The next sentence actually confuses me: "But this is not true when HierarchicalHelper.getDataValue(...) returns an empty list (instead of null or an object that is no collection) and the parameter "addParentObject" is false." Especially in combination with "Maybe a check for isEmpty() should be added"

First: the assumption of the HierarchicalHelper is that the tree structure is build up in a way that children are stored in a collection in the parent object. It will not work if the children are no collections. And isEmpty() btw can also only work on a collection and also an empty list is a collection. 

Second: the process is recursive, means the parent is already added before.

From my point of view everything works as intended. If you still think it is incorrect please provide an example where you think the flattening of the structure should produce something else. Maybe I missed a use case, but I don't get it from your explanation.
Comment 2 Florian Müller CLA 2022-06-03 04:43:05 EDT
Sorry.. should've added an example right away.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.nebula.widgets.nattable.hierarchical.HierarchicalHelper;
import org.eclipse.nebula.widgets.nattable.hierarchical.HierarchicalWrapper;

public class Node {

    private final String name;

    private final Collection<Node> children;

    public Node(final String name, final Collection<Node> children) {
        this.name = name;
        this.children = children;
    }

    public Collection<Node> getChildren() {
        return children;
    }

    @Override
    public String toString() {
        return name + (children != null ? children : "");
    }

    public static void main(final String[] args) {
        // car1, children null => added
        final Node car1 = new Node("car1", null);

        // car2, children NOT null, but empty => NOT added !
        final Node car2 = new Node("car2", new ArrayList<Node>());

        // car 3, children not null and not empty => added
        final Node car3 = new Node("car3", Collections.singleton(new Node("motor1", null)));

        final String[] propertyNames = new String[] { "name", "children.name" };

        final List<HierarchicalWrapper> deNormalized = HierarchicalHelper.deNormalize(Arrays.asList(car1, car2, car3), false, propertyNames);
        for (final HierarchicalWrapper h : deNormalized) {
            System.out.println(h.getObject(0));
        }
    }

}



Output is:
car1
car3[motor1]

=> "car2" is missing.
Comment 3 Florian Müller CLA 2022-06-03 04:59:51 EDT
I think the problem is HierarchicalHelper.deNormalizeWithDirectChildren(...) checking "child instanceof Collection<?>", but not "child.isEmpty()".

In my example the former is true, but the latter is false for "car2", so no parent is added (because addParentObject is false), and an empty result is returned.
Comment 4 Eclipse Genie CLA 2022-06-03 05:42:29 EDT
New Gerrit change created: https://git.eclipse.org/r/c/nattable/org.eclipse.nebula.widgets.nattable/+/193931
Comment 5 Dirk Fauth CLA 2022-06-03 05:46:07 EDT
Not I get the point. If the child collection is not null but an empty collection, the processing is incorrect.

I have added the isEmpty() check and a test case to verify this.
Comment 7 Florian Müller CLA 2022-06-03 07:39:16 EDT
(In reply to Dirk Fauth from comment #5)
> Now I get the point. If the child collection is not null but an empty
> collection, the processing is incorrect.
> 
> I have added the isEmpty() check and a test case to verify this.

Thank you very much!
Comment 8 Dirk Fauth CLA 2022-08-09 02:29:53 EDT
Released with 2.0.3