cdc.io.data.Node Maven / Gradle / Ivy
package cdc.io.data;
import java.util.Comparator;
import java.util.function.Predicate;
/**
* Base interface of data nodes.
*
* Nodes are organized as a tree.
* Implementations of Node are:
*
* - {@link Document}
*
- {@link Element}
*
- {@link Comment}
*
- {@link Text}
*
*
* @author Damien Carbonne
*
*/
public interface Node {
/**
* A Node Predicate that always return {@code true}.
*/
public static final Predicate ANY_NODE = n -> true;
/**
* A Node Predicate that returns {@code true} when the node is a Comment.
*/
public static final Predicate IS_COMMENT =
node -> node.getType() == NodeType.COMMENT;
/**
* A Node Predicate that returns {@code true} when the node is an Element.
*/
public static final Predicate IS_ELEMENT =
node -> node.getType() == NodeType.ELEMENT;
/**
* A Node Predicate that returns {@code true} when the node is a Text.
*/
public static final Predicate IS_TEXT =
node -> node.getType() == NodeType.TEXT;
/**
* A Node Predicate that returns {@code true} when the node is an Element
* that has no attributes and no children .
*/
public static final Predicate IS_PURE_ELEMENT = node -> {
if (node.getType() == NodeType.ELEMENT) {
final Element element = (Element) node;
return !element.hasAttributes() && !element.hasChildren();
} else {
return false;
}
};
/**
* A Node Predicate that returns {@code true} when the node is a Text that is ignorable.
*/
public static final Predicate IS_IGNORABLE_TEXT = node -> {
if (node.getType() == NodeType.TEXT) {
final Text text = (Text) node;
return text.isIgnorable();
} else {
return false;
}
};
public static final Comparator ELEMENT_NAME_COMPARATOR = (node1,
node2) -> {
if (node1 instanceof Element && node2 instanceof Element) {
return ((Element) node1).getName().compareTo(((Element) node2).getName());
} else {
throw new IllegalArgumentException();
}
};
public static final Comparator ELEMENT_NAME_AND_ATTRIBUTES_COMPARATOR = (node1,
node2) -> {
if (node1 instanceof Element && node2 instanceof Element) {
return getNameAndAttributes((Element) node1).compareTo(getNameAndAttributes((Element) node2));
} else {
throw new IllegalArgumentException();
}
};
static String getNameAndAttributes(Element element) {
final StringBuilder builder = new StringBuilder();
builder.append(element.getName());
for (final Attribute att : element.getSortedAttributes()) {
builder.append(':');
builder.append(att.getName());
builder.append('=');
builder.append(att.getValue());
}
return builder.toString();
}
/**
* @return The node type.
*/
public NodeType getType();
/**
* Return a clone of this node.
*
* @param recurse If true, also clone children nodes.
* @return A clone of this node, and optionally its children.
*/
public Node clone(boolean recurse);
/**
* Return true when this node and its descendants equals other node hierarchy.
*
* Parents are ignored.
*
* @param node The other node to compare.
* @return True when this node and other node have same hierarchies.
*/
public boolean deepEquals(Node node);
/**
* @return The document of this node, possibly null.
*/
public Document getDocument();
/**
* Returns the root element of this node.
*
* If this node is a document, then this is its unique child element, possibly {@code null}.
* If this node is a child, then this is the highest ancestor that is an element, possibly {@code null}.
*
* @return The root element of this node, possibly null.
*/
public Element getRootElement();
/**
* @return A string representation of this node. May be used for debug.
*/
public String getQName();
public static String getQName(Node node) {
return node == null ? "null" : node.getQName();
}
}