Files
ConfigKit/internal/engine/collection_policy_index.go

138 lines
4.3 KiB
Go

package engine
// collectionPolicyRetirementIndex locates only assembly policies whose YAML
// identity or record-owned state can be cleared by an ancestor replacement.
// Mapping keys and sequence indexes remain distinct through pathSegment keys.
type collectionPolicyRetirementIndex struct {
children map[pathSegment]*collectionPolicyRetirementIndex
entryKey string
hasEntry bool
}
func newCollectionPolicyRetirementIndex(scope collectionPolicyScope) *collectionPolicyRetirementIndex {
index := &collectionPolicyRetirementIndex{}
for _, entry := range scope.collections {
if collectionPolicyHasRetirementState(entry.policy) {
index.set(entry)
}
}
return index
}
func (index *collectionPolicyRetirementIndex) set(entry collectionPolicyEntry) {
node := index
for _, segment := range entry.destination.segments {
if node.children == nil {
node.children = make(map[pathSegment]*collectionPolicyRetirementIndex)
}
if node.children[segment] == nil {
node.children[segment] = &collectionPolicyRetirementIndex{}
}
node = node.children[segment]
}
node.entryKey = entry.destination.String()
node.hasEntry = true
}
func (index *collectionPolicyRetirementIndex) remove(destination Path) {
if index == nil {
return
}
nodes := make([]*collectionPolicyRetirementIndex, 1, len(destination.segments)+1)
nodes[0] = index
node := index
for _, segment := range destination.segments {
node = node.children[segment]
if node == nil {
return
}
nodes = append(nodes, node)
}
node.entryKey = ""
node.hasEntry = false
pruneCollectionPolicyIndex(nodes, destination.segments)
}
func (index *collectionPolicyRetirementIndex) retire(scope *collectionPolicyScope, ancestor Path) {
if index == nil || scope == nil {
return
}
nodes := make([]*collectionPolicyRetirementIndex, 1, len(ancestor.segments)+1)
nodes[0] = index
node := index
for _, segment := range ancestor.segments {
node = node.children[segment]
if node == nil {
return
}
nodes = append(nodes, node)
}
index.clearSubtree(scope, node)
pruneCollectionPolicyIndex(nodes, ancestor.segments)
}
func (index *collectionPolicyRetirementIndex) clearSubtree(scope *collectionPolicyScope, node *collectionPolicyRetirementIndex) {
if node.hasEntry {
if entry, found := scope.collections[node.entryKey]; found {
clearCollectionIdentity(&entry.policy)
scope.collections[node.entryKey] = entry
}
node.entryKey = ""
node.hasEntry = false
}
for segment, child := range node.children {
index.clearSubtree(scope, child)
if child.empty() {
delete(node.children, segment)
}
}
if len(node.children) == 0 {
node.children = nil
}
}
func (index *collectionPolicyRetirementIndex) empty() bool {
return index == nil || !index.hasEntry && len(index.children) == 0
}
func pruneCollectionPolicyIndex(nodes []*collectionPolicyRetirementIndex, segments []pathSegment) {
for position := len(segments) - 1; position >= 0; position-- {
child := nodes[position+1]
if !child.empty() {
return
}
delete(nodes[position].children, segments[position])
}
}
func collectionPolicyHasRetirementState(policy collectionPolicy) bool {
return policy.identityFields != nil || policy.identityPresent || policy.identityLocation != nil ||
policy.recordOrder != nil || policy.recordPolicies != nil
}
func (assembly *assemblyAccumulator) setCollectionPolicy(destination Path, policy collectionPolicy) {
if assembly == nil || assembly.current == nil {
return
}
if assembly.collectionPolicyRetirement == nil {
assembly.collectionPolicyRetirement = newCollectionPolicyRetirementIndex(assembly.current.collectionPolicies)
}
assembly.current.collectionPolicies.set(destination, policy)
entry := assembly.current.collectionPolicies.collections[destination.String()]
if collectionPolicyHasRetirementState(entry.policy) {
assembly.collectionPolicyRetirement.set(entry)
} else {
assembly.collectionPolicyRetirement.remove(destination)
}
}
func (assembly *assemblyAccumulator) retireCollectionPoliciesAtOrBelow(ancestor Path) {
if assembly == nil || assembly.current == nil {
return
}
if assembly.collectionPolicyRetirement == nil {
assembly.collectionPolicyRetirement = newCollectionPolicyRetirementIndex(assembly.current.collectionPolicies)
}
assembly.collectionPolicyRetirement.retire(&assembly.current.collectionPolicies, ancestor)
}