Skip to content

Some experimentation with "composition over inheritence"

License

Notifications You must be signed in to change notification settings

maxhbr/spdx-3-model.hs

Repository files navigation

An implementation of spdx-3-model

This repository implements the datamodel defined in spdx-3-model.

Just a POC

This is just a proof of concept and probably roughtly 80% complete, but it has the following features

  • a datamodel, using GADTs
    • implementing “core” and “software” profile
  • complete serialization to JSON
    • example outputs are written to ./_testOut/
  • complete deserialization from JSON
  • conversion from SPDX 2.2 or 2.3 to 3.0

Some comments on the Serialization to JSON

Lets look at a Package:

{ 
    "@type": "Package",
    "SPDXID": "urn:spdx:curl-7.50.3-1",
    "comment": null,
    "contentIdentifier": null,
    "creationInfo": {
        "created": "2022-11-13T13:14:36.324980945Z",
        "createdBy": [
            {
                "actorType": "PERSON",
                "name": "Some Actor"
            },
            {
                "actorType": "TOOL",
                "name": "This Tool"
            }
        ],
        "dataLicense": "CC0-1.0",
        "profile": [
            {
                "name": "core"
            },
            {
                "name": "software"
            },
            {
                "name": "licensing"
            }
        ],
        "specVer": "3.0.0"
    },
    "description": null,
    "downloadLocation": null,
    "externalIdentifiers": [],
    "externalReferences": [],
    "homePage": null,
    "name": "curl-7.50.3-1",
    "originatedBy": [],
    "packagePurpose": [],
    "packageUrl": "pkg:deb/debian/[email protected]?arch=i386&distro=jessie",
    "summary": null,
    "verifiedUsing": []
}

This contanis all properties of Package, Artifact and Element, pulled to one flat JSON object. For parsing, the type is specified in @type, and here all fields are filled with dummy data or their default values. The null and [] entries are optional.

dropping all optional fields would result in:

{ 
    "@type": "Package",
    "SPDXID": "urn:spdx:curl-7.50.3-1",
    "creationInfo": {
        "created": "2022-11-13T13:14:36.324980945Z",
        "createdBy": [
            {
                "actorType": "PERSON",
                "name": "Some Actor"
            },
            {
                "actorType": "TOOL",
                "name": "This Tool"
            }
        ],
        "dataLicense": "CC0-1.0",
        "profile": [
            {
                "name": "core"
            },
            {
                "name": "software"
            },
            {
                "name": "licensing"
            }
        ],
        "specVer": "3.0.0"
    },
    "name": "curl-7.50.3-1",
    "packageUrl": "pkg:deb/debian/[email protected]?arch=i386&distro=jessie"
}

Lets pack it into a Collection:

Now lets pack the package from above into a collection, a SpdxDocument in this case. Lets give it the name ”Tho Document”, the SPDXID ”urn:spdx:Document” and the same creationInfo as our Package. Additionally we add a rather small Annotation that just contains the text ”some Annotation” and has our package as the subject. The subject can either be an inline Element or a String which is then the SPDXID.

{
    "@type": "SpdxDocument",
    "SPDXID": "urn:spdx:Document",
    "comment": null,
    "context": null,
    "creationInfo": {
        "created": "2022-11-13T13:14:36.324980945Z",
        "createdBy": [
            {
                "actorType": "PERSON",
                "name": "Some Actor"
            },
            {
                "actorType": "TOOL",
                "name": "This Tool"
            }
        ],
        "dataLicense": "CC0-1.0",
        "profile": [
            {
                "name": "core"
            },
            {
                "name": "software"
            },
            {
                "name": "licensing"
            }
        ],
        "specVer": "3.0.0"
    },
    "description": null,
    "elements": [
        {
            "@type": "Package",
            "SPDXID": "urn:spdx:curl-7.50.3-1",
            "comment": null,
            "contentIdentifier": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "downloadLocation": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "homePage": null,
            "name": "curl-7.50.3-1",
            "originatedBy": [],
            "packagePurpose": [],
            "packageUrl": "pkg:deb/debian/[email protected]?arch=i386&distro=jessie",
            "summary": null,
            "verifiedUsing": []
        },
        {
            "@type": "Annotation",
            "SPDXID": "urn:spdx:Annotation0",
            "comment": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "name": null,
            "statement": "some Annotation",
            "subject": "urn:spdx:curl-7.50.3-1",
            "summary": null,
            "verifiedUsing": []
        }
    ],
    "externalIdentifiers": [],
    "externalReferences": [],
    "imports": {},
    "name": "The Document",
    "namespaces": {},
    "rootElements": [],
    "summary": null,
    "verifiedUsing": []
}

For more complexity and for demonstrating inlining, lets add a Relationsihp:

Lets create two files (with generated SPDXIDs) contained in our Package, ”urn:File:efe40ac114769e83b4d4971da76295a4” and ”urn:File:65f2e7526fd42ae9f0893991e2473915”. Then add a Relationship which represents this, where one file is inlined and one is referenced and placed in the SpdxDocument. This defines two elements which then can be added to the document:

[...]
        {
            "@type": "Relationship",
            "SPDXID": "urn:Relationship:d74e9f23525b8766dc81f5ada441e4fb",
            "comment": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "from": "urn:spdx:curl-7.50.3-1",
            "name": null,
            "relationshipCompleteness": null,
            "relationshipType": "CONTAINS",
            "summary": null,
            "to": [
                "urn:File:efe40ac114769e83b4d4971da76295a4",
                {
                    "@type": "File",
                    "SPDXID": "urn:File:65f2e7526fd42ae9f0893991e2473915",
                    "comment": null,
                    "contentIdentifier": null,
                    "contentType": null,
                    "creationInfo": {
                        "created": "2022-11-13T13:14:36.324980945Z",
                        "createdBy": [
                            {
                                "actorType": "PERSON",
                                "name": "Some Actor"
                            },
                            {
                                "actorType": "TOOL",
                                "name": "This Tool"
                            }
                        ],
                        "dataLicense": "CC0-1.0",
                        "profile": [
                            {
                                "name": "core"
                            },
                            {
                                "name": "software"
                            },
                            {
                                "name": "licensing"
                            }
                        ],
                        "specVer": "3.0.0"
                    },
                    "description": null,
                    "externalIdentifiers": [],
                    "externalReferences": [],
                    "filePurpose": [],
                    "name": "path/to/the/file/f1",
                    "originatedBy": [],
                    "summary": null,
                    "verifiedUsing": []
                }
            ],
            "verifiedUsing": []
        },
        {
            "@type": "File",
            "SPDXID": "urn:File:efe40ac114769e83b4d4971da76295a4",
            "comment": null,
            "contentIdentifier": null,
            "contentType": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "filePurpose": [],
            "name": "path/to/the/file/f0",
            "originatedBy": [],
            "summary": null,
            "verifiedUsing": []
        }
[...]

The complete example:

this is basically roughtly similar to the example generated in _testOut/example.spdx3.json, and can look like:

{
    "@type": "SpdxDocument",
    "SPDXID": "urn:spdx:Document",
    "comment": null,
    "context": null,
    "creationInfo": {
        "created": "2022-11-13T13:14:36.324980945Z",
        "createdBy": [
            {
                "actorType": "PERSON",
                "name": "Some Actor"
            },
            {
                "actorType": "TOOL",
                "name": "This Tool"
            }
        ],
        "dataLicense": "CC0-1.0",
        "profile": [
            {
                "name": "core"
            },
            {
                "name": "software"
            },
            {
                "name": "licensing"
            }
        ],
        "specVer": "3.0.0"
    },
    "description": null,
    "elements": [
        {
            "@type": "Package",
            "SPDXID": "urn:spdx:curl-7.50.3-1",
            "comment": null,
            "contentIdentifier": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "downloadLocation": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "homePage": null,
            "name": "curl-7.50.3-1",
            "originatedBy": [],
            "packagePurpose": [],
            "packageUrl": "pkg:deb/debian/[email protected]?arch=i386&distro=jessie",
            "summary": null,
            "verifiedUsing": []
        },
        {
            "@type": "Annotation",
            "SPDXID": "urn:spdx:Annotation0",
            "comment": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "name": null,
            "statement": "some Annotation",
            "subject": "urn:spdx:curl-7.50.3-1",
            "summary": null,
            "verifiedUsing": []
        },
        {
            "@type": "Relationship",
            "SPDXID": "urn:Relationship:d74e9f23525b8766dc81f5ada441e4fb",
            "comment": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "from": "urn:spdx:curl-7.50.3-1",
            "name": null,
            "relationshipCompleteness": null,
            "relationshipType": "CONTAINS",
            "summary": null,
            "to": [
                "urn:File:efe40ac114769e83b4d4971da76295a4",
                {
                    "@type": "File",
                    "SPDXID": "urn:File:65f2e7526fd42ae9f0893991e2473915",
                    "comment": null,
                    "contentIdentifier": null,
                    "contentType": null,
                    "creationInfo": {
                        "created": "2022-11-13T13:14:36.324980945Z",
                        "createdBy": [
                            {
                                "actorType": "PERSON",
                                "name": "Some Actor"
                            },
                            {
                                "actorType": "TOOL",
                                "name": "This Tool"
                            }
                        ],
                        "dataLicense": "CC0-1.0",
                        "profile": [
                            {
                                "name": "core"
                            },
                            {
                                "name": "software"
                            },
                            {
                                "name": "licensing"
                            }
                        ],
                        "specVer": "3.0.0"
                    },
                    "description": null,
                    "externalIdentifiers": [],
                    "externalReferences": [],
                    "filePurpose": [],
                    "name": "path/to/the/file/f1",
                    "originatedBy": [],
                    "summary": null,
                    "verifiedUsing": []
                }
            ],
            "verifiedUsing": []
        },
        {
            "@type": "File",
            "SPDXID": "urn:File:efe40ac114769e83b4d4971da76295a4",
            "comment": null,
            "contentIdentifier": null,
            "contentType": null,
            "creationInfo": {
                "created": "2022-11-13T13:14:36.324980945Z",
                "createdBy": [
                    {
                        "actorType": "PERSON",
                        "name": "Some Actor"
                    },
                    {
                        "actorType": "TOOL",
                        "name": "This Tool"
                    }
                ],
                "dataLicense": "CC0-1.0",
                "profile": [
                    {
                        "name": "core"
                    },
                    {
                        "name": "software"
                    },
                    {
                        "name": "licensing"
                    }
                ],
                "specVer": "3.0.0"
            },
            "description": null,
            "externalIdentifiers": [],
            "externalReferences": [],
            "filePurpose": [],
            "name": "path/to/the/file/f0",
            "originatedBy": [],
            "summary": null,
            "verifiedUsing": []
        }
    ],
    "externalIdentifiers": [],
    "externalReferences": [],
    "imports": {},
    "name": "The Document",
    "namespaces": {},
    "rootElements": [],
    "summary": null,
    "verifiedUsing": []
}

About

Some experimentation with "composition over inheritence"

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published