Class AbstractContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>

    • Field Detail

      • content

        protected final List<N extends Node> content
    • Constructor Detail

      • AbstractContentNode

        public AbstractContentNode()
    • Method Detail

      • isEmpty

        public boolean isEmpty()
        Specified by:
        isEmpty in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Returns:
        true if this content node is completely empty, which for many such nodes is not valid
      • requireNotEmpty

        protected void requireNotEmpty()
        Verifies that at least one content element has been provided.
        Throws:
        ContentException.ContentRequired - if this content node is still empty
      • validateContentNodeForAppend

        protected void validateContentNodeForAppend​(N node)
        Called on each content node before it is added to validate that the node can be accepted.
        Parameters:
        node - the node that is about to be added
      • content

        public final List<N> content()
        Description copied from interface: ContentNode
        Returns the existing contents of this content node.

        Notes:

        • The returned list cannot be modified directly.
        • Whether it is a live view of the node's contents or a copy is left unspecified. Callers are advised to make an explicit copy of the list if this matters, such as when the node's contents will be modified while iterating over this list.
        • The nodes within the list will generally be mutable. The caller should make an explicit copy of the node before modifying it if the original is not meant to be affected.
        Specified by:
        content in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Returns:
        the existing contents of this content node.
      • content

        @SafeVarargs
        public final C content​(N... content)
        Description copied from interface: ContentNode
        Adds the given nodes as content within this containing node.

        Each content item is validated as acceptable content before it is added. If validation is successful, then it is added to this node's content before the next node is validated, so the validation method is permitted to rely on the ContentNode.content() value being up-to-date at all times.

        If validation fails for a particular content item, then those particular content items are discarded, but any content nodes that follow will still be attempted.

        Specified by:
        content in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Parameters:
        content - the content to add
        Returns:
        this
      • content

        public final C content​(Stream<? extends N> content)
        Description copied from interface: ContentNode
        Adds the given nodes as content within this containing node.

        Each content item is validated as acceptable content before it is added. If validation is successful, then it is added to this node's content before the next node is validated, so the validation method is permitted to rely on the ContentNode.content() value being up-to-date at all times.

        If validation fails for a particular content item, then those particular content items are discarded, but any content nodes that follow will still be attempted.

        Specified by:
        content in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Parameters:
        content - the content to add
        Returns:
        this
      • allNodes

        public Stream<Node> allNodes()
        Description copied from interface: ContentNode
        Produces a stream consisting of the in-order traversal of this node and all of its contents, where any nested ContentNodes are also expanded.

        Example

        If a Doc is constructed from this input:

        
           {
             "type": "paragraph",
             "content": [
               {
                 "type": "text",
                 "text": "Hello "
               },
               {
                 "type": "text",
                 "text": "world",
                 "marks": [
                   {
                     "type": "textColor",
                     "attrs": {
                       "color": "#00ff00"
                     }
                   }
                 ]
               },
               {
                 "type": "text",
                 "text": "!"
               }
             ]
           }
         

        then calling doc.allNodes() would produce the following stream of nodes:

        • The doc node itself

        • The paragraph node

        • The text node containing "Hello "

        • The text node containing "world"

        • The text node containing "!"

        Note that marks are not considered separate nodes; they are part of the containing text node.

        Specified by:
        allNodes in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Returns:
        a stream of this node and the deep expansion of its contents
      • clear

        public C clear()
        Description copied from interface: ContentNode
        Discards all existing content in this node.

        Note that for some node types, it is not valid for the node to be left empty and new content must be added to replace it.

        Specified by:
        clear in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Returns:
        this
      • transformContent

        public void transformContent​(Function<? super N,​? extends N> transformer)
        Description copied from interface: ContentNode
        Applies a transformation to the immediate children of this content node.

        The transformer has the following characteristics:

        1. It will be called once for each piece of content currently held by this parent content node.
        2. It may return that same object to keep that piece of content.
        3. It may return same other object that is suitable for the parent content node, and that node will replace the original value.
        4. It may return null, in which case that content item will be removed, instead.

        WARNING: Once all content items have been processed by the transformer, this method uses ContentNode.replaceContent(List) to perform the update if the structure of the list has changed (that is, if any content items are removed or replaced). In addition to the warnings on that method, note that since the transformer has already been called on the content items, they may have been modified in ways that impact the validity of the content node even if its content item list is left unchanged. If so, this may not be detected until some time later when the node's validity is rechecked for some other reason. Proceed with caution.

        Specified by:
        transformContent in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Parameters:
        transformer - the transforming function
      • transformDescendants

        public <T extends Node> void transformDescendants​(Class<T> targetNodeClass,
                                                          Function<? super T,​? extends T> transformer)
        Description copied from interface: ContentNode
        Applies a transformation to all descendants of this node that match the given type.

        The transformer has the following characteristics:

        1. It will be called once for each piece of content currently held by this content node or any of its descendants that matches the given targetNodeClass.
        2. It may return that same object to keep that node within the content node that contains it.
        3. It may return same other object that is suitable for the parent content node that contained it, and that new node will replace the original value.
        4. It may return null, in which case that content item will be removed, instead.

        WARNING: Once all content items have been processed by the transformer, this method uses ContentNode.replaceContent(List) to perform the update if the structure of the list has changed (that is, if any content items are removed or replaced). In addition to the warnings on that method, note that since the transformer has already been called on the content items, they may have been modified in ways that impact the validity of the content node even if its content item list is left unchanged. If so, this may not be detected until some time later when the node's validity is rechecked for some other reason. Proceed with caution.

        IMPLEMENTATION NOTE

        This method has special support for MediaSingle nodes, which do not implement the ContentNode interface even though they contain child nodes. In particular:
        1. The media and (if present) caption nodes are included in the traversal
        2. If the transformer removes a media node that is inside of a mediaSingle, then that mediaSingle is also removed without visiting its caption.
        Specified by:
        transformDescendants in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        transformer - the transforming function
      • replaceContent

        public final void replaceContent​(List<? extends N> newContent)
        Description copied from interface: ContentNode
        Completely replace this content node's existing content items with the new ones provided. If this results in an exception being thrown (such as rejecting the new first content item in a node like ListItem that has restrictions for it), then the old content is restored before the exception is propagated to the caller.

        WARNING: Although this method tries very hard to ensure that the content node is left in a valid state, it does still allow content to be removed, possibly leaving it entirely empty. Just as with ContentNode.clear(), it is up to the caller to follow this up by adding new content as required to establish a valid state for the content node, or the problem may not be detected until the node is validated during some future use. Proceed with caution.

        Specified by:
        replaceContent in interface ContentNode<C extends AbstractContentNode<C,​N>,​N extends Node>
        Parameters:
        newContent - the new content list for this node
      • contentFieldMaps

        protected List<? extends Map<String,​?>> contentFieldMaps()
      • validate

        public final void validate()
        Description copied from interface: Element
        Verifies that the node is well-formed (including the state of any descendents that it has).
        Specified by:
        validate in interface Element
      • contentNodeValidate

        protected void contentNodeValidate()
      • validateContentItems

        protected final void validateContentItems()
        Validates that each of the content nodes is in a valid state.
      • addContent

        protected final void addContent​(FieldMap map)
      • addContentIfPresent

        protected final void addContentIfPresent​(FieldMap map)
      • contentNodeHashCode

        protected int contentNodeHashCode()
        Allows content nodes that have their own fields to augment the hashCode implementation with a hash of their own field values.

        Implementations need not include the node's class; that is already covered by AbstractNode.hashCode(). Implementations need not include the content, either; that is already covered by AbstractNode.nodeHashCode(), which is expected to be this method's only consumer.

        Just as with the relationship between hashCode, equals, and toString for ordinary Java classes, subclasses of AbstractContentNode should maintain consistent implementations of contentNodeHashCode, contentNodeEquals, and appendContentNodeFields.

        Returns:
        the hash code of any additional field values that belong to a particular type of content node.
        See Also:
        contentNodeEquals(AbstractContentNode), appendContentNodeFields(ToStringHelper)
      • contentNodeEquals

        protected boolean contentNodeEquals​(C other)
        Allows content nodes that have their own fields to augment the equals implementation with tests for their own field values.

        Implementations need not check for identity, null, or a different node class; those are already covered by AbstractNode.equals(Object). Implementations need not check the content(), either; that is already covered by nodeEquals(AbstractContentNode), which is expected to be this method's only consumer.

        Just as with the relationship between hashCode, equals, and toString for ordinary Java classes, subclasses of AbstractContentNode should maintain consistent implementations of contentNodeHashCode, contentNodeEquals, and appendContentNodeFields.

        Returns:
        true if all additional field values that belong to a particular type of content node test as equal; false if differences are found
        See Also:
        contentNodeHashCode(), appendContentNodeFields(ToStringHelper)
      • appendContentNodeFields

        protected void appendContentNodeFields​(AbstractNode.ToStringHelper buf)
        Allows content nodes that have their own fields to augment the toString() implementation with their own field values.

        Each field's value should be provided by calling AbstractNode.ToStringHelper.appendField(String, Object). The value may be null, in which case the field is omitted, for brevity. It will handle array values gracefully, including arrays of primitive types.

        Just as with the relationship between hashCode, equals, and toString for ordinary Java classes, subclasses of AbstractContentNode should maintain consistent implementations of contentNodeHashCode, contentNodeEquals, and appendContentNodeFields.

        Parameters:
        buf - where the field values should be written
        See Also:
        contentNodeHashCode(), contentNodeEquals(AbstractContentNode)
      • nodeEquals

        protected final boolean nodeEquals​(C other)
        Description copied from class: AbstractNode
        Allows nodes that have their own fields to augment the equals implementation with tests for their own field values.

        Implementations need not check for identity, null, or a different node class; those are already covered by the AbstractNode.equals(Object) implementation that is expected to be this method's only consumer.

        Just as with the relationship between hashCode, equals, and toString for ordinary Java classes, subclasses of AbstractNode should maintain consistent implementations of nodeHashCode, nodeEquals, and appendNodeFields.

        Overrides:
        nodeEquals in class AbstractNode<C extends AbstractContentNode<C,​N>>
        Returns:
        true if all additional field values that belong to a particular type of content node test as equal; false if differences are found
        See Also:
        AbstractNode.nodeHashCode(), AbstractNode.appendNodeFields(ToStringHelper)
      • parseOptionalContent

        protected C parseOptionalContent​(Map<String,​?> map,
                                         Class<N> contentClass)
      • parseRequiredContentAllowEmpty

        protected C parseRequiredContentAllowEmpty​(Map<String,​?> map,
                                                   Class<N> contentClass)
      • parseRequiredContent

        protected C parseRequiredContent​(Map<String,​?> map,
                                         Class<N> contentClass)
      • parseContentItems

        protected void parseContentItems​(List<Map<String,​?>> maps,
                                         Class<N> contentClass)
      • parseContentItem

        protected N parseContentItem​(Map<String,​?> map,
                                     Class<N> contentClass)
      • appendPlainText

        public void appendPlainText​(StringBuilder sb)
        Description copied from interface: Node
        Renders this node as plain-text suitable for viewing by end users. This is equivalent to calling Node.toPlainText() and appending the result to the given buffer, except that it may be slightly more efficient, since it will write directly to the existing buffer instead of using a temporary buffer and having to make a copy of the result.
        Specified by:
        appendPlainText in interface Node
        Overrides:
        appendPlainText in class AbstractNode<C extends AbstractContentNode<C,​N>>
        Parameters:
        sb - where to write the result
      • appendPlainTextContentJoinedWith

        protected void appendPlainTextContentJoinedWith​(char delimiter,
                                                        StringBuilder sb)
        Intended for content nodes that hold block elements, this will render their contents as plain-text by joining the items with the given delimiter between them. If this node is empty, then this call has no effect.
        Parameters:
        delimiter - the text (commonly "\n", a newline) to use as a separator between content items
        sb - the buffer to which the contents should be rendered as plain-text
      • appendPlainTextInlineContent

        protected void appendPlainTextInlineContent​(StringBuilder sb)
        For content nodes that hold InlineContent (or some other marker interface like CaptionContent that has a similar purpose), append that content to the given buffer with appropriate handling of mention nodes.

        Briefly, this means that if a mention node is present in the content, then a space is added between it and the following node so that the mention name is not encroached upon by the following text. We want the mention @foo followed by the text bar to be @foo bar, not @foobar.

        Parameters:
        sb - the buffer to which the inline content (or similar) should be rendered as plain-text
      • trim

        protected void trim​(StringBuilder sb,
                            int start)
        Trims a substring directly in the string builder's buffer to avoid creating an intermediate String, trimming that, and writing it back to the original buffer.
        Parameters:
        sb - the buffer containing the substring to be trimmed
        start - the beginning of the substring to be trimmed