@Override
    public void validate(Validation.Context context) {
        record SchemaAndField(String schemaName, String fieldName) {}

        // Collect all embedder ids from EmbedExpression instances in all schemas
        var fieldToEmbedderId = new HashMap<SchemaAndField, String>();
        context.model().getContentClusters().forEach((__, contentCluster) -> {
            if (!contentCluster.getSearch().hasSearchCluster()) return;

            contentCluster.getSearch().getSearchCluster().schemas().forEach((___, schema) -> {
                schema.fullSchema().allFields()
                        .forEach(field -> {
                            if (field.isImportedField() || field.getIndexingScript().isEmpty()) return;

                            var visitor = new ExpressionVisitor() {
                                @Override
                                protected void doVisit(Expression e) {
                                    if (e instanceof EmbedExpression ee) {
                                        ee.requestedEmbedderId().ifPresent(id -> {
                                            var fieldName = field.getName();
                                            var schemaName = schema.fullSchema().getName();
                                            log.log(Level.FINE, () -> "Found embedder '%s' for field '%s' in schema '%s'".formatted(id, fieldName, schemaName));
                                            fieldToEmbedderId.put(new SchemaAndField(schemaName, fieldName), id);
                                        });
                                    }
                                }
                            };
                            visitor.visit(field.getIndexingScript());
                        });
            });
        });

        // Collect all component ids from the model
        var allComponentIds = new HashSet<String>();
        context.model().getContainerClusters().forEach((__, containerCluster) ->
                containerCluster.getAllComponents()
                        .forEach(component -> {
                            var id = component.getComponentId().getName();
                            log.log(Level.FINE, () -> "Found component id '%s'".formatted(id));
                            allComponentIds.add(id);
                        }));

        // Validate that all embedder ids are present as components
        fieldToEmbedderId.forEach((field, requestedEmbedderId) -> {
            if (!allComponentIds.contains(requestedEmbedderId)) {
                context.illegal(
                        ("The 'embed' expression for field '%s' in schema '%s' refers to an embedder with id '%s'. " +
                                "No component with that id is configured.").formatted(
                                        field.fieldName(), field.schemaName(), requestedEmbedderId));
            }
        });
    }
Validates that all embedder ids specified in 'embed' expressions references an existing component.

@author bjorncs
config-model/src/main/java/com/yahoo/vespa/model/application/validation/EmbedExpressionValidator.java