Working through components what-changed code.

Moved comparison function for map checking to be async, removed the untyped variation as it's no longer required. Getting prepared for tests
This commit is contained in:
Dave Shanley
2022-11-14 16:57:14 -05:00
parent 1abc25a923
commit f66c77ccb5
5 changed files with 231 additions and 78 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/pb33f/libopenapi/datamodel/low"
"gopkg.in/yaml.v3"
"strings"
"sync"
)
const (
@@ -184,74 +185,8 @@ func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Chan
func CheckMapForChanges[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
changes *[]*Change, label string, compareFunc func(l, r T) R) map[string]R {
lHashes := make(map[string]string)
rHashes := make(map[string]string)
lValues := make(map[string]low.ValueReference[T])
rValues := make(map[string]low.ValueReference[T])
for k := range expLeft {
lHashes[k.Value] = low.GenerateHashString(expLeft[k].Value)
lValues[k.Value] = expLeft[k]
}
for k := range expRight {
rHashes[k.Value] = low.GenerateHashString(expRight[k].Value)
rValues[k.Value] = expRight[k]
}
expChanges := make(map[string]R)
checkLeft := func(k string, doneChan chan bool, f, g map[string]string, p, h map[string]low.ValueReference[T]) {
rhash := g[k]
if rhash == "" {
if p[k].GetValueNode().Value == "" {
p[k].GetValueNode().Value = k
}
CreateChange(changes, ObjectRemoved, label,
p[k].GetValueNode(), nil, true,
p[k].GetValue(), nil)
doneChan <- true
return
}
if f[k] == g[k] {
doneChan <- true
return
}
// run comparison.
expChanges[k] = compareFunc(p[k].Value, h[k].Value)
doneChan <- true
}
doneChan := make(chan bool)
count := 0
// check left example hashes
for k := range lHashes {
count++
go checkLeft(k, doneChan, lHashes, rHashes, lValues, rValues)
}
//check right example hashes
for k := range rHashes {
count++
go checkRightValue(k, doneChan, lHashes, rValues, changes, label)
}
// wait for all done signals.
completed := 0
for completed < count {
select {
case <-doneChan:
completed++
}
}
return expChanges
}
// CheckMapForChangesUntyped checks a left and right low level map for any additions, subtractions or modifications to
// values. The compareFunc can be generic and accept any type
func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
changes *[]*Change, label string, compareFunc func(l, r any) R) map[string]R {
// stop concurrent threads screwing up changes.
var chLock sync.Mutex
lHashes := make(map[string]string)
rHashes := make(map[string]string)
@@ -276,9 +211,11 @@ func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyRefere
if p[k].GetValueNode().Value == "" {
p[k].GetValueNode().Value = k
}
chLock.Lock()
CreateChange(changes, ObjectRemoved, label,
p[k].GetValueNode(), nil, true,
p[k].GetValue(), nil)
chLock.Unlock()
doneChan <- true
return
}
@@ -303,7 +240,7 @@ func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyRefere
//check right example hashes
for k := range rHashes {
count++
go checkRightValue(k, doneChan, lHashes, rValues, changes, label)
go checkRightValue(k, doneChan, lHashes, rValues, changes, label, &chLock)
}
// wait for all done signals.
@@ -317,17 +254,88 @@ func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyRefere
return expChanges
}
//// CheckMapForChangesUntyped checks a left and right low level map for any additions, subtractions or modifications to
//// values. The compareFunc can be generic and accept any type
//func CheckMapForChangesUntyped[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
// changes *[]*Change, label string, compareFunc func(l, r any) R) map[string]R {
//
// lHashes := make(map[string]string)
// rHashes := make(map[string]string)
// lValues := make(map[string]low.ValueReference[T])
// rValues := make(map[string]low.ValueReference[T])
//
// for k := range expLeft {
// lHashes[k.Value] = low.GenerateHashString(expLeft[k].Value)
// lValues[k.Value] = expLeft[k]
// }
//
// for k := range expRight {
// rHashes[k.Value] = low.GenerateHashString(expRight[k].Value)
// rValues[k.Value] = expRight[k]
// }
//
// expChanges := make(map[string]R)
//
// checkLeft := func(k string, doneChan chan bool, f, g map[string]string, p, h map[string]low.ValueReference[T]) {
// rhash := g[k]
// if rhash == "" {
// if p[k].GetValueNode().Value == "" {
// p[k].GetValueNode().Value = k // yes, a dirty thing, but it's clean for the consumer.
// }
// CreateChange(changes, ObjectRemoved, label,
// p[k].GetValueNode(), nil, true,
// p[k].GetValue(), nil)
// doneChan <- true
// return
// }
// if f[k] == g[k] {
// doneChan <- true
// return
// }
// // run comparison.
// expChanges[k] = compareFunc(p[k].Value, h[k].Value)
// doneChan <- true
// }
//
// doneChan := make(chan bool)
// count := 0
//
// // check left example hashes
// for k := range lHashes {
// count++
// go checkLeft(k, doneChan, lHashes, rHashes, lValues, rValues)
// }
//
// //check right example hashes
// for k := range rHashes {
// count++
// go checkRightValue(k, doneChan, lHashes, rValues, changes, label)
// }
//
// // wait for all done signals.
// completed := 0
// for completed < count {
// select {
// case <-doneChan:
// completed++
// }
// }
// return expChanges
//}
func checkRightValue[T any](k string, doneChan chan bool, f map[string]string, p map[string]low.ValueReference[T],
changes *[]*Change, label string) {
changes *[]*Change, label string, lock *sync.Mutex) {
lhash := f[k]
if lhash == "" {
if p[k].GetValueNode().Value == "" {
p[k].GetValueNode().Value = k
p[k].GetValueNode().Value = k // this is kinda dirty, but I don't want to duplicate code so sue me.
}
lock.Lock()
CreateChange(changes, ObjectAdded, label,
nil, p[k].GetValueNode(), false,
nil, p[k].GetValue())
lock.Unlock()
}
doneChan <- true
}