Interface TreeTable.Node

All Known Implementing Classes:
Default­Tree­Table​.Node
Enclosing interface:
Tree­Table

public static interface TreeTable.Node
A node in a tree combined with a row in a table. A Tree­Table​.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 predefined columns. The list of allowed columns is given by the Tree­Table​.get­Columns() method.

The following table summarizes the tree-related and table-related methods:

Tree-table methods
Tree-related methods Table-related methods
In addition, each Node can be associated to an arbitrary object by the get­User­Object() method. This object is not used directly by the tree tables.
Since:
0.3
  • Method Details

    • getParent

      TreeTable.Node getParent()
      Returns the parent node, or null if this node is the root of the tree.

      There is intentionally no set­Parent(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.

      Returns:
      the parent, or null if none.
    • isLeaf

      boolean isLeaf()
      Returns true if this node cannot 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). Tree­Table­Format does not use this value.

      Returns:
      true if this node cannot have any children.
    • getChildren

      Collection<TreeTable.Node> getChildren()
      Returns the children of this node. The returned collection may or may not be modifiable, at implementation choice. If the collection is modifiable, then it shall be live, i.e. any modification to the returned collection are reflected immediately in the tree. This allows addition or removal of child nodes as below:
      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.
      Returns:
      the children, or an empty collection if none.
    • newChild

      Creates a new child with the same columns than the other children, and adds it to the children collection. The new child is typically added at the end of the collection, but this is not mandatory: implementations can add the child at whatever position they see fit.
      Returns:
      the new child.
      Throws:
      Unsupported­Operation­Exception - if this node cannot add new children.
    • getValue

      <V> V getValue(TableColumn<V> column)
      Returns the value in the given column, or null if none.
      Type Parameters:
      V - the base type of values in the given column.
      Parameters:
      column - identifier of the column from which to get the value.
      Returns:
      the value in the given column, or null if none.
      See Also:
    • setValue

      <V> void setValue(TableColumn<V> column, V value) throws IllegalArgumentException, UnsupportedOperationException
      Sets the value for the given column (optional operation). The is­Editable(Table­Column) method can be invoked before this setter method for determining if the given column is modifiable.
      Type Parameters:
      V - the base type of values in the given column.
      Parameters:
      column - identifier of the column into which to set the value.
      value - the value to set.
      Throws:
      Illegal­Argument­Exception - if the given column is not a legal column for this node.
      Unsupported­Operation­Exception - if values in the given column cannot be modified.
      See Also:
    • isEditable

      boolean isEditable(TableColumn<?> column)
      Determines whether the value in the specified column is editable. If the given column is not a legal column for this Node instance, then this method returns false.
      Parameters:
      column - the column to query.
      Returns:
      true if the given column is a legal column for this Node implementation and the corresponding value is editable, or false otherwise.
    • getUserObject

      Object getUserObject()
      Returns the user object associated to this node. The user object is for information purpose only and does not appear in the rendered tree. It is typically a Java object whose content is splitted into the various table columns.

      Example

      If a City­Location class is defined as a (city name, latitude, longitude) tuple, then a Tree­Table​.Node could be defined to have 3 columns for the above 3 tuple components, and the user object could be the original City­Location instance.
      Returns:
      any object stored at this node by the user, or null if none.
    • equals

      boolean equals(Object other)
      Returns 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: The node returned by get­Parent() 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.

      Purpose of this method: example with ISO metadata

      Consider the following tree made of ISO 19115 metadata objects: a platform containing a list of instruments, and an instrument containing a reference to the platform on which the instrument is installed. In this example, nodes 2 and 4 contain a reference to the same Platform instance, so we have a cyclic graph:
      Metadata tree example
      Node 1: Acquisition information
      Node 2:  └─Platform
      Node 3:     └─Instrument
      Node 4:        └─Platform (same instance than above)
      Node 5:           └─etc…
      The Abstract­Metadata​.as­Tree­Table() 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 Tree­Table 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.

      Flexibility in implementations

      The above list specifies minimal conditions that must be true when two nodes are considered equal. Implementations should not relax those conditions, but are free to make them more restrictive. In particular, many implementations will require that the two nodes are instances of the same class. Some implementations may also perform identity comparisons (with the == operator) between values instead of 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 of 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.
      Overrides:
      equals in class Object
      Parameters:
      other - the other object to compare with this node.
      Returns:
      whether the two objects are nodes with equal values and equal children, ignoring parents.
      Since:
      0.8
    • hashCode

      int hashCode()
      Returns a hash code value consistent with the equals(Object) implementation for this node. If the equals(Object) method has not been overridden, then this hash­Code() 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 hash­Code() 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.
      Overrides:
      hash­Code in class Object
      Returns:
      a hash code for this node, potentially based on values and children but ignoring parent.
      Since:
      0.8