@Test
public void mapsAndFiltersOverShapes() {

    List<ValidationEvent> events = Model.assembler()
            .addImport(getClass().getResource("validator-filtering-and-mapping.smithy"))
            .validatorFactory(new ValidatorFactory() {
                @Override
                public List<Validator> loadBuiltinValidators() {
                    return Collections.emptyList();
                }
                @Override
                public Optional<Validator> createValidator(String name, ObjectNode configuration) {
                    return name.equals("hello")
                           ? Optional.of(
                                   model -> model.shapes()
                                           .map(shape -> ValidationEvent.builder()
                                                   .id(name)
                                                   .shape(shape)
                                                   .severity(Severity.WARNING)
                                                   .message("Hello!")
                                                   .build())
                                           .collect(Collectors.toList()))
                           : Optional.empty();
                }
            })
            .assemble()
            .getValidationEvents();
    assertThat(events, not(empty()));
    Assertions.assertEquals(2, events.stream().filter(e -> e.getId().equals("hello")).count());
    Assertions.assertEquals(4, events.stream().filter(e -> e.getId().equals("custom")).count());
    // Ensure that template expansion works.
    for (ValidationEvent event : events) {
        if (event.getId().equals("custom")) {
            assertThat(event.getMessage(), equalTo("Test Hello!"));
        }
    }
}