128 lines
5.7 KiB
Go
128 lines
5.7 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) {
|
|
previous := displacedOrigins(existing, mergedOrigins, childPath)
|
|
result.replacements = append(result.replacements, inheritanceReplacement{
|
|
path: childPath.clone(), before: existing, after: incoming,
|
|
previous: previous, effective: cloneOrigin(child.origins[childPath.String()]),
|
|
})
|
|
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
|
|
}
|