Coverage Report

Created: 2026-07-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmSpdx.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmSpdx.h"
4
5
#include <stdexcept>
6
#include <string>
7
8
#include "cmSbomSerializer.h"
9
10
inline void SerializeIfPresent(cmSbomSerializer& s, std::string const& key,
11
                               cm::optional<std::string> const& v)
12
0
{
13
0
  if (v) {
14
0
    s.AddString(key, *v);
15
0
  }
16
0
}
17
18
std::string to_string(cmSpdxIntegrityMethod::HashAlgorithmId id)
19
0
{
20
0
  switch (id) {
21
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::ADLER32:
22
0
      return "ADLER32";
23
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B256:
24
0
      return "BLAKE2B256";
25
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B384:
26
0
      return "BLAKE2B384";
27
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE2B512:
28
0
      return "BLAKE2B512";
29
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::BLAKE3:
30
0
      return "BLAKE3";
31
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::MD2:
32
0
      return "MD2";
33
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::MD4:
34
0
      return "MD4";
35
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::MD5:
36
0
      return "MD5";
37
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::MD6:
38
0
      return "MD6";
39
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA1:
40
0
      return "SHA1";
41
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA224:
42
0
      return "SHA224";
43
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA256:
44
0
      return "SHA256";
45
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA384:
46
0
      return "SHA384";
47
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA512:
48
0
      return "SHA512";
49
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_256:
50
0
      return "SHA3_256";
51
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_384:
52
0
      return "SHA3_384";
53
0
    case cmSpdxIntegrityMethod::HashAlgorithmId::SHA3_512:
54
0
      return "SHA3_512";
55
0
  }
56
0
  throw std::invalid_argument("Unknown HashAlgorithmId");
57
0
}
58
59
std::string to_string(cmSpdxSoftwareArtifact::PurposeId id)
60
0
{
61
0
  switch (id) {
62
0
    case cmSpdxSoftwareArtifact::PurposeId::APPLICATION:
63
0
      return "application";
64
0
    case cmSpdxSoftwareArtifact::PurposeId::ARCHIVE:
65
0
      return "archive";
66
0
    case cmSpdxSoftwareArtifact::PurposeId::CONTAINER:
67
0
      return "container";
68
0
    case cmSpdxSoftwareArtifact::PurposeId::DATA:
69
0
      return "data";
70
0
    case cmSpdxSoftwareArtifact::PurposeId::DEVICE:
71
0
      return "device";
72
0
    case cmSpdxSoftwareArtifact::PurposeId::FIRMWARE:
73
0
      return "firmware";
74
0
    case cmSpdxSoftwareArtifact::PurposeId::FILE:
75
0
      return "file";
76
0
    case cmSpdxSoftwareArtifact::PurposeId::INSTALL:
77
0
      return "install";
78
0
    case cmSpdxSoftwareArtifact::PurposeId::LIBRARY:
79
0
      return "library";
80
0
    case cmSpdxSoftwareArtifact::PurposeId::MODULE:
81
0
      return "module";
82
0
    case cmSpdxSoftwareArtifact::PurposeId::OPERATING_SYSTEM:
83
0
      return "operatingSystem";
84
0
    case cmSpdxSoftwareArtifact::PurposeId::SOURCE:
85
0
      return "source";
86
0
  }
87
0
  throw std::invalid_argument("Unknown PurposeId");
88
0
}
89
90
std::string to_string(cmSpdxSbom::TypeId id)
91
0
{
92
0
  switch (id) {
93
0
    case cmSpdxSbom::TypeId::ANALYZED:
94
0
      return "analyzed";
95
0
    case cmSpdxSbom::TypeId::BUILD:
96
0
      return "build";
97
0
    case cmSpdxSbom::TypeId::DEPLOYED:
98
0
      return "deployed";
99
0
    case cmSpdxSbom::TypeId::DESIGN:
100
0
      return "design";
101
0
    case cmSpdxSbom::TypeId::RUNTIME:
102
0
      return "runtime";
103
0
    case cmSpdxSbom::TypeId::SOURCE:
104
0
      return "source";
105
0
    case cmSpdxSbom::TypeId::TEST:
106
0
      return "test";
107
0
  }
108
0
  throw std::invalid_argument("Unknown Sbom::TypeId");
109
0
}
110
111
std::string to_string(cmSpdxFile::FileKindId id)
112
0
{
113
0
  switch (id) {
114
0
    case cmSpdxFile::FileKindId::DIRECTORY:
115
0
      return "directory";
116
0
    case cmSpdxFile::FileKindId::FILE:
117
0
      return "file";
118
0
  }
119
0
  throw std::invalid_argument("Unknown File::FileKindId");
120
0
}
121
122
std::string to_string(cmSpdxRelationship::RelationshipTypeId id)
123
0
{
124
0
  switch (id) {
125
0
    case cmSpdxRelationship::RelationshipTypeId::DESCRIBES:
126
0
      return "describes";
127
0
    case cmSpdxRelationship::RelationshipTypeId::CONTAINS:
128
0
      return "contains";
129
0
    case cmSpdxRelationship::RelationshipTypeId::DEPENDS_ON:
130
0
      return "dependsOn";
131
0
    case cmSpdxRelationship::RelationshipTypeId::HAS_DECLARED_LICENSE:
132
0
      return "hasDeclaredLicense";
133
0
    case cmSpdxRelationship::RelationshipTypeId::OTHER:
134
0
      return "other";
135
0
  }
136
0
  throw std::invalid_argument("Unknown RelationshipTypeId");
137
0
}
138
139
std::string to_string(cmSpdxLifecycleScopedRelationship::ScopeId id)
140
0
{
141
0
  switch (id) {
142
0
    case cmSpdxLifecycleScopedRelationship::ScopeId::BUILD:
143
0
      return "build";
144
0
    case cmSpdxLifecycleScopedRelationship::ScopeId::DESIGN:
145
0
      return "design";
146
0
    case cmSpdxLifecycleScopedRelationship::ScopeId::RUNTIME:
147
0
      return "runtime";
148
0
    case cmSpdxLifecycleScopedRelationship::ScopeId::TEST:
149
0
      return "test";
150
0
  }
151
0
  throw std::invalid_argument("Unknown Lifecycle ScopeId");
152
0
}
153
154
std::string to_string(cmSpdxAnnotation::AnnotationTypeId id)
155
0
{
156
0
  switch (id) {
157
0
    case cmSpdxAnnotation::AnnotationTypeId::REVIEW:
158
0
      return "review";
159
0
    case cmSpdxAnnotation::AnnotationTypeId::OTHER:
160
0
      return "other";
161
0
  }
162
0
  throw std::invalid_argument("Unknown AnnotationTypeId");
163
0
}
164
165
std::string to_string(cmSpdxArtifact::SupportTypeId id)
166
0
{
167
0
  switch (id) {
168
0
    case cmSpdxArtifact::SupportTypeId::COMMUNITY:
169
0
      return "community";
170
0
    case cmSpdxArtifact::SupportTypeId::COMMERCIAL:
171
0
      return "commercial";
172
0
    case cmSpdxArtifact::SupportTypeId::NONE:
173
0
      return "none";
174
0
  }
175
0
  throw std::invalid_argument("Unknown SupportTypeId");
176
0
}
177
178
void cmSpdxExternalIdentifier::Serialize(cmSbomSerializer& serializer) const
179
0
{
180
0
  serializer.AddString("type", "ExternalIdentifier");
181
0
  SerializeIfPresent(serializer, "externalIdentifierType",
182
0
                     ExternalIdentifierType);
183
0
  SerializeIfPresent(serializer, "identifier", Identifier);
184
0
  SerializeIfPresent(serializer, "comment", Comment);
185
0
  SerializeIfPresent(serializer, "identifierLocation", IdentifierLocation);
186
0
  SerializeIfPresent(serializer, "issuingAuthority", IssuingAuthority);
187
0
}
188
189
void cmSpdxExternalRef::Serialize(cmSbomSerializer& serializer) const
190
0
{
191
0
  serializer.AddString("type", "ExternalRef");
192
0
  SerializeIfPresent(serializer, "externalRefType", ExternalRefType);
193
0
  SerializeIfPresent(serializer, "locator", Locator);
194
0
  SerializeIfPresent(serializer, "contentType", ContentType);
195
0
  SerializeIfPresent(serializer, "comment", Comment);
196
0
}
197
198
void cmSpdxChecksum::Serialize(cmSbomSerializer& serializer) const
199
0
{
200
0
  serializer.AddString("type", "Checksum");
201
0
  serializer.AddString("algorithm", to_string(Algorithm));
202
0
  serializer.AddString("checksumValue", ChecksumValue);
203
0
}
204
205
void cmSpdxCreationInfo::Serialize(cmSbomSerializer& serializer) const
206
0
{
207
0
  serializer.AddString("type", "CreationInfo");
208
0
  SerializeIfPresent(serializer, "@id", SpdxId);
209
0
  if (SpecVersion) {
210
0
    serializer.AddString("specVersion", *SpecVersion);
211
0
  }
212
0
  SerializeIfPresent(serializer, "comment", Comment);
213
0
  SerializeIfPresent(serializer, "created", Created);
214
0
  if (!CreatedBy.empty()) {
215
0
    serializer.AddVectorIfPresent("createdBy", CreatedBy);
216
0
  }
217
0
  if (!CreatedUsing.empty()) {
218
0
    serializer.AddVectorIfPresent("createdUsing", CreatedUsing);
219
0
  }
220
0
}
221
222
void cmSpdxIntegrityMethod::Serialize(cmSbomSerializer& serializer) const
223
0
{
224
0
  serializer.AddString("type", "IntegrityMethod");
225
0
  SerializeIfPresent(serializer, "comment", Comment);
226
0
}
227
228
void cmSpdxElement::Serialize(cmSbomSerializer& serializer) const
229
0
{
230
0
  serializer.AddString("type", "Element");
231
0
  SerializeIfPresent(serializer, "spdxId", SpdxId);
232
0
  SerializeIfPresent(serializer, "name", Name);
233
0
  SerializeIfPresent(serializer, "summary", Summary);
234
0
  SerializeIfPresent(serializer, "description", Description);
235
0
  SerializeIfPresent(serializer, "comment", Comment);
236
0
  if (CreationInfo) {
237
0
    serializer.AddVisitable("creationInfo", *CreationInfo);
238
0
  }
239
0
  if (VerifiedUsing) {
240
0
    serializer.AddVisitable("verifiedUsing", *VerifiedUsing);
241
0
  }
242
0
  if (!ExternalRef.empty()) {
243
0
    serializer.AddVectorIfPresent("externalRef", ExternalRef);
244
0
  }
245
0
  if (!ExternalIdentifier.empty()) {
246
0
    serializer.AddVectorIfPresent("externalIdentifier", ExternalIdentifier);
247
0
  }
248
0
  if (Extension) {
249
0
    serializer.AddVisitable("extension", *Extension);
250
0
  }
251
0
}
252
253
void cmSpdxTool::Serialize(cmSbomSerializer& serializer) const
254
0
{
255
0
  cmSpdxElement::Serialize(serializer);
256
0
  serializer.AddString("type", "Tool");
257
0
}
258
259
void cmSpdxAgent::Serialize(cmSbomSerializer& serializer) const
260
0
{
261
0
  cmSpdxElement::Serialize(serializer);
262
0
  serializer.AddString("type", "Agent");
263
0
}
264
265
void cmSpdxOrganization::Serialize(cmSbomSerializer& serializer) const
266
0
{
267
0
  cmSpdxAgent::Serialize(serializer);
268
0
  serializer.AddString("type", "Organization");
269
0
}
270
271
void cmSpdxPerson::Serialize(cmSbomSerializer& serializer) const
272
0
{
273
0
  cmSpdxAgent::Serialize(serializer);
274
0
  serializer.AddString("type", "Person");
275
0
}
276
277
void cmSpdxSoftwareAgent::Serialize(cmSbomSerializer& serializer) const
278
0
{
279
0
  cmSpdxAgent::Serialize(serializer);
280
0
  serializer.AddString("type", "SoftwareAgent");
281
0
}
282
283
void cmSpdxPositiveIntegerRange::Serialize(cmSbomSerializer& serializer) const
284
0
{
285
0
  serializer.AddString("type", "PositiveIntegerRange");
286
0
  SerializeIfPresent(serializer, "beginIntegerRange", BeginIntegerRange);
287
0
  SerializeIfPresent(serializer, "endIntegerRange", EndIntegerRange);
288
0
}
289
290
void cmSpdxRelationship::Serialize(cmSbomSerializer& serializer) const
291
0
{
292
0
  cmSpdxElement::Serialize(serializer);
293
0
  serializer.AddString("type", "Relationship");
294
0
  if (From) {
295
0
    serializer.AddVisitable("from", *From);
296
0
  }
297
0
  if (!To.empty()) {
298
0
    serializer.AddVectorIfPresent("to", To);
299
0
  }
300
0
  if (RelationshipType) {
301
0
    serializer.AddString("relationshipType", to_string(*RelationshipType));
302
0
  }
303
0
  SerializeIfPresent(serializer, "startTime", StartTime);
304
0
  SerializeIfPresent(serializer, "endTime", EndTime);
305
0
}
306
307
void cmSpdxLifecycleScopedRelationship::Serialize(
308
  cmSbomSerializer& serializer) const
309
0
{
310
0
  cmSpdxRelationship::Serialize(serializer);
311
0
  serializer.AddString("type", "LifecycleScopedRelationship");
312
0
  if (Scope) {
313
0
    serializer.AddString("scope", to_string(*Scope));
314
0
  }
315
0
}
316
317
void cmSpdxArtifact::Serialize(cmSbomSerializer& serializer) const
318
0
{
319
0
  cmSpdxElement::Serialize(serializer);
320
0
  serializer.AddString("type", "Artifact");
321
0
  if (!OriginatedBy.empty()) {
322
0
    serializer.AddVectorIfPresent("originatedBy", OriginatedBy);
323
0
  }
324
0
  if (SuppliedBy) {
325
0
    serializer.AddVisitable("suppliedBy", *SuppliedBy);
326
0
  }
327
0
  SerializeIfPresent(serializer, "builtTime", BuiltTime);
328
0
  SerializeIfPresent(serializer, "releaseTime", ReleaseTime);
329
0
  SerializeIfPresent(serializer, "validUntilTime", ValidUntilTime);
330
0
  SerializeIfPresent(serializer, "standardName", StandardName);
331
0
  if (Support) {
332
0
    serializer.AddString("support", to_string(*Support));
333
0
  }
334
0
}
335
336
void cmSpdxIndividualElement::Serialize(cmSbomSerializer& serializer) const
337
0
{
338
0
  cmSpdxElement::Serialize(serializer);
339
0
  serializer.AddString("type", "IndividualElement");
340
0
}
341
342
void cmSpdxAnnotation::Serialize(cmSbomSerializer& serializer) const
343
0
{
344
0
  cmSpdxElement::Serialize(serializer);
345
0
  serializer.AddString("type", "Annotation");
346
0
  if (AnnotationType) {
347
0
    serializer.AddString("annotationType", to_string(*AnnotationType));
348
0
  }
349
0
  SerializeIfPresent(serializer, "contentType", ContentType);
350
0
  SerializeIfPresent(serializer, "statement", Statement);
351
0
  if (Element) {
352
0
    serializer.AddVisitable("element", *Element);
353
0
  }
354
0
}
355
356
void cmSpdxExternalMap::Serialize(cmSbomSerializer& serializer) const
357
0
{
358
0
  serializer.AddString("type", "ExternalMap");
359
0
  SerializeIfPresent(serializer, "externalSpdxId", ExternalSpdxId);
360
0
  if (VerifiedUsing) {
361
0
    serializer.AddVisitable("verifiedUsing", *VerifiedUsing);
362
0
  }
363
0
  SerializeIfPresent(serializer, "locationHistory", LocationHistory);
364
0
  if (DefiningArtifact) {
365
0
    serializer.AddVisitable("definingArtifact", *DefiningArtifact);
366
0
  }
367
0
}
368
369
void cmSpdxNamespaceMap::Serialize(cmSbomSerializer& serializer) const
370
0
{
371
0
  serializer.AddString("type", "NamespaceMap");
372
0
  SerializeIfPresent(serializer, "prefix", Prefix);
373
0
  SerializeIfPresent(serializer, "namespace", Namespace);
374
0
}
375
376
void cmSpdxElementCollection::Serialize(cmSbomSerializer& serializer) const
377
0
{
378
0
  cmSpdxElement::Serialize(serializer);
379
0
  serializer.AddString("type", "ElementCollection");
380
0
  if (!Elements.empty()) {
381
0
    serializer.AddVectorIfPresent("element", Elements);
382
0
  }
383
0
  if (!RootElements.empty()) {
384
0
    serializer.AddVectorIfPresent("rootElement", RootElements);
385
0
  }
386
0
  if (!ProfileConformance.empty()) {
387
0
    serializer.AddVectorIfPresent("profileConformance", ProfileConformance);
388
0
  }
389
0
}
390
391
void cmSpdxPackageVerificationCode::Serialize(
392
  cmSbomSerializer& serializer) const
393
0
{
394
0
  serializer.AddString("type", "PackageVerificationCode");
395
0
  if (Algorithm) {
396
0
    serializer.AddString("algorithm", to_string(*Algorithm));
397
0
  }
398
0
  SerializeIfPresent(serializer, "hashValue", HashValue);
399
0
  SerializeIfPresent(serializer, "packageVerificationCodeExcludedFile",
400
0
                     PackageVerificationCodeExcludedFile);
401
0
}
402
403
void cmSpdxHash::Serialize(cmSbomSerializer& serializer) const
404
0
{
405
0
  serializer.AddString("type", "Hash");
406
0
  serializer.AddString("hashAlgorithm", to_string(HashAlgorithm));
407
0
  serializer.AddString("hashValue", HashValue);
408
0
}
409
410
void cmSpdxBundle::Serialize(cmSbomSerializer& serializer) const
411
0
{
412
0
  cmSpdxElementCollection::Serialize(serializer);
413
0
  serializer.AddString("type", "Bundle");
414
0
  SerializeIfPresent(serializer, "context", Context);
415
0
}
416
417
void cmSpdxBom::Serialize(cmSbomSerializer& serializer) const
418
0
{
419
0
  cmSpdxBundle::Serialize(serializer);
420
0
  serializer.AddString("type", "Bom");
421
0
}
422
423
void cmSpdxSbom::Serialize(cmSbomSerializer& serializer) const
424
0
{
425
0
  cmSpdxBom::Serialize(serializer);
426
0
  serializer.AddString("type", "software_Sbom");
427
0
  if (Types) {
428
0
    for (auto const& t : *Types) {
429
0
      serializer.AddString("sbomType", to_string(t));
430
0
    }
431
0
  }
432
0
  if (LifecycleScope) {
433
0
    serializer.AddString("lifecycleScope", to_string(*LifecycleScope));
434
0
  }
435
0
}
436
437
void cmSpdxSoftwareArtifact::Serialize(cmSbomSerializer& serializer) const
438
0
{
439
0
  cmSpdxArtifact::Serialize(serializer);
440
0
  serializer.AddString("type", "software_SoftwareArtifact");
441
0
  if (PrimaryPurpose) {
442
0
    serializer.AddString("software_primaryPurpose",
443
0
                         to_string(*PrimaryPurpose));
444
0
  }
445
0
  if (AdditionalPurpose) {
446
0
    for (auto const& p : *AdditionalPurpose) {
447
0
      serializer.AddString("software_AdditionalPurpose", to_string(p));
448
0
    }
449
0
  }
450
0
  SerializeIfPresent(serializer, "software_copyrightText", CopyrightText);
451
0
  SerializeIfPresent(serializer, "software_attributionText", AttributionText);
452
0
  if (ContentIdentifier) {
453
0
    serializer.AddVisitable("software_contentIdentifier", *ContentIdentifier);
454
0
  }
455
0
  SerializeIfPresent(serializer, "software_artifactSize", ArtifactSize);
456
0
}
457
458
void cmSpdxPackage::Serialize(cmSbomSerializer& serializer) const
459
0
{
460
0
  cmSpdxSoftwareArtifact::Serialize(serializer);
461
0
  serializer.AddString("type", "software_Package");
462
0
  SerializeIfPresent(serializer, "software_downloadLocation",
463
0
                     DownloadLocation);
464
0
  SerializeIfPresent(serializer, "software_homePage", Homepage);
465
0
  SerializeIfPresent(serializer, "software_packageVersion", PackageVersion);
466
0
  SerializeIfPresent(serializer, "software_packageUrl", PackageUrl);
467
0
  SerializeIfPresent(serializer, "software_sourceInfo", SourceInfo);
468
0
}
469
470
void cmSpdxFile::Serialize(cmSbomSerializer& serializer) const
471
0
{
472
0
  cmSpdxArtifact::Serialize(serializer);
473
0
  serializer.AddString("type", "software_File");
474
0
  if (ContentType) {
475
0
    serializer.AddString("software_contentType", *ContentType);
476
0
  }
477
0
  if (FileType) {
478
0
    serializer.AddString("software_fileType", to_string(*FileType));
479
0
  }
480
0
}
481
482
void cmSpdxContentIdentifier::Serialize(cmSbomSerializer& serializer) const
483
0
{
484
0
  cmSpdxIntegrityMethod::Serialize(serializer);
485
0
  serializer.AddString("type", "software_contentIdentifier");
486
0
  SerializeIfPresent(serializer, "software_contentIdentifierType",
487
0
                     ContentIdentifierType);
488
0
  SerializeIfPresent(serializer, "software_contentValue", ContentValue);
489
0
}
490
491
void cmSpdxSnippet::Serialize(cmSbomSerializer& serializer) const
492
0
{
493
0
  cmSpdxSoftwareArtifact::Serialize(serializer);
494
0
  serializer.AddString("type", "software_snippet");
495
0
  SerializeIfPresent(serializer, "software_byteRange", ByteRange);
496
0
  SerializeIfPresent(serializer, "software_lineRange", LineRange);
497
0
  if (SnippetFromFile) {
498
0
    serializer.AddVisitable("software_snippetFromFile", *SnippetFromFile);
499
0
  }
500
0
}
501
502
void cmSpdxAnyLicenseInfo::Serialize(cmSbomSerializer& serializer) const
503
0
{
504
0
  cmSpdxElement::Serialize(serializer);
505
0
  serializer.AddString("type", "simplelicensing_AnyLicenseInfo");
506
0
}
507
508
void cmSpdxLicenseExpression::Serialize(cmSbomSerializer& serializer) const
509
0
{
510
0
  cmSpdxAnyLicenseInfo::Serialize(serializer);
511
0
  serializer.AddString("type", "simplelicensing_LicenseExpression");
512
0
  SerializeIfPresent(serializer, "simplelicensing_licenseExpression",
513
0
                     LicenseExpression);
514
0
}
515
516
void cmSpdxDocument::Serialize(cmSbomSerializer& serializer) const
517
0
{
518
0
  cmSpdxElementCollection::Serialize(serializer);
519
520
0
  serializer.AddString("type", "SpdxDocument");
521
0
  if (ExternalMap) {
522
0
    serializer.AddVisitable("externalMap", *ExternalMap);
523
0
  }
524
0
  if (NamespaceMap) {
525
0
    serializer.AddVisitable("namespaceMap", *NamespaceMap);
526
0
  }
527
0
  if (DataLicense) {
528
0
    serializer.AddVisitable("dataLicense", *DataLicense);
529
0
  }
530
0
}
531
532
void cmSbomDocument::Serialize(cmSbomSerializer& serializer) const
533
0
{
534
0
  serializer.AddString(
535
0
    "@context",
536
0
    Context.value_or("https://spdx.org/rdf/3.0.1/spdx-context.jsonld"));
537
0
  if (!Graph.empty()) {
538
0
    serializer.AddVectorIfPresent("@graph", Graph);
539
0
  }
540
0
}