As part of the suggested refactorings I proposed, it was noted that the utility functions such as idsearcher.go, which duplicate functionality for SPDX 2.1, 2.2, etc. could be made more generic using some reflection (and/or generics, which I don't think will help here).
Additionally, there is a desire to have the ability to convert between format versions. I propose using a "migration" approach for this and have created some functionality that does quite a lot of the work automatically, with heavy use of reflection.
I've created a draft PR here: kzantow-anchore#2 to illustrate how this can work, along with a full document conversion from a 2_2 to a 2_3 struct.
The gist of this approach is twofold:
- Use reflection to recursively map all fields from one struct to another based on convertible fields:
- fields with the same name and convertible types are automatically handled
- slices, maps, structs, and primitive types are currently handled
- each struct may implement a
ConvertFrom method, which runs after the automatic conversion to correct, add, or modify the resulting struct, being passed the struct from which it was originally converted
- Set up a migration list so each version (v2_2, v2_3) can implement a
ConvertFrom method from the previous (and possibly next) version. Implement a function that, given a specific version and a specific target, walks the list through each intermediate version conversion.
A ConvertFrom function for v2_3.Document would look something like:
func (t *Document) ConvertFrom(in interface{}) error {
if prior, ok := in.(v2_2.Document); ok {
// do any specific stuff here
}
t.SPDXVersion = "SPDX-2.3"
return nil
}
As part of the suggested refactorings I proposed, it was noted that the utility functions such as
idsearcher.go, which duplicate functionality for SPDX 2.1, 2.2, etc. could be made more generic using some reflection (and/or generics, which I don't think will help here).Additionally, there is a desire to have the ability to convert between format versions. I propose using a "migration" approach for this and have created some functionality that does quite a lot of the work automatically, with heavy use of reflection.
I've created a draft PR here: kzantow-anchore#2 to illustrate how this can work, along with a full document conversion from a 2_2 to a 2_3 struct.
The gist of this approach is twofold:
ConvertFrommethod, which runs after the automatic conversion to correct, add, or modify the resulting struct, being passed the struct from which it was originally convertedConvertFrommethod from the previous (and possibly next) version. Implement a function that, given a specific version and a specific target, walks the list through each intermediate version conversion.A
ConvertFromfunction forv2_3.Documentwould look something like: