Prepare reusable inheritance scope execution
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Sequence Identity And Combination Implementation Plan
|
||||
|
||||
Status: implementation in progress; Stages 1–19 complete.
|
||||
Status: implementation in progress; Stages 1–20 complete.
|
||||
|
||||
Audience: a Luna coding agent implementing one numbered stage per prompt, in
|
||||
order. This plan starts at commit
|
||||
@@ -702,6 +702,10 @@ Validation: inheritance execution, scheduling, history, and budget tests plus
|
||||
the everyday check. This refactor does not introduce new parent-reference forms
|
||||
or change public loading semantics yet.
|
||||
|
||||
**Completion:** Implemented reusable mapping and identified-sequence scope
|
||||
execution with focused inheritance/scheduling/history/budget tests,
|
||||
`go test -race ./internal/engine`, and `./scripts/check.sh`.
|
||||
|
||||
## Stage 21 — Resolve Record Inheritance With Ownership And Evidence
|
||||
|
||||
Scope: integrate Stage 19's graphs and Stage 20's executor into the structural
|
||||
|
||||
@@ -61,6 +61,92 @@ func TestIdentifiedInheritanceGraphSchedulesForwardReferencesInPlace(t *testing.
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifiedInheritanceScopeAdapterReusesTemplateExecution(t *testing.T) {
|
||||
sequence := parseIdentifiedInheritanceSequence(t, "identified-scope", `- id: child-a
|
||||
tenant: team-a
|
||||
extends: {id: parent-a, tenant: team-a}
|
||||
settings: {child: a}
|
||||
- id: parent-a
|
||||
tenant: team-a
|
||||
settings: {parent: a}
|
||||
- id: child-b
|
||||
tenant: team-b
|
||||
extends: {id: parent-b, tenant: team-b}
|
||||
settings: {child: b}
|
||||
- id: parent-b
|
||||
tenant: team-b
|
||||
settings: {parent: b}
|
||||
`)
|
||||
path := Keys("jobs")
|
||||
graph, diagnostics := analyzeIdentifiedInheritanceGraph(sequence, path, []string{"tenant", "id"})
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatalf("analyze identified graph: %#v", diagnostics)
|
||||
}
|
||||
policies := collectionPolicyScope{}
|
||||
policies.set(path.Index(1).Key("steps"), collectionPolicy{
|
||||
identityFields: []string{"step-id"}, identityPresent: true,
|
||||
})
|
||||
result, diagnostics := applyIdentifiedInheritanceTemplates(graph, defaultProjectionLimits(), nil, policies, sequencePolicy{})
|
||||
if len(diagnostics) != 0 {
|
||||
t.Fatalf("apply identified templates: %#v", diagnostics)
|
||||
}
|
||||
if got := len(result.root.Sequence); got != 4 {
|
||||
t.Fatalf("result sequence length = %d, want 4", got)
|
||||
}
|
||||
for index, want := range []string{"child-a", "parent-a", "child-b", "parent-b"} {
|
||||
id, found := documentAtPath(result.root.Sequence[index], Path{}.Key("id"))
|
||||
if !found || id.Text != want {
|
||||
t.Fatalf("result identity at index %d = %#v, found %t; want %q", index, id, found, want)
|
||||
}
|
||||
}
|
||||
for index, want := range []string{"a", "b"} {
|
||||
value, found := documentAtPath(result.root.Sequence[index*2], Path{}.Key("settings").Key("parent"))
|
||||
if !found || value.Text != want {
|
||||
t.Fatalf("inherited value at record %d = %#v, found %t; want %q", index*2, value, found, want)
|
||||
}
|
||||
}
|
||||
if len(result.transfers) != 2 || result.transfers[0].from.String() != "/jobs/1" || result.transfers[0].to.String() != "/jobs/0" ||
|
||||
result.transfers[1].from.String() != "/jobs/3" || result.transfers[1].to.String() != "/jobs/2" {
|
||||
t.Fatalf("record transfers = %#v, want independent transfers at authored positions", result.transfers)
|
||||
}
|
||||
if len(result.controls) != 2 || result.controls[0].path.String() != "/jobs/0/extends" || result.controls[1].path.String() != "/jobs/2/extends" {
|
||||
t.Fatalf("relationship controls = %#v, want paths from child positions", result.controls)
|
||||
}
|
||||
if len(result.operations) != 4 || result.operations[1].transfer == nil || result.operations[1].transfer.to.String() != "/jobs/0" ||
|
||||
result.operations[3].transfer == nil || result.operations[3].transfer.to.String() != "/jobs/2" {
|
||||
t.Fatalf("relationship history operations = %#v, want transfer evidence at child positions", result.operations)
|
||||
}
|
||||
if _, found := result.origins[path.Index(0).Key("id").String()]; !found {
|
||||
t.Fatal("resolved sequence output did not retain the child identity origin path")
|
||||
}
|
||||
projectedPolicy, found := result.collectionPolicies.at(path.Index(0).Key("steps"))
|
||||
if !found || !projectedPolicy.identityPresent || len(projectedPolicy.identityFields) != 1 || projectedPolicy.identityFields[0] != "step-id" {
|
||||
t.Fatalf("inherited nested collection policy = %#v, found %t", projectedPolicy, found)
|
||||
}
|
||||
adapter := identifiedSequenceInheritanceScope{graph: graph, policies: policies}
|
||||
fields := adapter.templates()[0].identityFields
|
||||
if len(fields) != 2 || fields[0] != "id" || fields[1] != "tenant" {
|
||||
t.Fatalf("payload identity fields = %v, want [id tenant]", fields)
|
||||
}
|
||||
templates := adapter.templates()
|
||||
parentPolicy, found := templates[1].collectionPolicies.at(Keys("steps"))
|
||||
if !found || len(parentPolicy.identityFields) != 1 || parentPolicy.identityFields[0] != "step-id" {
|
||||
t.Fatalf("parent nested policy = %#v, found %t", parentPolicy, found)
|
||||
}
|
||||
if _, found := templates[0].collectionPolicies.at(Keys("steps")); found {
|
||||
t.Fatal("nested policy from one record leaked into a sibling template")
|
||||
}
|
||||
parentPolicy.identityFields[0] = "changed"
|
||||
templates[1].collectionPolicies.set(Keys("steps"), parentPolicy)
|
||||
reused, found := adapter.templates()[1].collectionPolicies.at(Keys("steps"))
|
||||
if !found || len(reused.identityFields) != 1 || reused.identityFields[0] != "step-id" {
|
||||
t.Fatal("reusing the adapter observed a mutation to a prior template snapshot")
|
||||
}
|
||||
if sequence.Sequence[0].Mapping[0].Value.Text != "child-a" {
|
||||
t.Fatal("executing the sequence adapter mutated its source scope")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifiedInheritanceRequiresChildIdentityBeforeParentLookup(t *testing.T) {
|
||||
sequence := parseIdentifiedInheritanceSequence(t, "missing-child-field", `- id: child
|
||||
extends: {id: parent, tenant: acme}
|
||||
|
||||
@@ -155,40 +155,45 @@ func expandSiblingDefinitionsWithCollectionRules(scope *document.Node, scopePath
|
||||
// dependency-ready order while retaining the existing origins, merge history,
|
||||
// and node-accounting evidence. The root keeps its authored mapping order.
|
||||
func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits projectionLimits, inputOrigins map[string]Origin, budget ...*retainedNodeCounter) (*inheritanceScope, []Diagnostic) {
|
||||
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))
|
||||
return applyInheritanceScopeTemplates(mappingInheritanceScope{graph: graph}, order, limits, inputOrigins, budget...)
|
||||
}
|
||||
|
||||
func applyInheritanceScopeTemplates(adapter inheritanceScopeAdapter, order []int, limits projectionLimits, inputOrigins map[string]Origin, budget ...*retainedNodeCounter) (*inheritanceScope, []Diagnostic) {
|
||||
templates := adapter.templates()
|
||||
resolved := make([]*document.Node, len(templates))
|
||||
resolvedOrigins := make([]map[string]Origin, len(templates))
|
||||
resolvedPolicyTemplates := make([][]collectionPolicyScope, len(templates))
|
||||
resolvedPolicies := make([]collectionPolicyScope, len(templates))
|
||||
result := &inheritanceScope{}
|
||||
counter := newRetainedNodeCounter(historyNodeLimit)
|
||||
if len(budget) != 0 {
|
||||
counter = budget[0]
|
||||
}
|
||||
retained := 1 // scope mapping node
|
||||
for _, entry := range graph.scope.Mapping {
|
||||
if entry.Value.Kind == document.Mapping {
|
||||
retained := 1 // scope container node
|
||||
for _, slot := range adapter.slots() {
|
||||
if slot.hasTemplate || slot.value.Kind == document.Mapping {
|
||||
continue
|
||||
}
|
||||
remaining := limits.nodes - retained - 1
|
||||
if limits.nodes >= 0 && remaining < 0 {
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(graph.scopePath.Key(entry.Key), entry.Value.Location)}
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(slot.path, slot.value.Location)}
|
||||
}
|
||||
count, within := inheritanceLowerBoundCount(entry.Value, remaining)
|
||||
count, within := inheritanceLowerBoundCount(slot.value, remaining)
|
||||
if !within {
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(graph.scopePath.Key(entry.Key), entry.Value.Location)}
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(slot.path, slot.value.Location)}
|
||||
}
|
||||
retained += 1 + count
|
||||
}
|
||||
|
||||
for _, index := range order {
|
||||
node := graph.nodes[index]
|
||||
node := templates[index]
|
||||
templatePolicies := cloneCollectionPolicyScopeForInheritance(node.collectionPolicies)
|
||||
payload := withoutInheritanceDirective(node.entry.Value)
|
||||
operationStart, replacementStart := len(result.operations), len(result.replacements)
|
||||
childOrigins := directInheritanceOrigins(payload, node.path, inputOrigins)
|
||||
if node.hasDirective {
|
||||
control := inheritanceControl{
|
||||
path: node.path.Key(inheritanceKey),
|
||||
path: node.directivePath,
|
||||
locations: []Location{publicLocation(node.directive.Value.Location)},
|
||||
cancelled: node.cancelled,
|
||||
}
|
||||
@@ -199,7 +204,7 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
})
|
||||
}
|
||||
if limits.nodes >= 0 {
|
||||
remaining := limits.nodes - retained - 1 // the sibling key
|
||||
remaining := limits.nodes - retained - adapter.slotOverhead()
|
||||
within := inheritanceLowerBoundWithin(payload, remaining)
|
||||
if node.hasParent {
|
||||
within = inheritanceOverlayLowerBoundWithin(resolved[node.parent], payload, remaining)
|
||||
@@ -217,14 +222,14 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
childPolicyScope := projectCurrentInheritanceCollectionPolicies(templatePolicies, node.path)
|
||||
merged := document.Clone(parent)
|
||||
mergedPolicyScope, policyDiagnostics := mergeInheritanceCollectionPolicies(
|
||||
parentPolicyScope, childPolicyScope, node.path, parent, graph.applicationPolicy,
|
||||
parentPolicyScope, childPolicyScope, node.path, parent, adapter.applicationPolicy(),
|
||||
)
|
||||
if len(policyDiagnostics) != 0 {
|
||||
return nil, policyDiagnostics
|
||||
}
|
||||
transfer := inheritanceTransfer{
|
||||
from: graph.nodes[node.parent].path, to: node.path,
|
||||
reference: node.path.Key(inheritanceKey),
|
||||
from: templates[node.parent].path, to: node.path,
|
||||
reference: node.directivePath,
|
||||
locations: []Location{publicLocation(node.directive.Value.Location)},
|
||||
policyTemplates: parentPolicies, templatePolicies: cloneCollectionPolicyScopeForInheritance(templatePolicies),
|
||||
projectedPolicies: projectInheritancePolicyTemplates(
|
||||
@@ -253,7 +258,7 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
},
|
||||
merge: func(childPath Path, existing, incoming *document.Node) (*document.Node, bool) {
|
||||
resolution, _, _, active, issues := inheritanceCollectionResolution(
|
||||
childPath, parentPolicyScope, childPolicyScope, graph.applicationPolicy,
|
||||
childPath, parentPolicyScope, childPolicyScope, adapter.applicationPolicy(),
|
||||
)
|
||||
if len(issues) != 0 {
|
||||
combinationDiagnostics = append(combinationDiagnostics, issues...)
|
||||
@@ -293,10 +298,11 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
return combined.value, true
|
||||
},
|
||||
})
|
||||
preserveInheritanceIdentityFields(merged, payload, node.identityFields)
|
||||
if len(combinationDiagnostics) != 0 {
|
||||
return nil, canonicalDiagnostics(combinationDiagnostics)
|
||||
}
|
||||
if problems := validateRegisteredInheritanceSequences(merged, node.path, graph.applicationPolicy); len(problems) != 0 {
|
||||
if problems := validateRegisteredInheritanceSequences(merged, node.path, adapter.applicationPolicy()); len(problems) != 0 {
|
||||
return nil, problems
|
||||
}
|
||||
merged.Location = node.entry.Value.Location
|
||||
@@ -320,7 +326,7 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
}
|
||||
|
||||
count, _ := inheritanceLowerBoundCount(resolved[index], limits.nodes)
|
||||
retained += 1 + count
|
||||
retained += adapter.slotOverhead() + count
|
||||
for _, operation := range result.operations[operationStart:] {
|
||||
if !counter.add(operation.parent) || !counter.add(operation.effective) {
|
||||
return nil, []Diagnostic{inheritanceHistoryBudgetDiagnostic(node.path, node.entry.Value.Location)}
|
||||
@@ -333,30 +339,27 @@ func applyInheritanceTemplates(graph *inheritanceGraph, order []int, limits proj
|
||||
}
|
||||
}
|
||||
|
||||
root := *graph.scope
|
||||
root.Mapping = make([]document.Entry, len(graph.scope.Mapping))
|
||||
root := adapter.rebuild(resolved)
|
||||
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)
|
||||
result.origins = directInheritanceOrigins(&document.Node{Kind: root.Kind, Location: root.Location}, adapter.scopePath(), inputOrigins)
|
||||
for _, slot := range adapter.slots() {
|
||||
if slot.hasTemplate {
|
||||
index := slot.template
|
||||
projectInheritancePolicyRoots(&result.collectionPolicies, resolvedPolicies[index], templates[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) {
|
||||
localPolicies := inheritancePolicyScopeAtPath(adapter.collectionPolicies(), slot.path)
|
||||
projectInheritancePolicyRoots(&result.collectionPolicies, localPolicies, slot.path)
|
||||
for pointer, origin := range directInheritanceOrigins(slot.value, slot.path, inputOrigins) {
|
||||
result.origins[pointer] = origin
|
||||
}
|
||||
}
|
||||
result.root = &root
|
||||
result.root = root
|
||||
if !inheritanceLowerBoundWithin(result.root, limits.nodes) {
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(graph.scopePath, graph.scope.Location)}
|
||||
return nil, []Diagnostic{inheritanceBudgetDiagnostic(adapter.scopePath(), adapter.scope().Location)}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
178
internal/engine/inheritance_scope.go
Normal file
178
internal/engine/inheritance_scope.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package engine
|
||||
|
||||
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
||||
|
||||
// inheritanceScopeAdapter keeps relationship execution independent from the
|
||||
// container that owns the records. Adapters are private preparation machinery;
|
||||
// public loading continues to use mapping scopes until record inheritance is
|
||||
// activated separately.
|
||||
type inheritanceScopeAdapter interface {
|
||||
scope() *document.Node
|
||||
scopePath() Path
|
||||
collectionPolicies() collectionPolicyScope
|
||||
applicationPolicy() sequencePolicy
|
||||
templates() []inheritanceExecutionTemplate
|
||||
slots() []inheritanceScopeSlot
|
||||
slotOverhead() int
|
||||
rebuild(resolved []*document.Node) *document.Node
|
||||
}
|
||||
|
||||
type inheritanceExecutionTemplate struct {
|
||||
entry document.Entry
|
||||
path Path
|
||||
collectionPolicies collectionPolicyScope
|
||||
parent int
|
||||
hasParent bool
|
||||
hasDirective bool
|
||||
cancelled bool
|
||||
directive document.Entry
|
||||
directivePath Path
|
||||
identityFields []string
|
||||
}
|
||||
|
||||
type inheritanceScopeSlot struct {
|
||||
value *document.Node
|
||||
path Path
|
||||
template int
|
||||
hasTemplate bool
|
||||
}
|
||||
|
||||
type mappingInheritanceScope struct{ graph *inheritanceGraph }
|
||||
|
||||
func (scope mappingInheritanceScope) scope() *document.Node { return scope.graph.scope }
|
||||
func (scope mappingInheritanceScope) scopePath() Path { return scope.graph.scopePath }
|
||||
func (scope mappingInheritanceScope) collectionPolicies() collectionPolicyScope {
|
||||
return scope.graph.collectionPolicies
|
||||
}
|
||||
func (scope mappingInheritanceScope) applicationPolicy() sequencePolicy {
|
||||
return scope.graph.applicationPolicy
|
||||
}
|
||||
func (scope mappingInheritanceScope) slotOverhead() int { return 1 }
|
||||
func (scope mappingInheritanceScope) templates() []inheritanceExecutionTemplate {
|
||||
result := make([]inheritanceExecutionTemplate, len(scope.graph.nodes))
|
||||
for index, node := range scope.graph.nodes {
|
||||
var directive document.Entry
|
||||
if node.hasDirective {
|
||||
directive = node.directive
|
||||
}
|
||||
result[index] = inheritanceExecutionTemplate{
|
||||
entry: node.entry, path: node.path,
|
||||
collectionPolicies: node.collectionPolicies, parent: node.parent,
|
||||
hasParent: node.hasParent, hasDirective: node.hasDirective,
|
||||
cancelled: node.cancelled, directive: directive,
|
||||
directivePath: node.path.Key(inheritanceKey),
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
func (scope mappingInheritanceScope) slots() []inheritanceScopeSlot {
|
||||
result := make([]inheritanceScopeSlot, len(scope.graph.scope.Mapping))
|
||||
for index, entry := range scope.graph.scope.Mapping {
|
||||
slot := inheritanceScopeSlot{
|
||||
value: entry.Value, path: scope.graph.scopePath.Key(entry.Key),
|
||||
}
|
||||
if template, ok := scope.graph.byName[entry.Key]; ok {
|
||||
slot.template, slot.hasTemplate = template, true
|
||||
}
|
||||
result[index] = slot
|
||||
}
|
||||
return result
|
||||
}
|
||||
func (scope mappingInheritanceScope) rebuild(resolved []*document.Node) *document.Node {
|
||||
root := *scope.graph.scope
|
||||
root.Mapping = make([]document.Entry, len(scope.graph.scope.Mapping))
|
||||
for index, entry := range scope.graph.scope.Mapping {
|
||||
root.Mapping[index] = entry
|
||||
if template, ok := scope.graph.byName[entry.Key]; ok {
|
||||
root.Mapping[index].Value = resolved[template]
|
||||
} else {
|
||||
root.Mapping[index].Value = document.Clone(entry.Value)
|
||||
}
|
||||
}
|
||||
return &root
|
||||
}
|
||||
|
||||
type identifiedSequenceInheritanceScope struct {
|
||||
graph *identifiedInheritanceGraph
|
||||
policies collectionPolicyScope
|
||||
application sequencePolicy
|
||||
}
|
||||
|
||||
func (scope identifiedSequenceInheritanceScope) scope() *document.Node { return scope.graph.scope }
|
||||
func (scope identifiedSequenceInheritanceScope) scopePath() Path { return scope.graph.scopePath }
|
||||
func (scope identifiedSequenceInheritanceScope) collectionPolicies() collectionPolicyScope {
|
||||
return scope.policies
|
||||
}
|
||||
func (scope identifiedSequenceInheritanceScope) applicationPolicy() sequencePolicy {
|
||||
return scope.application
|
||||
}
|
||||
func (scope identifiedSequenceInheritanceScope) slotOverhead() int { return 0 }
|
||||
func (scope identifiedSequenceInheritanceScope) templates() []inheritanceExecutionTemplate {
|
||||
result := make([]inheritanceExecutionTemplate, len(scope.graph.nodes))
|
||||
for index, node := range scope.graph.nodes {
|
||||
result[index] = inheritanceExecutionTemplate{
|
||||
entry: document.Entry{Value: node.item}, path: node.path,
|
||||
collectionPolicies: inheritancePolicyScopeAtPath(scope.policies, node.path),
|
||||
parent: node.parent, hasParent: node.hasParent,
|
||||
hasDirective: node.directive != nil, cancelled: node.cancelled,
|
||||
directive: document.Entry{Value: node.directive}, directivePath: node.directivePath,
|
||||
identityFields: scope.graph.fields,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
func (scope identifiedSequenceInheritanceScope) slots() []inheritanceScopeSlot {
|
||||
result := make([]inheritanceScopeSlot, len(scope.graph.nodes))
|
||||
for index, node := range scope.graph.nodes {
|
||||
result[index] = inheritanceScopeSlot{
|
||||
value: node.item, path: node.path, template: index, hasTemplate: true,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
func (scope identifiedSequenceInheritanceScope) rebuild(resolved []*document.Node) *document.Node {
|
||||
root := *scope.graph.scope
|
||||
root.Sequence = make([]*document.Node, len(scope.graph.nodes))
|
||||
for index := range root.Sequence {
|
||||
root.Sequence[index] = resolved[index]
|
||||
}
|
||||
return &root
|
||||
}
|
||||
|
||||
func preserveInheritanceIdentityFields(merged, child *document.Node, fields []string) {
|
||||
if len(fields) == 0 || merged == nil || merged.Kind != document.Mapping || child == nil || child.Kind != document.Mapping {
|
||||
return
|
||||
}
|
||||
for _, field := range fields {
|
||||
for _, entry := range child.Mapping {
|
||||
if entry.Key != field {
|
||||
continue
|
||||
}
|
||||
for index := range merged.Mapping {
|
||||
if merged.Mapping[index].Key == field {
|
||||
merged.Mapping[index] = document.Entry{Key: field, Value: document.Clone(entry.Value)}
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func applyIdentifiedInheritanceTemplates(
|
||||
graph *identifiedInheritanceGraph,
|
||||
limits projectionLimits,
|
||||
inputOrigins map[string]Origin,
|
||||
policies collectionPolicyScope,
|
||||
application sequencePolicy,
|
||||
budget ...*retainedNodeCounter,
|
||||
) (*inheritanceScope, []Diagnostic) {
|
||||
order, diagnostics := graph.schedule()
|
||||
if len(diagnostics) != 0 {
|
||||
return nil, diagnostics
|
||||
}
|
||||
adapter := identifiedSequenceInheritanceScope{
|
||||
graph: graph, policies: policies, application: application,
|
||||
}
|
||||
return applyInheritanceScopeTemplates(adapter, order, limits, inputOrigins, budget...)
|
||||
}
|
||||
Reference in New Issue
Block a user