Class YXmlFragment

java.lang.Object
net.carcdr.ycrdt.YXmlFragment
All Implemented Interfaces:
Closeable, AutoCloseable

public class YXmlFragment extends Object implements Closeable
Represents a fragment of XML content in a Y-CRDT document. A fragment is a container for XML nodes (elements and text) and serves as the root of an XML tree structure.

XML fragments support hierarchical structures, allowing elements and text nodes to be organized in a tree. Unlike the simpler YXmlElement and YXmlText which wrap single nodes, a fragment can contain multiple root-level children.

Example usage:


 try (YDoc doc = new YDoc();
      YXmlFragment fragment = doc.getXmlFragment("document")) {

     // Insert an element
     fragment.insertElement(0, "div");

     // Insert text
     fragment.insertText(1, "Hello World");

     // Get number of children
     System.out.println("Children: " + fragment.length());

     // Get XML string representation
     System.out.println(fragment.toXmlString());
 }
 

This class implements AutoCloseable and should be used with try-with-resources to ensure proper cleanup of native resources.

Since:
0.2.0
  • Method Details

    • length

      public int length()
      Returns the number of children in this fragment.
      Returns:
      the number of child nodes
      Throws:
      IllegalStateException - if this fragment has been closed
    • length

      public int length(YTransaction txn)
      Returns the number of children in this fragment using an existing transaction.
      Parameters:
      txn - The transaction to use for this operation
      Returns:
      the number of child nodes
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
    • insertElement

      public void insertElement(int index, String tag)
      Inserts an XML element as a child at the specified index.
      Parameters:
      index - the index at which to insert (0-based)
      tag - the tag name for the element (e.g., "div", "span")
      Throws:
      IllegalStateException - if this fragment has been closed
      IllegalArgumentException - if tag is null
      IndexOutOfBoundsException - if index is negative or greater than length()
    • insertElement

      public void insertElement(YTransaction txn, int index, String tag)
      Inserts an XML element as a child at the specified index within an existing transaction.

      Use this method to batch multiple operations:

      
       try (YTransaction txn = doc.beginTransaction()) {
           fragment.insertElement(txn, 0, "div");
           fragment.insertElement(txn, 1, "span");
       }
       
      Parameters:
      txn - Transaction handle
      index - the index at which to insert (0-based)
      tag - the tag name for the element (e.g., "div", "span")
      Throws:
      IllegalArgumentException - if txn or tag is null
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative or greater than length()
    • insertText

      public void insertText(int index, String content)
      Inserts an XML text node as a child at the specified index.
      Parameters:
      index - the index at which to insert (0-based)
      content - the text content
      Throws:
      IllegalStateException - if this fragment has been closed
      IllegalArgumentException - if content is null
      IndexOutOfBoundsException - if index is negative or greater than length()
    • insertText

      public void insertText(YTransaction txn, int index, String content)
      Inserts an XML text node as a child at the specified index within an existing transaction.

      Use this method to batch multiple operations:

      
       try (YTransaction txn = doc.beginTransaction()) {
           fragment.insertText(txn, 0, "Hello");
           fragment.insertText(txn, 1, "World");
       }
       
      Parameters:
      txn - Transaction handle
      index - the index at which to insert (0-based)
      content - the text content
      Throws:
      IllegalArgumentException - if txn or content is null
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative or greater than length()
    • remove

      public void remove(int index, int length)
      Removes children from this fragment.
      Parameters:
      index - the starting index (0-based)
      length - the number of children to remove
      Throws:
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if the range is invalid
    • remove

      public void remove(YTransaction txn, int index, int length)
      Removes children from this fragment within an existing transaction.

      Use this method to batch multiple operations:

      
       try (YTransaction txn = doc.beginTransaction()) {
           fragment.remove(txn, 0, 1);
           fragment.remove(txn, 0, 1);
       }
       
      Parameters:
      txn - Transaction handle
      index - the starting index (0-based)
      length - the number of children to remove
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if the range is invalid
    • getNodeType

      public YXmlNode.NodeType getNodeType(int index)
      Gets the type of the child node at the specified index.
      Parameters:
      index - the index of the child (0-based)
      Returns:
      the node type, or null if index is out of bounds
      Throws:
      IllegalStateException - if this fragment has been closed
    • getNodeType

      public YXmlNode.NodeType getNodeType(YTransaction txn, int index)
      Gets the type of the child node at the specified index using an existing transaction.
      Parameters:
      txn - The transaction to use for this operation
      index - the index of the child (0-based)
      Returns:
      the node type, or null if index is out of bounds
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
    • getChild

      public Object getChild(int index)
      Retrieves a child node at the specified index.

      This generic method automatically returns the correct type (YXmlElement or YXmlText) based on the child node type. This is more convenient than calling getNodeType(int) followed by type-specific getters.

      Example usage:

      
       try (YDoc doc = new YDoc();
            YXmlFragment fragment = doc.getXmlFragment("doc")) {
           fragment.insertElement(0, "div");
           fragment.insertText(1, "Hello");
      
           // Generic access - automatically returns correct type
           Object child0 = fragment.getChild(0); // Returns YXmlElement
           Object child1 = fragment.getChild(1); // Returns YXmlText
      
           if (child0 instanceof YXmlElement) {
               YXmlElement elem = (YXmlElement) child0;
               // Use element...
               elem.close();
           }
       }
       
      Parameters:
      index - the index of the child node (0-based)
      Returns:
      a YXmlElement or YXmlText depending on the child type, or null if the index is out of bounds
      Throws:
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative
    • getElement

      public YXmlElement getElement(int index)
      Retrieves a child element at the specified index.

      This method returns a new YXmlElement instance that wraps the child element at the given index. The returned element is independent and must be closed separately using try-with-resources or by calling YXmlElement.close().

      Example usage:

      
       try (YDoc doc = new YDoc();
            YXmlFragment fragment = doc.getXmlFragment("doc")) {
           fragment.insertElement(0, "div");
      
           // Retrieve the element
           try (YXmlElement div = fragment.getElement(0)) {
               div.setAttribute("class", "container");
               System.out.println(div.getTag()); // "div"
           }
       }
       
      Parameters:
      index - the index of the child element (0-based)
      Returns:
      a YXmlElement wrapping the child element, or null if the child at the given index is not an element or the index is out of bounds
      Throws:
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative
    • getElement

      public YXmlElement getElement(YTransaction txn, int index)
      Retrieves a child element at the specified index using an existing transaction.
      Parameters:
      txn - The transaction to use for this operation
      index - the index of the child element (0-based)
      Returns:
      a YXmlElement wrapping the child element, or null if the child at the given index is not an element or the index is out of bounds
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative
    • getText

      public YXmlText getText(int index)
      Retrieves a child text node at the specified index.

      This method returns a new YXmlText instance that wraps the child text node at the given index. The returned text node is independent and must be closed separately using try-with-resources or by calling YXmlText.close().

      Example usage:

      
       try (YDoc doc = new YDoc();
            YXmlFragment fragment = doc.getXmlFragment("doc")) {
           fragment.insertText(0, "Hello");
      
           // Retrieve the text node
           try (YXmlText text = fragment.getText(0)) {
               text.push(" World");
               System.out.println(text.toString()); // "Hello World"
           }
       }
       
      Parameters:
      index - the index of the child text node (0-based)
      Returns:
      a YXmlText wrapping the child text node, or null if the child at the given index is not a text node or the index is out of bounds
      Throws:
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative
    • getText

      public YXmlText getText(YTransaction txn, int index)
      Retrieves a child text node at the specified index using an existing transaction.
      Parameters:
      txn - The transaction to use for this operation
      index - the index of the child text node (0-based)
      Returns:
      a YXmlText wrapping the child text node, or null if the child at the given index is not a text node or the index is out of bounds
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
      IndexOutOfBoundsException - if index is negative
    • toXmlString

      public String toXmlString()
      Returns the XML string representation of this fragment. This includes all child nodes serialized as XML.
      Returns:
      the XML string
      Throws:
      IllegalStateException - if this fragment has been closed
    • toXmlString

      public String toXmlString(YTransaction txn)
      Returns the XML string representation of this fragment using an existing transaction.
      Parameters:
      txn - The transaction to use for this operation
      Returns:
      the XML string
      Throws:
      IllegalArgumentException - if txn is null
      IllegalStateException - if this fragment has been closed
    • toString

      public String toString()
      Returns the XML string representation of this fragment. Equivalent to toXmlString().
      Overrides:
      toString in class Object
      Returns:
      the XML string
    • observe

      public YSubscription observe(YObserver observer)
      Registers an observer to be notified when this XML fragment changes.

      The observer will be called whenever child nodes are added, removed, or modified in this fragment. The observer receives a YEvent containing details about the changes.

      Example:

      
       try (YDoc doc = new YDoc();
            YXmlFragment fragment = doc.getXmlFragment("document");
            YSubscription sub = fragment.observe(event -> {
                System.out.println("Fragment changed!");
                for (YChange change : event.getChanges()) {
                    // Handle change
                }
            })) {
           fragment.insertElement(0, "div"); // Observer is called
       }
       
      Parameters:
      observer - The observer to register (must not be null)
      Returns:
      A subscription handle that can be used to unregister the observer
      Throws:
      IllegalArgumentException - if observer is null
      IllegalStateException - if this fragment has been closed
    • unobserveById

      public void unobserveById(long subscriptionId)
      Unregisters an observer by its subscription ID.

      This method is typically called automatically when a YSubscription is closed. Users should prefer using try-with-resources with YSubscription rather than calling this method directly.

      Parameters:
      subscriptionId - The ID of the subscription to remove
    • close

      public void close()
      Closes this fragment and releases native resources. After calling this method, the fragment cannot be used.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
    • isClosed

      public boolean isClosed()
      Checks if this fragment has been closed.
      Returns:
      true if closed, false otherwise