Interface NodeBuilder

All Known Implementing Classes:
MemoryNodeBuilder, ReadOnlyBuilder, SegmentNodeBuilder

public interface NodeBuilder
Builder interface for constructing new node states.

A node builder can be thought of as a mutable version of a node state. In addition to property and child node access methods like the ones that are already present in the NodeState interface, the NodeBuilder interface contains the following key methods:

  • The setProperty and removeProperty methods for modifying properties
  • The getChildNode method for accessing or modifying an existing subtree
  • The setChildNode and removeChildNode methods for adding, replacing or removing a subtree
  • The exists method for checking whether the node represented by a builder exists or is accessible
  • The getNodeState method for getting a frozen snapshot of the modified content tree
All the builders acquired from the same root builder instance are linked so that changes made through one instance automatically become visible in the other builders. For example:
     NodeBuilder rootBuilder = root.builder();
     NodeBuilder fooBuilder = rootBuilder.getChildNode("foo");
     NodeBuilder barBuilder = fooBuilder.getChildNode("bar");

     assert !barBuilder.getBoolean("x");
     fooBuilder.getChildNode("bar").setProperty("x", Boolean.TRUE);
     assert barBuilder.getBoolean("x");

     assert barBuilder.exists();
     fooBuilder.removeChildNode("bar");
     assert !barBuilder.exists();
 
The getNodeState method returns a frozen, immutable snapshot of the current state of the builder. Providing such a snapshot can be somewhat expensive especially if there are many changes in the builder, so the method should generally only be used as the last step after all intended changes have been made. Meanwhile the accessors in the NodeBuilder interface can be used to provide efficient read access to the current state of the tree being modified.

The node states constructed by a builder often retain an internal reference to the base state used by the builder. This allows common node state comparisons to perform really.

  • Method Details

    • getNodeState

      @NotNull @NotNull NodeState getNodeState()
      Returns an immutable node state that matches the current state of the builder.
      Returns:
      immutable node state
    • getBaseState

      @NotNull @NotNull NodeState getBaseState()
      Returns the original base state that this builder is modifying. The return value may be non-existent (i.e. its exists method returns false) if this builder represents a new node that didn't exist in the base content tree.
      Returns:
      base node state, possibly non-existent
    • exists

      boolean exists()
      Checks whether this builder represents a node that exists.
      Returns:
      true if the node exists, false otherwise
    • isNew

      boolean isNew()
      Check whether this builder represents a new node, which is not present in the base state.
      Returns:
      true for a new node
    • isNew

      boolean isNew(String name)
      Check whether the named property is new, i.e. not present in the base state.
      Parameters:
      name - property name
      Returns:
      true for a new property
    • isModified

      boolean isModified()
      Check whether this builder represents a modified node, which has either modified properties or removed or added child nodes.
      Returns:
      true for a modified node
    • isReplaced

      boolean isReplaced()
      Check whether this builder represents a node that used to exist but was then replaced with other content, for example as a result of a setChildNode(String) call.
      Returns:
      true for a replaced node
    • isReplaced

      boolean isReplaced(String name)
      Check whether the named property exists in the base state but is replaced with other content, for example as a result of a setProperty(PropertyState) call.
      Parameters:
      name - property name
      Returns:
      true for a replaced property
    • getChildNodeCount

      long getChildNodeCount(long max)
      Returns the current number of child nodes.

      If an implementation does know the exact value, it returns it (even if the value is higher than max). If the implementation does not know the exact value, and the child node count is higher than max, it may return Long.MAX_VALUE. The cost of the operation is at most O(max).

      Parameters:
      max - the maximum value
      Returns:
      number of child nodes
    • getChildNodeNames

      @NotNull @NotNull Iterable<String> getChildNodeNames()
      Returns the names of current child nodes.
      Returns:
      child node names
    • hasChildNode

      boolean hasChildNode(@NotNull @NotNull String name)
      Checks whether the named child node currently exists.
      Parameters:
      name - child node name
      Returns:
      true if the named child node exists, false otherwise
    • child

      @NotNull @NotNull NodeBuilder child(@NotNull @NotNull String name) throws IllegalArgumentException
      Returns a builder for constructing changes to the named child node. If the named child node does not already exist, a new empty child node is automatically created as the base state of the returned child builder. Otherwise the existing child node state is used as the base state of the returned builder.

      All updates to the returned child builder will implicitly affect also this builder, as if a setNode(name, childBuilder.getNodeState()) method call had been made after each update. Repeated calls to this method with the same name will return the same child builder instance until an explicit setChildNode(String, NodeState) or remove() call is made, at which point the link between this builder and a previously returned child builder for that child node name will get broken.

      Parameters:
      name - name of the child node
      Returns:
      child builder
      Throws:
      IllegalArgumentException - if the given name string is empty or contains the forward slash character
      Since:
      Oak 0.6
    • getChildNode

      @NotNull @NotNull NodeBuilder getChildNode(@NotNull @NotNull String name) throws IllegalArgumentException
      Returns a builder for constructing changes to the named child node. If the named child node does not already exist, the returned builder will refer to a non-existent node and trying to modify it will cause IllegalStateExceptions to be thrown.
      Parameters:
      name - name of the child node
      Returns:
      child builder, possibly non-existent
      Throws:
      IllegalArgumentException - if the given name string is empty or contains the forward slash character
      Since:
      Oak 0.7
    • setChildNode

      @NotNull @NotNull NodeBuilder setChildNode(@NotNull @NotNull String name) throws IllegalArgumentException
      Adds the named child node and returns a builder for modifying it. Possible previous content in the named subtree is removed.
      Parameters:
      name - name of the child node
      Returns:
      child builder
      Throws:
      IllegalArgumentException - if the given name string is empty or contains the forward slash character
      Since:
      Oak 0.7
    • setChildNode

      @NotNull @NotNull NodeBuilder setChildNode(@NotNull @NotNull String name, @NotNull @NotNull NodeState nodeState) throws IllegalArgumentException
      Adds or replaces a subtree.
      Parameters:
      name - name of the child node containing the new subtree
      nodeState - subtree
      Returns:
      child builder
      Throws:
      IllegalArgumentException - if the given name string is empty or contains the forward slash character
    • remove

      boolean remove()
      Remove this child node from its parent.
      Returns:
      true for existing nodes, false otherwise
    • moveTo

      boolean moveTo(@NotNull @NotNull NodeBuilder newParent, @NotNull @NotNull String newName) throws IllegalArgumentException
      Move this child to a new parent with a new name. When the move succeeded this builder has been moved to newParent as child newName. Otherwise neither this builder nor newParent are modified.

      The move succeeds if both, this builder and newParent exist, there is no child with newName at newParent and newParent is not in the subtree of this builder.

      The move fails if the this builder or newParent does not exist or if there is already a child newName at newParent.

      For all remaining cases (e.g. moving a builder into its own subtree) it is left to the implementation whether the move succeeds or fails as long as the state of the involved builder stays consistent.

      Parameters:
      newParent - builder for the new parent.
      newName - name of this child at the new parent
      Returns:
      true on success, false otherwise
      Throws:
      IllegalArgumentException - if the given name string is empty or contains the forward slash character
    • getPropertyCount

      long getPropertyCount()
      Returns the current number of properties.
      Returns:
      number of properties
    • getProperties

      @NotNull @NotNull Iterable<? extends PropertyState> getProperties()
      Returns the current properties.
      Returns:
      current properties
    • hasProperty

      boolean hasProperty(String name)
      Checks whether the named property exists. The implementation is equivalent to getProperty(name) != null, but may be optimized to avoid having to load the property value.
      Parameters:
      name - property name
      Returns:
      true if the named property exists, false otherwise
    • getProperty

      @Nullable @Nullable PropertyState getProperty(String name)
      Returns the current state of the named property, or null if the property is not set.
      Parameters:
      name - property name
      Returns:
      property state
    • getBoolean

      boolean getBoolean(@NotNull @NotNull String name)
      Returns the boolean value of the named property. The implementation is equivalent to the following code, but may be optimized.
       
       PropertyState property = builder.getProperty(name);
       return property != null
           && property.getType() == Type.BOOLEAN
           && property.getValue(Type.BOOLEAN);
       
       
      Parameters:
      name - property name
      Returns:
      boolean value of the named property, or false
    • getString

      @Nullable @Nullable String getString(String name)
      Returns the name value of the named property. The implementation is equivalent to the following code, but may be optimized.
       
       PropertyState property = builder.getProperty(name);
       if (property != null && property.getType() == Type.STRING) {
           return property.getValue(Type.STRING);
       } else {
           return null;
       }
       
       
      Parameters:
      name - property name
      Returns:
      string value of the named property, or null
    • getName

      @Nullable @Nullable String getName(@NotNull @NotNull String name)
      Returns the name value of the named property. The implementation is equivalent to the following code, but may be optimized.
       
       PropertyState property = builder.getProperty(name);
       if (property != null && property.getType() == Type.NAME) {
           return property.getValue(Type.NAME);
       } else {
           return null;
       }
       
       
      Parameters:
      name - property name
      Returns:
      name value of the named property, or null
    • getNames

      @NotNull @NotNull Iterable<String> getNames(@NotNull @NotNull String name)
      Returns the name values of the named property. The implementation is equivalent to the following code, but may be optimized.
       
       PropertyState property = builder.getProperty(name);
       if (property != null && property.getType() == Type.NAMES) {
           return property.getValue(Type.NAMES);
       } else {
           return Collections.emptyList();
       }
       
       
      Parameters:
      name - property name
      Returns:
      name values of the named property, or an empty collection
    • setProperty

      @NotNull @NotNull NodeBuilder setProperty(@NotNull @NotNull PropertyState property) throws IllegalArgumentException
      Set a property state
      Parameters:
      property - The property state to set
      Returns:
      this builder
      Throws:
      IllegalArgumentException - if the property name is empty or contains the forward slash character
    • setProperty

      @NotNull <T> @NotNull NodeBuilder setProperty(String name, @NotNull T value) throws IllegalArgumentException
      Set a property state
      Type Parameters:
      T - The type of this property. Must be one of String, Blob, byte[], Long, Integer, Double, Boolean, BigDecimal
      Parameters:
      name - The name of this property
      value - The value of this property
      Returns:
      this builder
      Throws:
      IllegalArgumentException - if T is not one of the above types, or if the property name is empty or contains the forward slash character
    • setProperty

      @NotNull <T> @NotNull NodeBuilder setProperty(String name, @NotNull T value, Type<T> type) throws IllegalArgumentException
      Set a property state
      Type Parameters:
      T - The type of this property.
      Parameters:
      name - The name of this property
      value - The value of this property
      Returns:
      this builder
      Throws:
      IllegalArgumentException - if the property name is empty or contains the forward slash character
    • removeProperty

      @NotNull @NotNull NodeBuilder removeProperty(String name)
      Remove the named property. This method has no effect if a property of the given name does not exist.
      Parameters:
      name - name of the property
    • createBlob

      Blob createBlob(InputStream stream) throws IOException
      Throws:
      IOException