aboutsummaryrefslogtreecommitdiff
path: root/spdxlib/described_elements.go
blob: a2a6356271451b306beb971e06abdf2f66dd2b1b (plain)
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Package spdxlib contains convenience and utility functions for working
// with an SPDX document that has already been created in memory.
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
package spdxlib

import (
	"fmt"

	"github.com/spdx/tools-golang/spdx/common"
	"github.com/spdx/tools-golang/spdx/v2_1"
	"github.com/spdx/tools-golang/spdx/v2_2"
	"github.com/spdx/tools-golang/spdx/v2_3"
)

// GetDescribedPackageIDs2_1 returns a slice of ElementIDs for all Packages
// in this Document that it "describes," according to SPDX rules:
// - If the document has only one Package, its ID is returned.
// - If the document has 2+ Packages, it returns the IDs of those that have
//   a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT.
func GetDescribedPackageIDs2_1(doc *v2_1.Document) ([]common.ElementID, error) {
	// if nil Packages map or zero packages in it, return empty slice
	if doc.Packages == nil {
		return nil, fmt.Errorf("Packages map is nil")
	}
	if len(doc.Packages) == 0 {
		return nil, fmt.Errorf("no Packages in Document")
	}
	if len(doc.Packages) == 1 {
		// get first (only) one and return its ID
		for _, pkg := range doc.Packages {
			return []common.ElementID{pkg.PackageSPDXIdentifier}, nil
		}
	}

	// two or more packages, so we need to go through the relationships,
	// find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are
	// valid IDs in this document's packages, and return them
	if doc.Relationships == nil {
		return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil")
	}

	eIDs, err := FilterRelationships2_1(doc, func(relationship *v2_1.Relationship) *common.ElementID {
		refDocument := common.MakeDocElementID("", "DOCUMENT")

		if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument {
			return &relationship.RefB.ElementRefID
		} else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument {
			return &relationship.RefA.ElementRefID
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	if len(eIDs) == 0 {
		return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document")
	}

	eIDs = SortElementIDs(eIDs)

	return eIDs, nil
}

// GetDescribedPackageIDs2_2 returns a slice of ElementIDs for all Packages
// in this Document that it "describes," according to SPDX rules:
// - If the document has only one Package, its ID is returned.
// - If the document has 2+ Packages, it returns the IDs of those that have
//   a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT.
func GetDescribedPackageIDs2_2(doc *v2_2.Document) ([]common.ElementID, error) {
	// if nil Packages map or zero packages in it, return empty slice
	if doc.Packages == nil {
		return nil, fmt.Errorf("Packages map is nil")
	}
	if len(doc.Packages) == 0 {
		return nil, fmt.Errorf("no Packages in Document")
	}
	if len(doc.Packages) == 1 {
		// get first (only) one and return its ID
		for _, pkg := range doc.Packages {
			return []common.ElementID{pkg.PackageSPDXIdentifier}, nil
		}
	}

	// two or more packages, so we need to go through the relationships,
	// find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are
	// valid IDs in this document's packages, and return them
	if doc.Relationships == nil {
		return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil")
	}

	eIDs, err := FilterRelationships2_2(doc, func(relationship *v2_2.Relationship) *common.ElementID {
		refDocument := common.MakeDocElementID("", "DOCUMENT")

		if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument {
			return &relationship.RefB.ElementRefID
		} else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument {
			return &relationship.RefA.ElementRefID
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	if len(eIDs) == 0 {
		return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document")
	}

	eIDs = SortElementIDs(eIDs)

	return eIDs, nil
}

// GetDescribedPackageIDs2_3 returns a slice of ElementIDs for all Packages
// in this Document that it "describes," according to SPDX rules:
// - If the document has only one Package, its ID is returned.
// - If the document has 2+ Packages, it returns the IDs of those that have
//   a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT.
func GetDescribedPackageIDs2_3(doc *v2_3.Document) ([]common.ElementID, error) {
	// if nil Packages map or zero packages in it, return empty slice
	if doc.Packages == nil {
		return nil, fmt.Errorf("Packages map is nil")
	}
	if len(doc.Packages) == 0 {
		return nil, fmt.Errorf("no Packages in Document")
	}
	if len(doc.Packages) == 1 {
		// get first (only) one and return its ID
		for _, pkg := range doc.Packages {
			return []common.ElementID{pkg.PackageSPDXIdentifier}, nil
		}
	}

	// two or more packages, so we need to go through the relationships,
	// find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are
	// valid IDs in this document's packages, and return them
	if doc.Relationships == nil {
		return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil")
	}

	eIDs, err := FilterRelationships2_3(doc, func(relationship *v2_3.Relationship) *common.ElementID {
		refDocument := common.MakeDocElementID("", "DOCUMENT")

		if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument {
			return &relationship.RefB.ElementRefID
		} else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument {
			return &relationship.RefA.ElementRefID
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	if len(eIDs) == 0 {
		return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document")
	}

	eIDs = SortElementIDs(eIDs)

	return eIDs, nil
}