Class TreeNode

java.lang.Object
org.apache.sis.metadata.TreeNode
All Implemented Interfaces:
TreeTable.Node
Direct Known Subclasses:
TreeNode.Element

class TreeNode extends Object implements TreeTable.Node
A node in a TreeTableView view. The TreeTableView class is used directly only for the root node, or for nodes containing a fixed value instead of a value fetched from the metadata object. For all other nodes, the actual node class shall be either TreeNode.Element or TreeNode.CollectionElement.

The value of a node is extracted from the metadata object by getUserObject(). For each instance of TreeTableView, that value is always a singleton, never a collection. If a metadata property is a collection, then there is an instance of the TreeNode.CollectionElement subclass for each element in the collection.

The newChild() operation is supported if the node is not a leaf. The user shall set the identifier and the value, in that order, before any other operation on the new child. See newChild() javadoc for an example.

API note: This class is not serializable because the values of the TreeNode.Element.indexInData and TreeNode.CollectionElement.indexInList fields may not be stable. The former may be invalid if the node is serialized and deserialized by two different versions of Apache SIS having properties in different order. The second may be invalid if the collection is not guaranteed to preserve order on serialization (e.g. CodeListSet with user supplied elements, in which case the elements order depends on the instantiation order).
Since:
0.3
Version:
1.0
  • Field Details

    • LEAF

      private static final Collection<TreeTable.Node> LEAF
      The collection of children to return when the node does not allow children (i.e. is a leaf). This constant is also used as a sentinel value by isLeaf().

      We choose an empty set instead of an empty list because TreeNodeChildren does not implement the List interface. So we are better to never give to the user a collection implementing List in order to signal incorrect casts sooner.

    • table

      final TreeTableView table
      The table for which this node is an element. Contains information like the metadata standard and the value existence policy.

      All TreeNode instances in the same tree have a reference to the same TreeTableView instance.

    • parent

      private final TreeNode parent
      The parent of this node to be returned by getParent(), or null if this node is the root of the tree.
      See Also:
    • metadata

      final Object metadata
      The metadata object from which the getUserObject() method will fetch the value. The value is fetched in different ways, which depend on the TreeNode subclass:
      • For TreeNode (the root of the tree), the value is directly metadata.
      • For TreeNode.Element (a metadata property which is not a collection), the value is accessor.get(indexInData, metadata).
      • For TreeNode.CollectionElement (an element in a collection), another index is used for fetching the element in that collection.
      This field shall never be null.
      See Also:
    • baseType

      final Class<?> baseType
      The return type of the getter method that provides the value encapsulated by this node. This information is used for filtering aspects when a class opportunistically implements many interfaces. This value is part of the CacheKey needed for invoking MetadataStandard methods.
    • name

      private transient CharSequence name
      The value of TableColumn.NAME, computed by getName() then cached.
      See Also:
    • children

      private transient Collection<TreeTable.Node> children
      The children of this node, or null if not yet computed. If and only if the node cannot have children (i.e. is a leaf), then this field is set to LEAF.
      See Also:
    • cachedValue

      transient Object cachedValue
      The value which existed when the TreeNodeChildren.iterator() traversed this node. This value is cached on the assumption that users will ask for value or for children soon after they iterated over this node. The cached value is cleared after its first use.

      This value shall be either null, or the exact same value than what a call to getUserObject() would return, assuming that the underlying metadata object didn't changed.

      The purpose of this cache is to avoid invoking (by reflection) the same getter methods twice in common situations like the TreeTableView.toString() implementation or in Graphical User Interface. However, we may remove this field in any future SIS version if experience shows that it is more problematic than helpful.

  • Constructor Details

    • TreeNode

      TreeNode(TreeTableView table, Object metadata, Class<?> baseType)
      Creates the root node of a new metadata tree table.
      Parameters:
      table - the table which is creating this root node.
      metadata - the root metadata object (cannot be null).
      baseType - the return type of the getter method that provides the value encapsulated by this node.
    • TreeNode

      private TreeNode(TreeNode parent, Object metadata, Class<?> baseType)
      Creates a new child for an element of the given metadata. This constructor is for the TreeNode.Element subclass only.
      Parameters:
      parent - the parent of this node.
      metadata - the metadata object for which this node will be a value.
      baseType - the return type of the getter method that provides the value encapsulated by this node.
  • Method Details

    • isMetadata

      final boolean isMetadata(Class<?> type)
      Returns true if nodes for values of the given type can be expanded with more children. A return value of false means that values of the given type are leaves.
    • key

      private CacheKey key()
      Returns the key to use for calls to MetadataStandard methods. This key is used only for some default method implementations in the root node; children will use the class of their node value instead.
    • getIdentifier

      String getIdentifier()
      Returns the UML identifier defined by the standard. The default implementation is suitable only for the root node, since it returns the class identifier. Subclasses must override in order to return the property identifier instead.
    • getIndex

      Integer getIndex()
      Returns the index in the collection if the metadata property type is a collection, or null otherwise. The (identifier, index) pair can be used as a primary key for identifying this node among its siblings.
    • getName

      CharSequence getName()
      Gets the human-readable name of this node. The name shall be stable, since it will be cached by the caller. The name typically contains identifier and index information, eventually localized.

      The default implementation is suitable only for the root node - subclasses must override.

    • getRemarks

      CharSequence getRemarks()
      Gets remarks about the value in this node, or null if none.
    • appendIdentifier

      void appendIdentifier(StringBuilder buffer)
      Appends an identifier for this node in the given buffer, for toString() implementation. The appended value is similar to the value returned by getIdentifier() (except for the root node), but may contains additional information like the index in a collection.

      The default implementation is suitable only for the root node - subclasses must override.

    • getUserObject

      public Object getUserObject()
      The metadata value for this node, to be returned by getValue(TableColumn.VALUE). The default implementation is suitable only for the root node - subclasses must override.
      Specified by:
      getUserObject in interface TreeTable.Node
      Returns:
      any object stored at this node by the user, or null if none.
    • setUserObject

      void setUserObject(Object value) throws UnsupportedOperationException
      Sets the metadata value for this node. Subclasses must override this method.
      Throws:
      UnsupportedOperationException - if the metadata value is not writable.
    • isWritable

      boolean isWritable()
      Returns true if the metadata value can be set. Subclasses must override this method.
    • equals

      public boolean equals(Object other)
      Returns true if the given object is of the same class than this node and contains a reference to the same metadata object. Since TreeNode generates all content from the wrapped metadata, this condition should ensure that two equal nodes have the same values and children.
      Specified by:
      equals in interface TreeTable.Node
      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.
    • hashCode

      public int hashCode()
      Returns a hash code value for this node.
      Specified by:
      hashCode in interface TreeTable.Node
      Overrides:
      hashCode in class Object
      Returns:
      a hash code for this node, potentially based on values and children but ignoring parent.
    • getParent

      public final TreeTable.Node getParent()
      Returns the parent node, or null if this node is the root of the tree.
      Specified by:
      getParent in interface TreeTable.Node
      Returns:
      the parent, or null if none.
    • isLeaf

      public final boolean isLeaf()
      Returns false if the value is a metadata object (and consequently can have children), or true if the value is not a metadata object.
      Specified by:
      isLeaf in interface TreeTable.Node
      Returns:
      true if this node cannot have any children.
    • getChildren

      public final Collection<TreeTable.Node> getChildren()
      Returns the children of this node, or an empty set if none. Only metadata object can have children.
      Specified by:
      getChildren in interface TreeTable.Node
      Returns:
      the children, or an empty collection if none.
    • newChild

      public final TreeTable.Node newChild() throws UnsupportedOperationException
      Returns a proxy for a new property to be defined in the metadata object. The user shall set the identifier and the value, in that order, before any other operation on the new child. Example: Do not keep a reference to the returned node for a long time, since it is only a proxy toward the real node to be created once the identifier is known.
      Specified by:
      newChild in interface TreeTable.Node
      Returns:
      the new child.
      Throws:
      UnsupportedOperationException - if this node is a leaf.
    • getCompactChildren

      private TreeNodeChildren getCompactChildren()
      Returns the children if the value policy is ValueExistencePolicy.COMPACT, or null otherwise.
    • getValue

      public final <V> V getValue(TableColumn<V> column)
      Returns the value of this node in the given column, or null if none. This method verifies the column argument, then delegates to getName(), getUserObject() or other properties.
      Specified by:
      getValue in interface TreeTable.Node
      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

      public final <V> void setValue(TableColumn<V> column, V value) throws UnsupportedOperationException
      Sets the value if the given column is TableColumn.VALUE. This method verifies the column argument, then delegates to setUserObject(Object).

      This method does not accept null value, because setting a singleton property to null with ValueExistencePolicy.NON_EMPTY is equivalent to removing the property, and setting a collection element to null is not allowed. Those various behavior are at risk of causing confusion, so we are better to never allow null.

      Specified by:
      setValue in interface TreeTable.Node
      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:
      UnsupportedOperationException - if values in the given column cannot be modified.
      See Also:
    • unmodifiableCellValue

      private String unmodifiableCellValue(TableColumn<?> column)
      Returns the error message for an unmodifiable cell value in the given column.
    • isEditable

      public final boolean isEditable(TableColumn<?> column)
      Returns true if the given column is TableColumn.VALUE and the property is writable, or false in all other cases. This method verifies the column argument, then delegates to isWritable().
      Specified by:
      isEditable in interface TreeTable.Node
      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.
    • toString

      public final String toString()
      Returns a string representation of this node for debugging purpose.
      Overrides:
      toString in class Object
    • appendStringTo

      final void appendStringTo(StringBuilder buffer)
      Implementation of toString() appending the string representation in the given buffer.