// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.schema.parser; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * This class holds the extracted information after parsing a * "document" block in a schema (.sd) file, using simple data * structures as far as possible. Do not put advanced logic here! * @author arnej27959 **/ public class ParsedDocument extends ParsedBlock { private final List inherited = new ArrayList<>(); private final Map resolvedInherits = new LinkedHashMap(); private final Map resolvedReferences = new LinkedHashMap(); private final Map docFields = new LinkedHashMap<>(); private final Map docStructs = new LinkedHashMap<>(); private final Map docAnnotations = new LinkedHashMap<>(); public ParsedDocument(String name) { super(name, "document"); } List getInherited() { return List.copyOf(inherited); } List getAnnotations() { return List.copyOf(docAnnotations.values()); } List getResolvedInherits() { assert(inherited.size() == resolvedInherits.size()); return List.copyOf(resolvedInherits.values()); } List getResolvedReferences() { return List.copyOf(resolvedReferences.values()); } List getAllResolvedParents() { List all = new ArrayList<>(); all.addAll(getResolvedInherits()); all.addAll(getResolvedReferences()); return all; } List getFields() { return List.copyOf(docFields.values()); } List getStructs() { return List.copyOf(docStructs.values()); } ParsedStruct getStruct(String name) { return docStructs.get(name); } ParsedAnnotation getAnnotation(String name) { return docAnnotations.get(name); } List getReferencedDocuments() { var result = new ArrayList(); for (var field : docFields.values()) { var type = field.getType(); if (type.getVariant() == ParsedType.Variant.DOC_REFERENCE) { var docType = type.getReferencedDocumentType(); assert(docType.getVariant() == ParsedType.Variant.DOCUMENT); result.add(docType.name()); } } return result; } void inherit(String other) { inherited.add(other); } void addField(ParsedField field) { String fieldName = field.name().toLowerCase(); verifyThat(! docFields.containsKey(fieldName), "Duplicate (case insensitively) " + field + " in document type '" + this.name() + "'"); docFields.put(fieldName, field); } void addStruct(ParsedStruct struct) { String sName = struct.name(); verifyThat(! docStructs.containsKey(sName), "already has struct", sName); docStructs.put(sName, struct); struct.tagOwner(this); } void addAnnotation(ParsedAnnotation annotation) { String annName = annotation.name(); verifyThat(! docAnnotations.containsKey(annName), "already has annotation", annName); docAnnotations.put(annName, annotation); annotation.tagOwner(this); } void resolveInherit(String name, ParsedDocument parsed) { verifyThat(inherited.contains(name), "resolveInherit for non-inherited name", name); verifyThat(name.equals(parsed.name()), "resolveInherit name mismatch for", name); verifyThat(! resolvedInherits.containsKey(name), "double resolveInherit for", name); resolvedInherits.put(name, parsed); } void resolveReferenced(ParsedDocument parsed) { var old = resolvedReferences.put(parsed.name(), parsed); assert(old == null || old == parsed); } ParsedStruct findParsedStruct(String name) { ParsedStruct found = getStruct(name); if (found != null) return found; for (var parent : getAllResolvedParents()) { var fromParent = parent.findParsedStruct(name); if (fromParent == null) continue; if (fromParent == found) continue; if (found == null) { found = fromParent; } else { throw new IllegalArgumentException("conflicting values for struct " + name + " in " +this); } } return found; } ParsedAnnotation findParsedAnnotation(String name) { ParsedAnnotation found = docAnnotations.get(name); if (found != null) return found; for (var parent : getResolvedInherits()) { var fromParent = parent.findParsedAnnotation(name); if (fromParent == null) continue; if (fromParent == found) continue; if (found == null) { found = fromParent; } else { throw new IllegalArgumentException("conflicting values for annotation " + name + " in " +this); } } return found; } }