public static interface TreeTable.Node
TreeTable.Node
can be seen as a
tree node associated to a single user object (like ordinary trees),
augmented with the capability to describe some aspects of the user object in pre-defined columns.
The list of allowed columns is given by the TreeTable.getColumns()
method.
The following table summarizes the tree-related and table-related methods:
Tree-related methods | Table-related methods |
---|---|
Node
can be associated to an arbitrary object by the
getUserObject()
method. This object is not used directly by the tree tables.Defined in the sis-utility
module
Modifier and Type | Method and Description |
---|---|
boolean |
equals(Object other)
Returns
true if the given object is a node with the same content than this node. |
Collection<TreeTable.Node> |
getChildren()
Returns the children of this node.
|
TreeTable.Node |
getParent()
Returns the parent node, or
null if this node is the root of the tree. |
Object |
getUserObject()
Returns the user object associated to this node.
|
<V> V |
getValue(TableColumn<V> column)
Returns the value in the given column, or
null if none. |
int |
hashCode()
Returns a hash code value consistent with the
equals(Object) implementation for this node. |
boolean |
isEditable(TableColumn<?> column)
Determines whether the value in the specified column is editable.
|
boolean |
isLeaf()
Returns
true if this node can not have any children. |
TreeTable.Node |
newChild()
Creates a new child with the same columns than the other children, and adds it to
the children collection.
|
<V> void |
setValue(TableColumn<V> column,
V value)
Sets the value for the given column (optional operation).
|
TreeTable.Node getParent()
null
if this node is the root of the tree.
There is intentionally no setParent(Node)
method, as children and parent managements
are highly implementation-dependant. If the children collection is
modifiable, then implementations are encouraged to update automatically the parent when a child
is added to or removed from that collection.
null
if none.boolean isLeaf()
true
if this node can not have any children. The children
collection of a leaf node can only be empty, and adding new child
is an unsupported operation.
This value is provided as a tip for graphical user interfaces, in order to determine if
a node is expandable (even if empty). TreeTableFormat
does not use this value.
true
if this node can not have any children.Collection<TreeTable.Node> getChildren()
TreeTable.Node newNode = new ...; // Create a new node here. parent.getChildren().add(newNode);The collection is often a
List
, but not necessarily. For some implementations like the
metadata tree table view,
compliance to the List
contract is impractical or inefficient.TreeTable.Node newChild() throws UnsupportedOperationException
UnsupportedOperationException
- if this node can not add new children.<V> V getValue(TableColumn<V> column)
null
if none.V
- the base type of values in the given column.column
- identifier of the column from which to get the value.null
if none.TreeTable.getColumns()
<V> void setValue(TableColumn<V> column, V value) throws IllegalArgumentException, UnsupportedOperationException
isEditable(TableColumn)
method can be invoked before this setter method
for determining if the given column is modifiable.V
- the base type of values in the given column.column
- identifier of the column into which to set the value.value
- the value to set.IllegalArgumentException
- if the given column is not a legal column for this node.UnsupportedOperationException
- if values in the given column can not be modified.TreeTable.getColumns()
,
isEditable(TableColumn)
boolean isEditable(TableColumn<?> column)
Node
instance, then this method
returns false
.column
- the column to query.true
if the given column is a legal column for this Node
implementation and the corresponding value is editable, or false
otherwise.Object getUserObject()
CityLocation
class is defined as a (city name, latitude,
longitude) tuple, then a TreeTable.Node
could be defined to have 3 columns for the
above 3 tuple components, and the user object could be the original CityLocation
instance.null
if none.boolean equals(Object other)
true
if the given object is a node with the same content than this node.
For this method, the meaning of same content is defined as below:
Node
.TreeTable.getColumns()
is equals for both nodes.getValue(TableColumn)
are equal for each column.getParent()
shall not be taken in account.
It is necessary to ignore the parent for consistency with clone
and for avoiding infinite recursivity when comparing the children.
A third reason is given in the purpose example below.
Platform
instance, so we have a cyclic graph:
Node 1: | Acquisition information |
---|---|
Node 2: | └─ Platform |
Node 3: | └─ Instrument |
Node 4: | └─ Platform (same instance than above) |
Node 5: | └─ etc… |
AbstractMetadata.asTreeTable()
method gives a view in which each node
has its content fully generated from wrapped metadata object. Consequently a naive walk over the above tree
causes an infinite loop with TreeTable
generating nodes with identical content as we bounce between
Platform
and Instrument
metadata objects. To break this loop, we need to know when the
content of a node (in this example, the wrapped metadata object) has already been visited.
The parent shall not be taken in account since node 2 and 4 have different parents
despite having the same Platform
content.
In this use case, the Node.equals(Object)
implementation needs only to compare the wrapped
metadata (usually given by the user object) since the node content,
including the list of children, is fully determined by those metadata. An identity comparison
(with ==
) is sufficient for the purpose of avoiding infinite recursivity.
==
operator) between values
instead than using Object.equals(Object)
. This flexibility means that even if all above conditions
are true, this is not a guarantee that this method will return true
.
It is okay to not override this method at all since the identity comparison inherited from
Object.equals(Object)
is consistent with this method contract. Alternatively, Node
implementations having a content fully determined by the wrapped user
object need only the following implementation:
@Override public boolean equals(Object obj) { return (obj instanceof MyNode) && ((MyNode) obj).getUserObject() == getUserObject(); }Implementation details may vary, for example in the way to compare
null
user objects or by invoking
Object.equals(Object)
instead than performing identity comparisons. Note however that since this
method purpose is to detect cyclic graphs (see above example), user objects should be compared with
equals(Object)
only if their implementations are known to be safe against infinite recursivity.int hashCode()
equals(Object)
implementation for this node.
If the equals(Object)
method has not been overridden, then this hashCode()
method
should not be overridden neither. Otherwise if this node content (values and
children) is fully generated from the user
object, then the equals(…)
and hashCode()
methods may be implemented like below:
@Override public boolean equals(Object obj) { return (obj instanceof MyNode) && ((MyNode) obj).getUserObject() == getUserObject(); } @Override public int hashCode() { return System.identityHashCode(getUserObject()); }Otherwise this method should compute a hash code based on values and children of this node, ignoring parent.
Copyright © 2010–2017 The Apache Software Foundation. All rights reserved.