-
Notifications
You must be signed in to change notification settings - Fork 53
/
document.go
150 lines (120 loc) · 4.16 KB
/
document.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Package spdx contains the struct definition for an SPDX Document
// and its constituent parts.
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
package v2_2
import (
"encoding/json"
"fmt"
converter "github.com/anchore/go-struct-converter"
"github.com/spdx/tools-golang/spdx/v2/common"
)
const Version = "SPDX-2.2"
const DataLicense = "CC0-1.0"
// ExternalDocumentRef is a reference to an external SPDX document
// as defined in section 6.6 for version 2.2 of the spec.
type ExternalDocumentRef struct {
// DocumentRefID is the ID string defined in the start of the
// reference. It should _not_ contain the "DocumentRef-" part
// of the mandatory ID string.
DocumentRefID string `json:"externalDocumentId"`
// URI is the URI defined for the external document
URI string `json:"spdxDocument"`
// Checksum is the actual hash data
Checksum common.Checksum `json:"checksum"`
}
// Document is an SPDX Document for version 2.2 of the spec.
// See https://spdx.github.io/spdx-spec/v2-draft/ (DRAFT)
type Document struct {
// 6.1: SPDX Version; should be in the format "SPDX-2.2"
// Cardinality: mandatory, one
SPDXVersion string `json:"spdxVersion"`
// 6.2: Data License; should be "CC0-1.0"
// Cardinality: mandatory, one
DataLicense string `json:"dataLicense"`
// 6.3: SPDX Identifier; should be "DOCUMENT" to represent
// mandatory identifier of SPDXRef-DOCUMENT
// Cardinality: mandatory, one
SPDXIdentifier common.ElementID `json:"SPDXID"`
// 6.4: Document Name
// Cardinality: mandatory, one
DocumentName string `json:"name"`
// 6.5: Document Namespace
// Cardinality: mandatory, one
DocumentNamespace string `json:"documentNamespace"`
// 6.6: External Document References
// Cardinality: optional, one or many
ExternalDocumentReferences []ExternalDocumentRef `json:"externalDocumentRefs,omitempty"`
// 6.11: Document Comment
// Cardinality: optional, one
DocumentComment string `json:"comment,omitempty"`
CreationInfo *CreationInfo `json:"creationInfo"`
Packages []*Package `json:"packages,omitempty"`
Files []*File `json:"files,omitempty"`
OtherLicenses []*OtherLicense `json:"hasExtractedLicensingInfos,omitempty"`
Relationships []*Relationship `json:"relationships,omitempty"`
Annotations []*Annotation `json:"annotations,omitempty"`
Snippets []Snippet `json:"snippets,omitempty"`
// DEPRECATED in version 2.0 of spec
Reviews []*Review `json:"-"`
}
func (d *Document) ConvertFrom(_ interface{}) error {
d.SPDXVersion = Version
return nil
}
var _ converter.ConvertFrom = (*Document)(nil)
func (d *Document) UnmarshalJSON(b []byte) error {
type doc Document
type extras struct {
DocumentDescribes []common.DocElementID `json:"documentDescribes"`
}
var d2 doc
if err := json.Unmarshal(b, &d2); err != nil {
return err
}
var e extras
if err := json.Unmarshal(b, &e); err != nil {
return err
}
*d = Document(d2)
relationshipExists := map[string]bool{}
serializeRel := func(r *Relationship) string {
return fmt.Sprintf("%v-%v->%v", common.RenderDocElementID(r.RefA), r.Relationship, common.RenderDocElementID(r.RefB))
}
// index current list of relationships to ensure no duplication
for _, r := range d.Relationships {
relationshipExists[serializeRel(r)] = true
}
// build relationships for documentDescribes field
for _, id := range e.DocumentDescribes {
r := &Relationship{
RefA: common.DocElementID{
ElementRefID: d.SPDXIdentifier,
},
RefB: id,
Relationship: common.TypeRelationshipDescribe,
}
if !relationshipExists[serializeRel(r)] {
d.Relationships = append(d.Relationships, r)
relationshipExists[serializeRel(r)] = true
}
}
// build relationships for package hasFiles field
for _, p := range d.Packages {
for _, f := range p.hasFiles {
r := &Relationship{
RefA: common.DocElementID{
ElementRefID: p.PackageSPDXIdentifier,
},
RefB: f,
Relationship: common.TypeRelationshipContains,
}
if !relationshipExists[serializeRel(r)] {
d.Relationships = append(d.Relationships, r)
relationshipExists[serializeRel(r)] = true
}
}
p.hasFiles = nil
}
return nil
}
var _ json.Unmarshaler = (*Document)(nil)