Retire obsolete collection identity before replacement agreement
This commit is contained in:
81
internal/engine/collection_retirement.go
Normal file
81
internal/engine/collection_retirement.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package engine
|
||||
|
||||
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
||||
|
||||
// A true entry replaces the collection itself as well as its descendants;
|
||||
// false records ordinary ancestor replacement without selecting a collection
|
||||
// operation at that exact path.
|
||||
type collectionReplacementPaths map[string]bool
|
||||
|
||||
func (paths collectionReplacementPaths) contains(path Path, includeExact bool) bool {
|
||||
for length := 0; length <= len(path.segments); length++ {
|
||||
prefix := Path{segments: path.segments[:length]}
|
||||
inclusive, found := paths[prefix.String()]
|
||||
if found && (length < len(path.segments) || includeExact && inclusive) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// lowerCollectionPoliciesForClaims makes replacement eligibility independent of
|
||||
// declaration order. It removes only old YAML identity/record state; new pending
|
||||
// declarations and application constraints are reconciled afterward.
|
||||
func lowerCollectionPoliciesForClaims(
|
||||
lower collectionPolicyScope,
|
||||
claims []compositionClaim,
|
||||
declarations map[string][]sequenceDeclarationSpec,
|
||||
application sequencePolicy,
|
||||
) (collectionPolicyScope, collectionReplacementPaths) {
|
||||
byPath := make(map[string]compositionClaim, len(claims))
|
||||
rootPath := ""
|
||||
if len(claims) != 0 {
|
||||
rootPath = claims[0].path.String()
|
||||
}
|
||||
for _, claim := range claims {
|
||||
byPath[claim.path.String()] = claim
|
||||
}
|
||||
replaced := make(collectionReplacementPaths)
|
||||
for key, claim := range byPath {
|
||||
old, hasOld := lower.collections[key]
|
||||
current := declarations[key]
|
||||
if claim.kind == document.Mapping && (key == rootPath || !hasOld && len(current) == 0) {
|
||||
continue // Ordinary mapping combination preserves descendants.
|
||||
}
|
||||
mode := sequenceMode(0)
|
||||
identity := old.policy.identityPresent
|
||||
for _, declaration := range current {
|
||||
identity = identity || declaration.identityPresent
|
||||
if mode == 0 && declaration.modePresent {
|
||||
mode = declaration.mode
|
||||
}
|
||||
}
|
||||
retainedMode := sequenceMode(0)
|
||||
if old.policy.explicitModePresent {
|
||||
retainedMode = old.policy.explicitMode
|
||||
}
|
||||
_, registered := application.identityFieldsAt(claim.path)
|
||||
mode = collectionOperationMode(mode, retainedMode, identity || registered)
|
||||
if mode == sequenceModeReplace {
|
||||
replaced[key] = true
|
||||
} else if claim.kind != document.Mapping && claim.kind != document.Sequence {
|
||||
replaced[key] = false
|
||||
}
|
||||
}
|
||||
result := cloneCollectionPolicyScope(lower)
|
||||
for key, entry := range result.collections {
|
||||
if replaced.contains(entry.destination, true) {
|
||||
clearCollectionIdentity(&entry.policy)
|
||||
result.collections[key] = entry
|
||||
}
|
||||
}
|
||||
return result, replaced
|
||||
}
|
||||
|
||||
func clearCollectionIdentity(policy *collectionPolicy) {
|
||||
policy.identityFields = nil
|
||||
policy.identityPresent = false
|
||||
policy.identityLocation = nil
|
||||
policy.recordOrder = nil
|
||||
policy.recordPolicies = nil
|
||||
}
|
||||
Reference in New Issue
Block a user