138 lines
4.3 KiB
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)
|
|
}
|