Class AbstractContentNode<C extends AbstractContentNode<C,N>,N extends Node>
- java.lang.Object
-
- com.atlassian.adf.model.node.AbstractNode<C>
-
- com.atlassian.adf.model.node.AbstractContentNode<C,N>
-
- Type Parameters:
C- the type of this container node that holds contentN- the common superclass or interface for all node types that are permitted as content within this node
- All Implemented Interfaces:
Element,Node,ContentNode<C,N>
- Direct Known Subclasses:
AbstractListNode,AbstractMarkedContentNode,AbstractTableCellNode,Blockquote,Caption,DecisionItem,DecisionList,Doc,LayoutColumn,ListItem,MediaGroup,NestedExpand,Panel,TableRow,TaskItem,TaskList
@Internal public abstract class AbstractContentNode<C extends AbstractContentNode<C,N>,N extends Node> extends AbstractNode<C> implements ContentNode<C,N>
Nodes that use the"content"key to specify a list of child nodes extend this type to handle the common conventions across those node types.
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class com.atlassian.adf.model.node.AbstractNode
AbstractNode.ToStringHelper
-
-
Constructor Summary
Constructors Constructor Description AbstractContentNode()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected voidaddContent(FieldMap map)protected voidaddContentIfPresent(FieldMap map)Stream<Node>allNodes()Produces a stream consisting of the in-order traversal of this node and all of its contents, where any nestedContentNodes are also expanded.protected voidappendContentNodeFields(AbstractNode.ToStringHelper buf)Allows content nodes that have their own fields to augment thetoString()implementation with their own field values.protected voidappendNodeFields(AbstractNode.ToStringHelper buf)Allows nodes that have their own fields to augment thetoString()implementation with their own field values.voidappendPlainText(StringBuilder sb)Renders this node as plain-text suitable for viewing by end users.protected voidappendPlainTextContentJoinedWith(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 givendelimiterbetween them.protected voidappendPlainTextInlineContent(StringBuilder sb)For content nodes that holdInlineContent(or some other marker interface likeCaptionContentthat has a similar purpose), append that content to the given buffer with appropriate handling of mention nodes.Cclear()Discards all existing content in this node.List<N>content()Returns the existing contents of this content node.Ccontent(Iterable<? extends N> content)Adds the given nodes as content within this containing node.Ccontent(Stream<? extends N> content)Adds the given nodes as content within this containing node.Ccontent(N content)Adds the given node as content within this containing node.Ccontent(N... content)Adds the given nodes as content within this containing node.protected List<? extends Map<String,?>>contentFieldMaps()protected booleancontentNodeEquals(C other)Allows content nodes that have their own fields to augment theequalsimplementation with tests for their own field values.protected intcontentNodeHashCode()Allows content nodes that have their own fields to augment thehashCodeimplementation with a hash of their own field values.protected voidcontentNodeValidate()booleanisEmpty()protected booleannodeEquals(C other)Allows nodes that have their own fields to augment theequalsimplementation with tests for their own field values.protected intnodeHashCode()Implementation ofnodeHashCode()that combines a hash of thecontent()with the value fromcontentNodeHashCode().protected NparseContentItem(Map<String,?> map, Class<N> contentClass)protected voidparseContentItems(List<Map<String,?>> maps, Class<N> contentClass)protected CparseOptionalContent(Map<String,?> map, Class<N> contentClass)protected CparseRequiredContent(Map<String,?> map, Class<N> contentClass)protected CparseRequiredContentAllowEmpty(Map<String,?> map, Class<N> contentClass)voidremoveIf(Predicate<? super N> predicate)Discards all content that matches the given predicate.voidreplaceContent(List<? extends N> newContent)Completely replace this content node's existing content items with the new ones provided.protected voidrequireNotEmpty()Verifies that at least one content element has been provided.voidtransformContent(Function<? super N,? extends N> transformer)Applies a transformation to the immediate children of this content node.<T extends Node>
voidtransformDescendants(Class<T> targetNodeClass, Function<? super T,? extends T> transformer)Applies a transformation to all descendants of this node that match the given type.protected voidtrim(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.voidvalidate()Verifies that the node is well-formed (including the state of any descendents that it has).protected voidvalidateContentItems()Validates that each of the content nodes is in a valid state.protected voidvalidateContentNodeForAppend(N node)Called on each content node before it is added to validate that the node can be accepted.-
Methods inherited from class com.atlassian.adf.model.node.AbstractNode
doubleEq, doubleHash, equals, hashCode, isSupported, mapWithType, numberEq, numberHash, self, toPlainText, toString
-
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
-
Methods inherited from interface com.atlassian.adf.model.node.type.ContentNode
allNodesOfType, allNodesOfTypeAsList, contentClass, copy
-
Methods inherited from interface com.atlassian.adf.model.Element
elementType, isSupported, toMap
-
Methods inherited from interface com.atlassian.adf.model.node.Node
toPlainText
-
-
-
-
Method Detail
-
isEmpty
public boolean isEmpty()
- Specified by:
isEmptyin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Returns:
trueif 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:ContentNodeReturns 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 listif 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 nodebefore modifying it if the original is not meant to be affected.
- Specified by:
contentin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Returns:
- the existing contents of this content node.
-
content
public final C content(N content)
Description copied from interface:ContentNodeAdds the given node as content within this containing node.The content is processed in the same way as if it were the single value provided to
ContentNode.content(Node[]).- Specified by:
contentin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Parameters:
content- the content to add- Returns:
this- See Also:
ContentNode.content(Node[])
-
content
@SafeVarargs public final C content(N... content)
Description copied from interface:ContentNodeAdds 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:
contentin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Parameters:
content- the content to add- Returns:
this
-
content
public final C content(Iterable<? extends N> content)
Description copied from interface:ContentNodeAdds the given nodes as content within this containing node.The content is processed just as if its elements were passed to
ContentNode.content(Node[]).- Specified by:
contentin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Parameters:
content- the content to add- Returns:
this- See Also:
ContentNode.content(Node[])
-
content
public final C content(Stream<? extends N> content)
Description copied from interface:ContentNodeAdds 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:
contentin interfaceContentNode<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:ContentNodeProduces a stream consisting of the in-order traversal of this node and all of its contents, where any nestedContentNodes are also expanded.Example
If a
Docis 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
docnode itselfThe
paragraphnodeThe
textnode containing"Hello "The
textnode containing"world"The
textnode containing"!"
Note that marks are not considered separate nodes; they are part of the containing
textnode.- Specified by:
allNodesin interfaceContentNode<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:ContentNodeDiscards 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:
clearin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Returns:
this
-
removeIf
public void removeIf(Predicate<? super N> predicate)
Description copied from interface:ContentNodeDiscards all content that matches the given predicate.WARNING: This uses
ContentNode.replaceContent(List)in an attempt to ensure that the node is left in a valid state. All the same caveats apply.- Specified by:
removeIfin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Parameters:
predicate- test for which content nodes should be removed
-
transformContent
public void transformContent(Function<? super N,? extends N> transformer)
Description copied from interface:ContentNodeApplies a transformation to the immediate children of this content node.The
transformerhas the following characteristics:- It will be called once for each piece of content currently held by this parent content node.
- It may return that same object to keep that piece of content.
- It may return same other object that is suitable for the parent content node, and that node will replace the original value.
- 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:
transformContentin interfaceContentNode<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:ContentNodeApplies a transformation to all descendants of this node that match the given type.The
transformerhas the following characteristics:- 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. - It may return that same object to keep that node within the content node that contains it.
- 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.
- 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 forMediaSinglenodes, which do not implement theContentNodeinterface even though they contain child nodes. In particular:- The
mediaand (if present)captionnodes are included in the traversal - If the
transformerremoves amedianode that is inside of amediaSingle, then thatmediaSingleis also removed without visiting itscaption.
- Specified by:
transformDescendantsin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>transformer- the transforming function
- 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
-
replaceContent
public final void replaceContent(List<? extends N> newContent)
Description copied from interface:ContentNodeCompletely 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 likeListItemthat 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 isvalidatedduring some future use. Proceed with caution.- Specified by:
replaceContentin interfaceContentNode<C extends AbstractContentNode<C,N>,N extends Node>- Parameters:
newContent- the new content list for this node
-
validate
public final void validate()
Description copied from interface:ElementVerifies that the node is well-formed (including the state of any descendents that it has).
-
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 thehashCodeimplementation 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 thecontent, either; that is already covered byAbstractNode.nodeHashCode(), which is expected to be this method's only consumer.Just as with the relationship between
hashCode,equals, andtoStringfor ordinary Java classes, subclasses ofAbstractContentNodeshould maintain consistent implementations ofcontentNodeHashCode,contentNodeEquals, andappendContentNodeFields.- 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 theequalsimplementation with tests for their own field values.Implementations need not check for identity,
null, or a different node class; those are already covered byAbstractNode.equals(Object). Implementations need not check thecontent(), either; that is already covered bynodeEquals(AbstractContentNode), which is expected to be this method's only consumer.Just as with the relationship between
hashCode,equals, andtoStringfor ordinary Java classes, subclasses ofAbstractContentNodeshould maintain consistent implementations ofcontentNodeHashCode,contentNodeEquals, andappendContentNodeFields.- Returns:
trueif all additional field values that belong to a particular type of content node test as equal;falseif 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 thetoString()implementation with their own field values.Each field's value should be provided by calling
AbstractNode.ToStringHelper.appendField(String, Object). Thevaluemay benull, 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, andtoStringfor ordinary Java classes, subclasses ofAbstractContentNodeshould maintain consistent implementations ofcontentNodeHashCode,contentNodeEquals, andappendContentNodeFields.- Parameters:
buf- where the field values should be written- See Also:
contentNodeHashCode(),contentNodeEquals(AbstractContentNode)
-
nodeHashCode
protected final int nodeHashCode()
Implementation ofnodeHashCode()that combines a hash of thecontent()with the value fromcontentNodeHashCode().- Overrides:
nodeHashCodein classAbstractNode<C extends AbstractContentNode<C,N>>- Returns:
- the hash code of any additional field values that belong to a particular type of content node.
- See Also:
contentNodeHashCode()
-
nodeEquals
protected final boolean nodeEquals(C other)
Description copied from class:AbstractNodeAllows nodes that have their own fields to augment theequalsimplementation with tests for their own field values.Implementations need not check for identity,
null, or a different node class; those are already covered by theAbstractNode.equals(Object)implementation that is expected to be this method's only consumer.Just as with the relationship between
hashCode,equals, andtoStringfor ordinary Java classes, subclasses ofAbstractNodeshould maintain consistent implementations ofnodeHashCode,nodeEquals, andappendNodeFields.- Overrides:
nodeEqualsin classAbstractNode<C extends AbstractContentNode<C,N>>- Returns:
trueif all additional field values that belong to a particular type of content node test as equal;falseif differences are found- See Also:
AbstractNode.nodeHashCode(),AbstractNode.appendNodeFields(ToStringHelper)
-
appendNodeFields
protected final void appendNodeFields(AbstractNode.ToStringHelper buf)
Description copied from class:AbstractNodeAllows nodes that have their own fields to augment thetoString()implementation with their own field values.Each field's value should be provided by calling
AbstractNode.ToStringHelper.appendField(String, Object). Thevaluemay benull, 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, andtoStringfor ordinary Java classes, subclasses ofAbstractNodeshould maintain consistent implementations ofnodeHashCode,nodeEquals, andappendNodeFields.- Overrides:
appendNodeFieldsin classAbstractNode<C extends AbstractContentNode<C,N>>- Parameters:
buf- where the field values should be written- See Also:
AbstractNode.nodeHashCode(),AbstractNode.nodeEquals(AbstractNode)
-
parseRequiredContentAllowEmpty
protected C parseRequiredContentAllowEmpty(Map<String,?> map, Class<N> contentClass)
-
parseContentItems
protected void parseContentItems(List<Map<String,?>> maps, Class<N> contentClass)
-
appendPlainText
public void appendPlainText(StringBuilder sb)
Description copied from interface:NodeRenders this node as plain-text suitable for viewing by end users. This is equivalent to callingNode.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:
appendPlainTextin interfaceNode- Overrides:
appendPlainTextin classAbstractNode<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 givendelimiterbetween 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 itemssb- the buffer to which the contents should be rendered as plain-text
-
appendPlainTextInlineContent
protected void appendPlainTextInlineContent(StringBuilder sb)
For content nodes that holdInlineContent(or some other marker interface likeCaptionContentthat 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
@foofollowed by the textbarto 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 trimmedstart- the beginning of the substring to be trimmed
-
-