func()

in pkg/log/structure/merger/merged.go [298:455]


func (d *StrategicMergedStructureData) buildArrayMergeResultSourceCache() error {
	d.arrayMergeResultSourceCache = &arrayMergeResultSourceCache{
		References: make([]*arrayMergeResultElementReference, 0),
	}
	patchKeys, err := d.patch.Keys()
	if err != nil {
		return err
	}
	strategy := d.mergeKeyResolver.GetMergeArrayStrategy(d.path)
	if strategy == MergeStrategyReplace {
		for _, key := range patchKeys {
			d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
				From:  d.patch,
				Index: key,
			})
		}
	} else {
		mergeKey, err := d.mergeKeyResolver.GetMergeKey(d.path)
		if err != nil {
			return err
		}
		patchElements, err := d.splitPatchKeysByElementsOrMergeAttributesInArray(d.patch)
		if err != nil {
			return err
		}
		if patchElements.Replace {
			for _, elem := range patchElements.Elements {
				d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
					From:  elem,
					Index: "",
				})
			}
			return nil
		}
		prevFields := []structuredata.StructureData{}
		prevKeys, err := d.prev.Keys()
		if err != nil {
			return err
		}
		if len(prevKeys) == 1 && prevKeys[0] == "" {
			// The previous value is nil
		} else {
			for _, key := range prevKeys {
				vany, err := d.prev.Value(key)
				if err != nil {
					return err
				}
				vst, convertible := vany.(structuredata.StructureData)
				if !convertible {
					return fmt.Errorf("expected vany to be convertible to structuredata, but didn't")
				}
				prevFields = append(prevFields, vst)
			}
		}
		prevFieldsKeyOrder := []string{}
		prevFieldsMap := map[string]structuredata.StructureData{}
		for _, field := range prevFields {
			keyValue, err := d.readScalar(field, mergeKey)
			if err != nil {
				return fmt.Errorf("merge key %s not found in prev field map", mergeKey)
			}
			hash, err := toHash(keyValue)
			if err != nil {
				return err
			}
			prevFieldsKeyOrder = append(prevFieldsKeyOrder, hash)
			prevFieldsMap[hash] = field
		}
		patchFieldKeyOrder := []string{}
		patchFieldMap := map[string]structuredata.StructureData{}
		for _, field := range patchElements.Elements {
			keyValue, err := d.readScalar(field, mergeKey)
			if err != nil {
				return fmt.Errorf("merge key %s not found in patch field map", mergeKey)
			}
			hash, err := toHash(keyValue)
			if err != nil {
				return err
			}
			patchFieldKeyOrder = append(patchFieldKeyOrder, hash)
			patchFieldMap[hash] = field
		}
		deletedMap := map[string]struct{}{}
		if d.deleteFromPrimitiveListDirective != nil {
			for _, primitive := range d.deleteFromPrimitiveListDirective.list {
				hash, err := toHash(primitive)
				if err != nil {
					return err
				}
				deletedMap[hash] = struct{}{}
			}
		}
		for _, field := range patchElements.DeletedFields {
			key, err := d.readScalarAsString(field, mergeKey)
			if err != nil {
				return err
			}
			deletedMap[key] = struct{}{}
		}
		keydiff := NewKeyDiffForArrayMerge(prevFieldsKeyOrder, patchFieldKeyOrder)
		setElementOrderKeys := []string{}
		if d.setElementOrderDirective != nil {
			for _, orderKeyValue := range d.setElementOrderDirective.list {
				if structuredata, convertible := orderKeyValue.(structuredata.StructureData); convertible {
					orderKeyValue, err = d.readScalar(structuredata, mergeKey)
					if err != nil {
						return err
					}
				}
				hash, err := toHash(orderKeyValue)
				if err != nil {
					return err
				}
				setElementOrderKeys = append(setElementOrderKeys, hash)
			}
		}
		orderedKeys := reorderArrayKeysForMerge(prevFieldsKeyOrder, patchFieldKeyOrder, setElementOrderKeys)
		bothKeys := map[string]struct{}{}
		for _, key := range keydiff.Both {
			bothKeys[key] = struct{}{}
		}
		for _, key := range orderedKeys {
			if _, found := deletedMap[key]; found {
				continue
			}
			if _, found := bothKeys[key]; found {
				d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
					From:  NewStrategicMergedStructureData(d.path+"[]", prevFieldsMap[key], patchFieldMap[key], d.mergeKeyResolver),
					Index: "",
				})
				continue
			}
			if _, found := patchFieldMap[key]; found {
				d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
					From:  patchFieldMap[key],
					Index: "",
				})
				continue
			}
			if _, found := prevFieldsMap[key]; found {
				d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
					From:  prevFieldsMap[key],
					Index: "",
				})
				continue
			}
			complemented, err := structuredata.DataFromYaml(fmt.Sprintf("%s: %s", mergeKey, key))
			if err != nil {
				return err
			}
			d.arrayMergeResultSourceCache.References = append(d.arrayMergeResultSourceCache.References, &arrayMergeResultElementReference{
				From:  complemented,
				Index: "",
			})
		}
	}
	return nil
}