package eu.dnetlib.validator2.engine.builtins;

import eu.dnetlib.validator2.engine.Rule;
import eu.dnetlib.validator2.engine.RuleEvaluationException;
import eu.dnetlib.validator2.engine.contexts.XMLContext;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import java.util.function.Predicate;

/**
 * An XML rule that evaluates an xpath in an XMLContext and then injects a custom nodelist predicate to
 * carry out the actual rule application.
 */
public class XMLRule<C extends XMLContext> implements Rule<Document> {

    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(XMLRule.class);
    private final C context;
    public final Predicate<NodeList> predicate;

    public XMLRule(C context, Predicate<NodeList> predicate) {
        this.context = context;
        this.predicate = predicate;
    }

    @Override
    public C getContext() {
        return context;
    }

    @Override
    public boolean test(Document doc) throws RuleEvaluationException {
        try {
            logger.debug("Applying {}", context.getIdProperty().getValue());
            NodeList nodes = context.getXPathExpressionProperty().evaluate(doc);
            return predicate.test(nodes);
        } catch (Throwable t) {
            // Catch all exceptions here to simplify predicate code
            throw new RuleEvaluationException(t.getMessage(), t);
        }
    }

    @Override
    public String toString() {
        return getContext().getIdProperty().getValue();
    }
}
