class AdvancedFilterValidator implements GenericMetaInfDataValidator, FilterValidator, DocumentViewXmlValidator, JcrPathValidator {

    @Override
    public @Nullable Collection<ValidationMessage> validateJcrPath(@NotNull NodeContext nodeContext,
            boolean isFolder) {
        if (!isFolder) {
            return validateFileNodePath(nodeContext.getNodePath());
        } else {
            return null;
        }
    }

}

class AdvancedFilterValidatorTest {

    private AdvancedFilterValidator validator;
    @Mock
    private FilterValidator filterValidator1;
    @Mock
    private FilterValidator filterValidator2;
    @Mock
    private PackageProperties properties;
    @Mock
    private WorkspaceFilter filter;
    private Collection<PackageInfo> dependenciesMetaInfo;
    private Collection<String> validRoots;
    private DocumentBuilderFactory factory;

    @Test
    public void testUncoveredAncestorNodesFailure() throws IOException, ConfigurationException {

        DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
        try (InputStream input = this.getClass().getResourceAsStream("/filter.xml")) {
            filter.load(input);
        }
        validator = new AdvancedFilterValidator(
                factory,
                ValidationMessageSeverity.ERROR,
                AdvancedFilterValidatorFactory.DEFAULT_SEVERITY_FOR_UNCOVERED_ANCESTOR_NODES,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.ERROR,
                false,
                dependenciesMetaInfo,
                filter, // this is per test
                validRoots);

        // default severity INFO
        ValidationExecutorTest.assertViolation(validator.validateJcrPath(getStandardNodeContext("/apps"), false), ValidationMessageSeverity.INFO,
                new ValidationMessage(ValidationMessageSeverity.INFO,
                        String.format(AdvancedFilterValidator.MESSAGE_ANCESTOR_NODE_NOT_COVERED_BUT_VALID_ROOT, "/apps")));
        ValidationExecutorTest.assertViolation(validator.validateJcrPath(getStandardNodeContext("/apps/test4"), false), ValidationMessageSeverity.INFO,
                new ValidationMessage(ValidationMessageSeverity.INFO,
                        String.format(AdvancedFilterValidator.MESSAGE_ANCESTOR_NODE_NOT_COVERED, "/apps/test4")));

        // default severity ERROR
        validator = new AdvancedFilterValidator(
                factory,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.ERROR,
                false,
                dependenciesMetaInfo,
                filter, // this is per test
                validRoots);

        ValidationExecutorTest.assertViolation(validator.validateJcrPath(getStandardNodeContext("/apps/test4"), false), ValidationMessageSeverity.INFO,
                new ValidationMessage(ValidationMessageSeverity.ERROR,
                        String.format(AdvancedFilterValidator.MESSAGE_ANCESTOR_NODE_NOT_COVERED, "/apps/test4")));

        // set valid roots
        validRoots.add("/someroot");
        // default severity ERROR
        validator = new AdvancedFilterValidator(
                factory,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.WARN,
                ValidationMessageSeverity.ERROR,
                ValidationMessageSeverity.ERROR,
                false,
                dependenciesMetaInfo,
                filter, // this is per test
                Collections.emptyList());
        ValidationExecutorTest.assertViolation(validator.validateJcrPath(getStandardNodeContext("/apps"), false), ValidationMessageSeverity.WARN,
                new ValidationMessage(ValidationMessageSeverity.WARN,
                        String.format(AdvancedFilterValidator.MESSAGE_ANCESTOR_NODE_NOT_COVERED, "/apps")));
    }

}