1// Package spdxlib contains convenience and utility functions for working 2// with an SPDX document that has already been created in memory. 3// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 4package spdxlib 5 6import ( 7 "fmt" 8 9 "github.com/spdx/tools-golang/spdx/common" 10 "github.com/spdx/tools-golang/spdx/v2_1" 11 "github.com/spdx/tools-golang/spdx/v2_2" 12 "github.com/spdx/tools-golang/spdx/v2_3" 13) 14 15// GetDescribedPackageIDs2_1 returns a slice of ElementIDs for all Packages 16// in this Document that it "describes," according to SPDX rules: 17// - If the document has only one Package, its ID is returned. 18// - If the document has 2+ Packages, it returns the IDs of those that have 19// a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT. 20func GetDescribedPackageIDs2_1(doc *v2_1.Document) ([]common.ElementID, error) { 21 // if nil Packages map or zero packages in it, return empty slice 22 if doc.Packages == nil { 23 return nil, fmt.Errorf("Packages map is nil") 24 } 25 if len(doc.Packages) == 0 { 26 return nil, fmt.Errorf("no Packages in Document") 27 } 28 if len(doc.Packages) == 1 { 29 // get first (only) one and return its ID 30 for _, pkg := range doc.Packages { 31 return []common.ElementID{pkg.PackageSPDXIdentifier}, nil 32 } 33 } 34 35 // two or more packages, so we need to go through the relationships, 36 // find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are 37 // valid IDs in this document's packages, and return them 38 if doc.Relationships == nil { 39 return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil") 40 } 41 42 eIDs, err := FilterRelationships2_1(doc, func(relationship *v2_1.Relationship) *common.ElementID { 43 refDocument := common.MakeDocElementID("", "DOCUMENT") 44 45 if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument { 46 return &relationship.RefB.ElementRefID 47 } else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument { 48 return &relationship.RefA.ElementRefID 49 } 50 51 return nil 52 }) 53 if err != nil { 54 return nil, err 55 } 56 57 if len(eIDs) == 0 { 58 return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document") 59 } 60 61 eIDs = SortElementIDs(eIDs) 62 63 return eIDs, nil 64} 65 66// GetDescribedPackageIDs2_2 returns a slice of ElementIDs for all Packages 67// in this Document that it "describes," according to SPDX rules: 68// - If the document has only one Package, its ID is returned. 69// - If the document has 2+ Packages, it returns the IDs of those that have 70// a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT. 71func GetDescribedPackageIDs2_2(doc *v2_2.Document) ([]common.ElementID, error) { 72 // if nil Packages map or zero packages in it, return empty slice 73 if doc.Packages == nil { 74 return nil, fmt.Errorf("Packages map is nil") 75 } 76 if len(doc.Packages) == 0 { 77 return nil, fmt.Errorf("no Packages in Document") 78 } 79 if len(doc.Packages) == 1 { 80 // get first (only) one and return its ID 81 for _, pkg := range doc.Packages { 82 return []common.ElementID{pkg.PackageSPDXIdentifier}, nil 83 } 84 } 85 86 // two or more packages, so we need to go through the relationships, 87 // find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are 88 // valid IDs in this document's packages, and return them 89 if doc.Relationships == nil { 90 return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil") 91 } 92 93 eIDs, err := FilterRelationships2_2(doc, func(relationship *v2_2.Relationship) *common.ElementID { 94 refDocument := common.MakeDocElementID("", "DOCUMENT") 95 96 if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument { 97 return &relationship.RefB.ElementRefID 98 } else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument { 99 return &relationship.RefA.ElementRefID 100 } 101 102 return nil 103 }) 104 if err != nil { 105 return nil, err 106 } 107 108 if len(eIDs) == 0 { 109 return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document") 110 } 111 112 eIDs = SortElementIDs(eIDs) 113 114 return eIDs, nil 115} 116 117// GetDescribedPackageIDs2_3 returns a slice of ElementIDs for all Packages 118// in this Document that it "describes," according to SPDX rules: 119// - If the document has only one Package, its ID is returned. 120// - If the document has 2+ Packages, it returns the IDs of those that have 121// a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT. 122func GetDescribedPackageIDs2_3(doc *v2_3.Document) ([]common.ElementID, error) { 123 // if nil Packages map or zero packages in it, return empty slice 124 if doc.Packages == nil { 125 return nil, fmt.Errorf("Packages map is nil") 126 } 127 if len(doc.Packages) == 0 { 128 return nil, fmt.Errorf("no Packages in Document") 129 } 130 if len(doc.Packages) == 1 { 131 // get first (only) one and return its ID 132 for _, pkg := range doc.Packages { 133 return []common.ElementID{pkg.PackageSPDXIdentifier}, nil 134 } 135 } 136 137 // two or more packages, so we need to go through the relationships, 138 // find DESCRIBES or DESCRIBED_BY for this DOCUMENT, verify they are 139 // valid IDs in this document's packages, and return them 140 if doc.Relationships == nil { 141 return nil, fmt.Errorf("multiple Packages in Document but Relationships slice is nil") 142 } 143 144 eIDs, err := FilterRelationships2_3(doc, func(relationship *v2_3.Relationship) *common.ElementID { 145 refDocument := common.MakeDocElementID("", "DOCUMENT") 146 147 if relationship.Relationship == "DESCRIBES" && relationship.RefA == refDocument { 148 return &relationship.RefB.ElementRefID 149 } else if relationship.Relationship == "DESCRIBED_BY" && relationship.RefB == refDocument { 150 return &relationship.RefA.ElementRefID 151 } 152 153 return nil 154 }) 155 if err != nil { 156 return nil, err 157 } 158 159 if len(eIDs) == 0 { 160 return nil, fmt.Errorf("no DESCRIBES or DESCRIBED_BY relationships found for this Document") 161 } 162 163 eIDs = SortElementIDs(eIDs) 164 165 return eIDs, nil 166} 167