Files
ConfigKit/internal/engine/inheritance_combine.go

126 lines
5.5 KiB
Go

package engine
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
type inheritanceTemplateResult struct {
value *document.Node
origins map[string]Origin
collectionPolicies collectionPolicyScope
policyTemplates []collectionPolicyScope
controls []inheritanceControl
transfers []inheritanceTransfer
replacements []inheritanceReplacement
operations []inheritanceOperation
}
func combineInheritanceTemplate(
template inheritanceExecutionTemplate,
child preparedInheritanceChild,
parent *preparedInheritanceParent,
parentOrigins map[string]Origin,
applicationPolicy sequencePolicy,
) (inheritanceTemplateResult, []Diagnostic) {
result := inheritanceTemplateResult{}
if child.control != nil {
result.controls = append(result.controls, *child.control)
result.operations = append(result.operations, inheritanceOperation{
control: child.control, controlOrigin: child.controlOrigin,
})
}
if parent == nil {
result.value = document.Clone(child.payload)
result.origins = child.origins
result.collectionPolicies = cloneCollectionPolicyScopeForInheritance(child.policyTemplates)
result.policyTemplates = []collectionPolicyScope{child.policyTemplates}
return result, nil
}
mergedPolicyScope, diagnostics := mergeInheritanceCollectionPolicies(
parent.parentPolicyScope, parent.childPolicyScope,
template.path, parent.payload, child.payload,
applicationPolicy, parent.replaced,
)
if len(diagnostics) != 0 {
return inheritanceTemplateResult{}, diagnostics
}
mergedOrigins := transferredInheritanceOrigins(parentOrigins, parent.transfer.from, template.path, parent.transfer)
mergeInheritanceOrigin(mergedOrigins, template.path, child.origins[template.path.String()])
var sequenceContributions []sequenceHistoryContribution
var combinationDiagnostics []Diagnostic
mergeRecursiveMappings(parent.payload, child.payload, template.path, new(mappingIndex), recursiveMergeHooks{
added: func(childPath Path, incoming *document.Node) {
copyInheritanceSubtree(mergedOrigins, child.origins, incoming, childPath)
},
combined: func(childPath Path, _ *document.Node) {
mergeInheritanceOrigin(mergedOrigins, childPath, child.origins[childPath.String()])
},
replaced: func(childPath Path, existing, incoming *document.Node) {
result.replacements = append(result.replacements, inheritanceReplacement{
before: existing, after: incoming,
})
deleteOriginSubtree(mergedOrigins, childPath, existing)
copyInheritanceSubtree(mergedOrigins, child.origins, incoming, childPath)
},
merge: func(childPath Path, existing, incoming *document.Node) (*document.Node, bool) {
resolution, _, _, active, issues := inheritanceCollectionResolution(
childPath, parent.parentPolicyScope, parent.childPolicyScope, applicationPolicy, incoming,
)
if len(issues) != 0 {
combinationDiagnostics = append(combinationDiagnostics, issues...)
return existing, false
}
if !active {
return nil, false
}
lowerValue := existing
combined, problems := combineSequence(lowerValue, incoming, resolution, sequenceCombinationContext{destination: childPath})
if len(problems) != 0 {
combinationDiagnostics = append(combinationDiagnostics, problems...)
return existing, false
}
policy := applyInheritanceSequencePolicy(
childPath, combined, resolution, parent.parentPolicyScope, parent.childPolicyScope,
)
mergedPolicyScope.set(childPath, policy)
result.replacements = append(result.replacements, applyInheritanceSequenceOrigins(
mergedOrigins, child.origins, childPath, lowerValue, incoming, combined, resolution.operation,
)...)
history := sequenceHistoryContribution{path: childPath.clone(), mode: sequenceHistoryMapped}
if resolution.operation == sequenceModeReplace {
history.mode = sequenceHistoryReplace
if incoming != nil && incoming.Kind == document.Sequence {
history.length = len(incoming.Sequence)
}
} else {
history.items = append([]sequenceItemProjection(nil), combined.higherItems...)
history.replacements = append([]sequenceItemReplacement(nil), combined.replacements...)
}
sequenceContributions = append(sequenceContributions, history)
return combined.value, true
},
})
preserveInheritanceIdentityFields(parent.payload, child.payload, template.identityFields)
if len(combinationDiagnostics) != 0 {
return inheritanceTemplateResult{}, canonicalDiagnostics(combinationDiagnostics)
}
if problems := validateRegisteredInheritanceSequences(parent.payload, template.path, applicationPolicy); len(problems) != 0 {
return inheritanceTemplateResult{}, problems
}
parent.payload.Location = template.entry.Value.Location
result.value = parent.payload
result.origins = mergedOrigins
result.collectionPolicies = inheritancePolicyScopeAtPath(mergedPolicyScope, template.path)
result.policyTemplates = parent.effectivePolicyTemplates
result.transfers = append(result.transfers, parent.transfer)
result.operations = append(result.operations, inheritanceOperation{
transfer: &parent.transfer, parent: parent.historyParent, effective: parent.payload,
parentOrigins: parentOrigins, effectiveOrigins: mergedOrigins,
parentPolicies: cloneInheritancePolicyTemplates(parent.policyTemplates),
templatePolicies: cloneCollectionPolicyScopeForInheritance(child.policyTemplates),
effectivePolicies: cloneInheritancePolicyTemplates(parent.effectivePolicyTemplates),
sequences: cloneSequenceHistoryContributions(sequenceContributions),
identityFields: cloneStrings(template.identityFields),
})
return result, nil
}