Index collection policy retirement
This commit is contained in:
137
internal/engine/collection_policy_index.go
Normal file
137
internal/engine/collection_policy_index.go
Normal file
@@ -0,0 +1,137 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user