From 5c24dc5c9642a8d9ed70aee4c950fd0678a1ebec Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Thu, 19 May 2022 12:03:06 +0200 Subject: Rename the 'searchdefinition' package to 'schema' --- .../yahoo/schema/DocumentReferenceResolver.java | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 config-model/src/main/java/com/yahoo/schema/DocumentReferenceResolver.java (limited to 'config-model/src/main/java/com/yahoo/schema/DocumentReferenceResolver.java') diff --git a/config-model/src/main/java/com/yahoo/schema/DocumentReferenceResolver.java b/config-model/src/main/java/com/yahoo/schema/DocumentReferenceResolver.java new file mode 100644 index 00000000000..b3e06fd5e02 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/schema/DocumentReferenceResolver.java @@ -0,0 +1,94 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.schema; + +import com.yahoo.document.Field; +import com.yahoo.documentmodel.NewDocumentReferenceDataType; +import com.yahoo.schema.document.SDDocumentType; +import com.yahoo.schema.document.SDField; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Stream; + +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.toMap; + +/** + * Resolves all document references in the search definitions + * + * Iterates through all document fields having a {@link NewDocumentReferenceDataType} and uses {@link NewDocumentReferenceDataType#getTargetTypeName()} + * to determine the referenced document. This information is aggregated into a {@link DocumentReferences} object. + * + * @author bjorncs + */ +public class DocumentReferenceResolver { + + private final Map schemaMapping; + + public DocumentReferenceResolver(Collection schemas) { + this.schemaMapping = createDocumentNameToSearchMapping(schemas); + } + + public void resolveReferences(SDDocumentType documentType) { + var references = new DocumentReferences(createFieldToDocumentReferenceMapping(documentType)); + documentType.setDocumentReferences(references); + } + + public void resolveInheritedReferences(SDDocumentType documentType) { + resolveInheritedReferencesRecursive(documentType, documentType.getInheritedTypes()); + } + + private void resolveInheritedReferencesRecursive(SDDocumentType documentType, + Collection inheritedTypes) { + for (var inheritedType : inheritedTypes) { + documentType.getDocumentReferences().get().mergeFrom(inheritedType.getDocumentReferences().get()); + } + for (var inheritedType : inheritedTypes) { + resolveInheritedReferencesRecursive(documentType, inheritedType.getInheritedTypes()); + } + } + + private Map createFieldToDocumentReferenceMapping(SDDocumentType documentType) { + return fieldStream(documentType) + .filter(field -> field.getDataType() instanceof NewDocumentReferenceDataType) + .collect(toMap(Field::getName, this::createDocumentReference)); + } + + private DocumentReference createDocumentReference(Field field) { + if (!isAttribute(field)) { + throw new IllegalArgumentException( + String.format( + "The field '%s' is an invalid document reference. The field must be an attribute.", + field.getName())); + } + NewDocumentReferenceDataType reference = (NewDocumentReferenceDataType) field.getDataType(); + String targetDocumentName = getTargetDocumentName(reference); + Schema schema = schemaMapping.get(targetDocumentName); + if (schema == null) { + throw new IllegalArgumentException( + String.format("Invalid document reference '%s': " + + "Could not find document type '%s'", field.getName(), targetDocumentName)); + } + return new DocumentReference(field, schema); + } + + private static boolean isAttribute(Field field) { + SDField sdField = (SDField) field; // Ugly, but SDDocumentType only expose the fields as the super class Field + return sdField.doesAttributing(); + } + + private static Map createDocumentNameToSearchMapping(Collection schemaDefintions) { + return schemaDefintions.stream() + .filter(search -> search.getDocument() != null) + .collect(toMap(search -> search.getDocument().getName(), identity())); + } + + private static Stream fieldStream(SDDocumentType documentType) { + return documentType.getDocumentType().getFields().stream(); + } + + private static String getTargetDocumentName(NewDocumentReferenceDataType reference) { + return reference.getTargetTypeName(); + } + +} -- cgit v1.2.3