1# Copyright (c) 2021 The Linux Foundation
2#
3# SPDX-License-Identifier: Apache-2.0
4
5from enum import Enum
6
7# DocumentConfig contains settings used to configure how the SPDX Document
8# should be built.
9class DocumentConfig:
10    def __init__(self):
11        super(DocumentConfig, self).__init__()
12
13        # name of document
14        self.name = ""
15
16        # namespace for this document
17        self.namespace = ""
18
19        # standardized DocumentRef- (including that prefix) that the other
20        # docs will use to refer to this one
21        self.docRefID = ""
22
23# Document contains the data assembled by the SBOM builder, to be used to
24# create the actual SPDX Document.
25class Document:
26    # initialize with a DocumentConfig
27    def __init__(self, cfg):
28        super(Document, self).__init__()
29
30        # configuration - DocumentConfig
31        self.cfg = cfg
32
33        # dict of SPDX ID => Package
34        self.pkgs = {}
35
36        # relationships "owned" by this Document, _not_ those "owned" by its
37        # Packages or Files; will likely be just DESCRIBES
38        self.relationships = []
39
40        # dict of filename (ignoring its directory) => number of times it has
41        # been seen while adding files to this Document; used to calculate
42        # useful SPDX IDs
43        self.timesSeen = {}
44
45        # dict of absolute path on disk => File
46        self.fileLinks = {}
47
48        # set of other Documents that our elements' Relationships refer to
49        self.externalDocuments = set()
50
51        # set of LicenseRef- custom licenses to be declared
52        # may or may not include "LicenseRef-" license prefix
53        self.customLicenseIDs = set()
54
55        # this Document's SHA1 hash, filled in _after_ the Document has been
56        # written to disk, so that others can refer to it
57        self.myDocSHA1 = ""
58
59# PackageConfig contains settings used to configure how an SPDX Package should
60# be built.
61class PackageConfig:
62    def __init__(self):
63        super(PackageConfig, self).__init__()
64
65        # package name
66        self.name = ""
67
68        # SPDX ID, including "SPDXRef-"
69        self.spdxID = ""
70
71        # the Package's declared license
72        self.declaredLicense = "NOASSERTION"
73
74        # the Package's copyright text
75        self.copyrightText = "NOASSERTION"
76
77        # absolute path of the "root" directory on disk, to be used as the
78        # base directory from which this Package's Files will calculate their
79        # relative paths
80        # may want to note this in a Package comment field
81        self.relativeBaseDir = ""
82
83# Package contains the data assembled by the SBOM builder, to be used to
84# create the actual SPDX Package.
85class Package:
86    # initialize with:
87    # 1) PackageConfig
88    # 2) the Document that owns this Package
89    def __init__(self, cfg, doc):
90        super(Package, self).__init__()
91
92        # configuration - PackageConfig
93        self.cfg = cfg
94
95        # Document that owns this Package
96        self.doc = doc
97
98        # verification code, calculated per section 3.9 of SPDX spec v2.2
99        self.verificationCode = ""
100
101        # concluded license for this Package, if
102        # cfg.shouldConcludePackageLicense == True; NOASSERTION otherwise
103        self.concludedLicense = "NOASSERTION"
104
105        # list of licenses found in this Package's Files
106        self.licenseInfoFromFiles = []
107
108        # Files in this Package
109        # dict of SPDX ID => File
110        self.files = {}
111
112        # Relationships "owned" by this Package (e.g., this Package is left
113        # side)
114        self.rlns = []
115
116        # If this Package was a target, which File was its main build product?
117        self.targetBuildFile = None
118
119# RelationshipDataElementType defines whether a RelationshipData element
120# (e.g., the "owner" or the "other" element) is a File, a target Package,
121# a Package's ID (as other only, and only where owner type is DOCUMENT),
122# or the SPDX document itself (as owner only).
123class RelationshipDataElementType(Enum):
124    UNKNOWN = 0
125    FILENAME = 1
126    TARGETNAME = 2
127    PACKAGEID = 3
128    DOCUMENT = 4
129
130# RelationshipData contains the pre-analysis data about a relationship between
131# Files and/or Packages/targets. It is eventually parsed into a corresponding
132# Relationship after we have organized the SPDX Package and File data.
133class RelationshipData:
134    def __init__(self):
135        super(RelationshipData, self).__init__()
136
137        # for the "owner" element (e.g., the left side of the Relationship),
138        # is it a filename or a target name (e.g., a Package in the build doc)
139        self.ownerType = RelationshipDataElementType.UNKNOWN
140
141        # owner file absolute path (if ownerType is FILENAME)
142        self.ownerFileAbspath = ""
143
144        # owner target name (if ownerType is TARGETNAME)
145        self.ownerTargetName = ""
146
147        # owner SPDX Document (if ownerType is DOCUMENT)
148        self.ownerDocument = None
149
150        # for the "other" element (e.g., the right side of the Relationship),
151        # is it a filename or a target name (e.g., a Package in the build doc)
152        self.otherType = RelationshipDataElementType.UNKNOWN
153
154        # other file absolute path (if otherType is FILENAME)
155        self.otherFileAbspath = ""
156
157        # other target name (if otherType is TARGETNAME)
158        self.otherTargetName = ""
159
160        # other package ID (if ownerType is DOCUMENT and otherType is PACKAGEID)
161        self.otherPackageID = ""
162
163        # text string with Relationship type
164        # from table in section 7.1 of SPDX spec v2.2
165        self.rlnType = ""
166
167# Relationship contains the post-analysis, processed data about a relationship
168# in a form suitable for creating the actual SPDX Relationship in a particular
169# Document's context.
170class Relationship:
171    def __init__(self):
172        super(Relationship, self).__init__()
173
174        # SPDX ID for left side of relationship
175        # including "SPDXRef-" as well as "DocumentRef-" if needed
176        self.refA = ""
177
178        # SPDX ID for right side of relationship
179        # including "SPDXRef-" as well as "DocumentRef-" if needed
180        self.refB = ""
181
182        # text string with Relationship type
183        # from table in section 7.1 of SPDX spec v2.2
184        self.rlnType = ""
185
186# File contains the data needed to create a File element in the context of a
187# particular SPDX Document and Package.
188class File:
189    # initialize with:
190    # 1) Document containing this File
191    # 2) Package containing this File
192    def __init__(self, doc, pkg):
193        super(File, self).__init__()
194
195        # absolute path to this file on disk
196        self.abspath = ""
197
198        # relative path for this file, measured from the owning Package's
199        # cfg.relativeBaseDir
200        self.relpath = ""
201
202        # SPDX ID for this file, including "SPDXRef-"
203        self.spdxID = ""
204
205        # SHA1 hash
206        self.sha1 = ""
207
208        # SHA256 hash, if pkg.cfg.doSHA256 == True; empty string otherwise
209        self.sha256 = ""
210
211        # MD5 hash, if pkg.cfg.doMD5 == True; empty string otherwise
212        self.md5 = ""
213
214        # concluded license, if pkg.cfg.shouldConcludeFileLicenses == True;
215        # "NOASSERTION" otherwise
216        self.concludedLicense = "NOASSERTION"
217
218        # license info in file
219        self.licenseInfoInFile = []
220
221        # copyright text
222        self.copyrightText = "NOASSERTION"
223
224        # Relationships "owned" by this File (e.g., this File is left side)
225        self.rlns = []
226
227        # Package that owns this File
228        self.pkg = pkg
229
230        # Document that owns this File
231        self.doc = doc
232