spdx/tools-golang

Reduce utility duplication by implementing document conversions

kzantow opened this issue · 0 comments

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:

  1. 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
  1. 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
}