Apply collection policies during sibling inheritance
This commit is contained in:
@@ -19,11 +19,13 @@ type inheritanceTemplate struct {
|
||||
}
|
||||
|
||||
type inheritanceGraph struct {
|
||||
scope *document.Node
|
||||
scopePath Path
|
||||
nodes []inheritanceTemplate
|
||||
edges []dependencyEdge
|
||||
byName map[string]int
|
||||
scope *document.Node
|
||||
scopePath Path
|
||||
collectionPolicies collectionPolicyScope
|
||||
applicationPolicy sequencePolicy
|
||||
nodes []inheritanceTemplate
|
||||
edges []dependencyEdge
|
||||
byName map[string]int
|
||||
}
|
||||
|
||||
// analyzeInheritanceGraph retains only direct mapping siblings as graph nodes.
|
||||
@@ -34,6 +36,10 @@ func analyzeInheritanceGraph(scope *document.Node, scopePath Path) (*inheritance
|
||||
}
|
||||
|
||||
func analyzeInheritanceGraphWithPolicies(scope *document.Node, scopePath Path, policies collectionPolicyScope) (*inheritanceGraph, []Diagnostic) {
|
||||
return analyzeInheritanceGraphWithCollectionRules(scope, scopePath, policies, sequencePolicy{})
|
||||
}
|
||||
|
||||
func analyzeInheritanceGraphWithCollectionRules(scope *document.Node, scopePath Path, policies collectionPolicyScope, applicationPolicy sequencePolicy) (*inheritanceGraph, []Diagnostic) {
|
||||
if scope == nil || scope.Kind != document.Mapping {
|
||||
return nil, []Diagnostic{{
|
||||
Code: CodeInheritanceInvalid, Severity: SeverityError, Path: scopePath,
|
||||
@@ -43,6 +49,7 @@ func analyzeInheritanceGraphWithPolicies(scope *document.Node, scopePath Path, p
|
||||
|
||||
graph := &inheritanceGraph{
|
||||
scope: scope, scopePath: scopePath,
|
||||
collectionPolicies: cloneCollectionPolicyScopeForInheritance(policies), applicationPolicy: applicationPolicy,
|
||||
byName: make(map[string]int, len(scope.Mapping)),
|
||||
}
|
||||
entries := make(map[string]document.Entry, len(scope.Mapping))
|
||||
@@ -125,7 +132,11 @@ func expandSiblingDefinitionsWithOrigins(scope *document.Node, scopePath Path, l
|
||||
}
|
||||
|
||||
func expandSiblingDefinitionsWithPolicies(scope *document.Node, scopePath Path, limits projectionLimits, inputOrigins map[string]Origin, policies collectionPolicyScope, budget ...*retainedNodeCounter) (*inheritanceScope, []Diagnostic) {
|
||||
graph, diagnostics := analyzeInheritanceGraphWithPolicies(scope, scopePath, policies)
|
||||
return expandSiblingDefinitionsWithCollectionRules(scope, scopePath, limits, inputOrigins, policies, sequencePolicy{}, budget...)
|
||||
}
|
||||
|
||||
func expandSiblingDefinitionsWithCollectionRules(scope *document.Node, scopePath Path, limits projectionLimits, inputOrigins map[string]Origin, policies collectionPolicyScope, applicationPolicy sequencePolicy, budget ...*retainedNodeCounter) (*inheritanceScope, []Diagnostic) {
|
||||
graph, diagnostics := analyzeInheritanceGraphWithCollectionRules(scope, scopePath, policies, applicationPolicy)
|
||||
if len(diagnostics) != 0 {
|
||||
return nil, diagnostics
|
||||
}
|
||||
@@ -137,7 +148,6 @@ func expandSiblingDefinitionsWithPolicies(scope *document.Node, scopePath Path,
|
||||
if len(diagnostics) != 0 {
|
||||
return nil, diagnostics
|
||||
}
|
||||
result.collectionPolicies = cloneCollectionPolicyScopeForInheritance(policies)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -148,6 +158,7 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
resolved := make([]*document.Node, len(graph.nodes))
|
||||
resolvedOrigins := make([]map[string]Origin, len(graph.nodes))
|
||||
resolvedPolicyTemplates := make([][]collectionPolicyScope, len(graph.nodes))
|
||||
resolvedPolicies := make([]collectionPolicyScope, len(graph.nodes))
|
||||
result := &inheritanceScope{}
|
||||
counter := newRetainedNodeCounter(historyNodeLimit)
|
||||
if len(budget) != 0 {
|
||||
@@ -202,16 +213,28 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
parent := resolved[node.parent]
|
||||
parentPolicies := cloneInheritancePolicyTemplates(resolvedPolicyTemplates[node.parent])
|
||||
effectivePolicies := append(cloneInheritancePolicyTemplates(parentPolicies), cloneCollectionPolicyScopeForInheritance(templatePolicies))
|
||||
parentPolicyScope := projectInheritanceCollectionPolicies(resolvedPolicies[node.parent], node.path)
|
||||
childPolicyScope := projectCurrentInheritanceCollectionPolicies(templatePolicies, node.path)
|
||||
merged := document.Clone(parent)
|
||||
mergedPolicyScope, policyDiagnostics := mergeInheritanceCollectionPolicies(
|
||||
parentPolicyScope, childPolicyScope, node.path, parent, graph.applicationPolicy,
|
||||
)
|
||||
if len(policyDiagnostics) != 0 {
|
||||
return nil, policyDiagnostics
|
||||
}
|
||||
transfer := inheritanceTransfer{
|
||||
from: graph.nodes[node.parent].path, to: node.path,
|
||||
reference: node.path.Key(inheritanceKey),
|
||||
locations: []Location{publicLocation(node.directive.Value.Location)},
|
||||
policyTemplates: parentPolicies, templatePolicies: cloneCollectionPolicyScopeForInheritance(templatePolicies),
|
||||
projectedPolicies: projectInheritancePolicyTemplates(parentPolicies, node.path),
|
||||
projectedPolicies: projectInheritancePolicyTemplates(
|
||||
[]collectionPolicyScope{resolvedPolicies[node.parent]}, node.path,
|
||||
),
|
||||
}
|
||||
mergedOrigins := transferredInheritanceOrigins(resolvedOrigins[node.parent], transfer.from, node.path, transfer)
|
||||
mergeInheritanceOrigin(mergedOrigins, node.path, childOrigins[node.path.String()])
|
||||
var sequenceContributions []sequenceHistoryContribution
|
||||
var combinationDiagnostics []Diagnostic
|
||||
mergeRecursiveMappings(merged, payload, node.path, new(mappingIndex), recursiveMergeHooks{
|
||||
added: func(childPath Path, incoming *document.Node) {
|
||||
copyInheritanceSubtree(mergedOrigins, childOrigins, incoming, childPath)
|
||||
@@ -228,9 +251,57 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
deleteOriginSubtree(mergedOrigins, childPath, existing)
|
||||
copyInheritanceSubtree(mergedOrigins, childOrigins, incoming, childPath)
|
||||
},
|
||||
merge: func(childPath Path, existing, incoming *document.Node) (*document.Node, bool) {
|
||||
resolution, _, _, active, issues := inheritanceCollectionResolution(
|
||||
childPath, parentPolicyScope, childPolicyScope, graph.applicationPolicy,
|
||||
)
|
||||
if len(issues) != 0 {
|
||||
combinationDiagnostics = append(combinationDiagnostics, issues...)
|
||||
return existing, false
|
||||
}
|
||||
if !active {
|
||||
return nil, false
|
||||
}
|
||||
lowerPath, within := relativeHistoryPath(node.path, childPath)
|
||||
if !within {
|
||||
return nil, false
|
||||
}
|
||||
lowerValue, _ := documentAtPath(parent, lowerPath)
|
||||
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, parentPolicyScope, childPolicyScope, &mergedPolicyScope,
|
||||
)
|
||||
mergedPolicyScope.set(childPath, policy)
|
||||
applyInheritanceSequenceOrigins(
|
||||
result, mergedOrigins, childOrigins, 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
|
||||
},
|
||||
})
|
||||
if len(combinationDiagnostics) != 0 {
|
||||
return nil, canonicalDiagnostics(combinationDiagnostics)
|
||||
}
|
||||
if problems := validateRegisteredInheritanceSequences(merged, node.path, graph.applicationPolicy); len(problems) != 0 {
|
||||
return nil, problems
|
||||
}
|
||||
merged.Location = node.entry.Value.Location
|
||||
resolved[index], resolvedOrigins[index] = merged, mergedOrigins
|
||||
resolvedPolicies[index] = inheritancePolicyScopeAtPath(mergedPolicyScope, node.path)
|
||||
result.transfers = append(result.transfers, transfer)
|
||||
result.operations = append(result.operations, inheritanceOperation{
|
||||
transfer: &transfer, parent: parent, effective: merged,
|
||||
@@ -238,12 +309,14 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
parentPolicies: cloneInheritancePolicyTemplates(parentPolicies),
|
||||
templatePolicies: cloneCollectionPolicyScopeForInheritance(templatePolicies),
|
||||
effectivePolicies: cloneInheritancePolicyTemplates(effectivePolicies),
|
||||
sequences: cloneSequenceHistoryContributions(sequenceContributions),
|
||||
})
|
||||
resolvedPolicyTemplates[index] = effectivePolicies
|
||||
} else {
|
||||
resolved[index] = document.Clone(payload)
|
||||
resolvedOrigins[index] = childOrigins
|
||||
resolvedPolicyTemplates[index] = []collectionPolicyScope{templatePolicies}
|
||||
resolvedPolicies[index] = cloneCollectionPolicyScopeForInheritance(templatePolicies)
|
||||
}
|
||||
|
||||
count, _ := inheritanceLowerBoundCount(resolved[index], limits.nodes)
|
||||
@@ -262,17 +335,21 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
|
||||
root := *graph.scope
|
||||
root.Mapping = make([]document.Entry, len(graph.scope.Mapping))
|
||||
result.collectionPolicies = collectionPolicyScope{}
|
||||
result.origins = directInheritanceOrigins(&document.Node{Kind: document.Mapping, Location: graph.scope.Location}, graph.scopePath, inputOrigins)
|
||||
for i, entry := range graph.scope.Mapping {
|
||||
root.Mapping[i] = entry
|
||||
if index, found := graph.byName[entry.Key]; found {
|
||||
root.Mapping[i].Value = resolved[index]
|
||||
projectInheritancePolicyRoots(&result.collectionPolicies, resolvedPolicies[index], graph.nodes[index].path)
|
||||
for pointer, origin := range resolvedOrigins[index] {
|
||||
result.origins[pointer] = origin
|
||||
}
|
||||
continue
|
||||
}
|
||||
root.Mapping[i].Value = document.Clone(entry.Value)
|
||||
localPolicies := inheritancePolicyScopeAtPath(graph.collectionPolicies, graph.scopePath.Key(entry.Key))
|
||||
projectInheritancePolicyRoots(&result.collectionPolicies, localPolicies, graph.scopePath.Key(entry.Key))
|
||||
for pointer, origin := range directInheritanceOrigins(entry.Value, graph.scopePath.Key(entry.Key), inputOrigins) {
|
||||
result.origins[pointer] = origin
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user