in pkg/log/structure/merger/merged.go [145:296]
func (d *StrategicMergedStructureData) Value(fieldName string) (any, error) {
ty, err := d.Type()
if err != nil {
return nil, err
}
switch ty {
case structuredata.StructuredTypeScalar:
patchPolicy, err := d.readScalarAsString(d.patch, "$patch")
if err == nil && patchPolicy == "delete" {
return nil, nil
}
return d.patch.Value(fieldName)
case structuredata.StructuredTypeMap:
if fieldName == "" {
return d, nil
}
patchPolicy, err := d.readScalarAsString(d.patch, "$patch")
if err == nil && patchPolicy == "replace" {
return d.patch.Value(fieldName)
}
retainKeysAttr, err := d.readStringArray(d.patch, "$retainKeys")
if err == nil {
kept := false
for _, key := range retainKeysAttr {
if key == fieldName {
kept = true
break
}
}
if !kept {
return fmt.Errorf("field not found:%s(patched by delete already)", fieldName), nil
}
}
prevFound := false
patchFound := false
var patchValueStructure structuredata.StructureData
var prevValueStructure structuredata.StructureData
patchValue, err := d.patch.Value(fieldName)
if err == nil {
var convertible bool
patchFound = true
patchValueStructure, convertible = patchValue.(structuredata.StructureData)
if !convertible {
return nil, fmt.Errorf("unreachable. Map children was not the structure data")
}
}
prevValue, err := d.prev.Value(fieldName)
if err == nil {
var convertible bool
prevValueStructure, convertible = prevValue.(structuredata.StructureData)
if !convertible {
return nil, fmt.Errorf("unreachable. Map children was not the structure data")
}
prevValueType, err := prevValueStructure.Type()
if err != nil {
return nil, err
}
// Ignore if the previous value is nil
if prevValueType == structuredata.StructuredTypeScalar {
prevActualValue, err := prevValueStructure.Value("")
if err != nil {
return nil, err
}
if prevActualValue != nil {
prevFound = true
} else if !patchFound {
return prevValueStructure, nil
}
} else {
prevFound = true
}
}
switch {
case prevFound && patchFound:
result := NewStrategicMergedStructureData(fmt.Sprintf("%s.%s", d.path, fieldName), prevValueStructure, patchValueStructure, d.mergeKeyResolver)
deleteFromPrimitiveList, err := d.readArray(d.patch, fmt.Sprintf("$deleteFromPrimitiveList/%s", fieldName))
if err == nil {
result.deleteFromPrimitiveListDirective = &deleteFromPrimitiveListDirective{
list: deleteFromPrimitiveList,
}
}
setOrderElementList, err := d.readArray(d.patch, fmt.Sprintf("$setElementOrder/%s", fieldName))
if err == nil {
result.setElementOrderDirective = &setElementOrderDirective{
list: setOrderElementList,
}
}
return result, nil
case prevFound:
result := NewStrategicMergedStructureData(fmt.Sprintf("%s.%s", d.path, fieldName), prevValueStructure, prevValueStructure, d.mergeKeyResolver)
deleteFromPrimitiveList, err := d.readArray(d.patch, fmt.Sprintf("$deleteFromPrimitiveList/%s", fieldName))
if err == nil {
result.deleteFromPrimitiveListDirective = &deleteFromPrimitiveListDirective{
list: deleteFromPrimitiveList,
}
}
setOrderElementList, err := d.readArray(d.patch, fmt.Sprintf("$setElementOrder/%s", fieldName))
if err == nil {
result.setElementOrderDirective = &setElementOrderDirective{
list: setOrderElementList,
}
}
return result, nil
case patchFound:
result := NewStrategicMergedStructureData(fmt.Sprintf("%s.%s", d.path, fieldName), patchValueStructure, patchValueStructure, d.mergeKeyResolver)
deleteFromPrimitiveList, err := d.readArray(d.patch, fmt.Sprintf("$deleteFromPrimitiveList/%s", fieldName))
if err == nil {
result.deleteFromPrimitiveListDirective = &deleteFromPrimitiveListDirective{
list: deleteFromPrimitiveList,
}
}
setOrderElementList, err := d.readArray(d.patch, fmt.Sprintf("$setElementOrder/%s", fieldName))
if err == nil {
result.setElementOrderDirective = &setElementOrderDirective{
list: setOrderElementList,
}
}
return result, nil
default:
return nil, fmt.Errorf("field not found:%s", fieldName)
}
case structuredata.StructuredTypeArray:
if fieldName == "" {
return d, nil
}
if d.arrayMergeResultSourceCache == nil {
err := d.buildArrayMergeResultSourceCache()
if err != nil {
return nil, err
}
}
index, err := strconv.Atoi(fieldName)
if err != nil {
return nil, err
}
if index < 0 || index >= len(d.arrayMergeResultSourceCache.References) {
return nil, fmt.Errorf("index out of range")
}
ref := d.arrayMergeResultSourceCache.References[index]
if ref.Index == "" {
return ref.From, nil
}
return ref.From.Value(ref.Index)
default:
return nil, fmt.Errorf("unsupported type to merge")
}
}