//Dstl (c) Crown Copyright 2017
package uk.gov.dstl.baleen.uima.utils.select;
/**
* Base structural evaluator.
*/
abstract class StructuralEvaluator<T> extends Evaluator<T> {
final Evaluator<T> evaluator;
public StructuralEvaluator(Evaluator<T> evaluator) {
this.evaluator = evaluator;
}
/**
* Evaluator<T> matches the given root node
*
*/
static class Root<T> extends Evaluator<T> {
@Override
public boolean matches(Node<T> root, Node<T> node) {
return root == node;
}
}
/**
* Evaluator<T> matches if the given evaluator matches for the nodes of the current node
*
*/
static class Has<T> extends StructuralEvaluator<T> {
public Has(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
Nodes<T> allNodes = node.getAllNodes();
for (Node<T> e : allNodes) {
if (e != node && evaluator.matches(root, e)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return String.format(":has(%s)", evaluator);
}
}
/**
* Evaluator<T> matches if the given evaluator does not
*
*/
static class Not<T> extends StructuralEvaluator<T> {
public Not(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
return !evaluator.matches(root, node);
}
@Override
public String toString() {
return String.format(":not(%s)", evaluator);
}
}
/**
* Evaluator<T> matches if any of the nodes parents matches the given evaluator
*
*/
static class Parent<T> extends StructuralEvaluator<T> {
public Parent(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
if (root == node) {
return false;
}
Node<T> parent = node.getParent();
while (true) {
if (evaluator.matches(root, parent)) {
return true;
}
if (parent == root) {
break;
}
parent = parent.getParent();
}
return false;
}
@Override
public String toString() {
return String.format(":parent(%s)", evaluator);
}
}
/**
* Evaluator<T> matches if the nodes immediate parent matches the given evaluator
*
*/
static class ImmediateParent<T> extends StructuralEvaluator<T> {
public ImmediateParent(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
if (root == node) {
return false;
}
Node<T> parent = node.getParent();
return parent != null && evaluator.matches(root, parent);
}
@Override
public String toString() {
return String.format(":immediateParent(%s)", evaluator);
}
}
/**
* Evaluator<T> matches if any of the nodes previous siblings matches the given evaluator
*
*/
static class PreviousSibling<T> extends StructuralEvaluator<T> {
public PreviousSibling(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
if (root == node) {
return false;
}
Node<T> prev = node.previousSibling();
while (prev != null) {
if (evaluator.matches(root, prev)) {
return true;
}
prev = prev.previousSibling();
}
return false;
}
@Override
public String toString() {
return String.format(":prev*(%s)", evaluator);
}
}
/**
* Evaluator<T> matches if the nodes immediate previous sibling matches the given evaluator
*
*/
static class ImmediatePreviousSibling<T> extends StructuralEvaluator<T> {
public ImmediatePreviousSibling(Evaluator<T> evaluator) {
super(evaluator);
}
@Override
public boolean matches(Node<T> root, Node<T> node) {
if (root == node) {
return false;
}
Node<T> prev = node.previousSibling();
return prev != null && evaluator.matches(root, prev);
}
@Override
public String toString() {
return String.format(":prev(%s)", evaluator);
}
}
}