1*ba677afaSXin Li// Package parser2v1 contains functions to read, load and parse 2*ba677afaSXin Li// SPDX tag-value files. 3*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 4*ba677afaSXin Lipackage parser2v1 5*ba677afaSXin Li 6*ba677afaSXin Liimport ( 7*ba677afaSXin Li "fmt" 8*ba677afaSXin Li 9*ba677afaSXin Li "github.com/spdx/tools-golang/spdx/common" 10*ba677afaSXin Li "github.com/spdx/tools-golang/spdx/v2_1" 11*ba677afaSXin Li "github.com/spdx/tools-golang/tvloader/reader" 12*ba677afaSXin Li) 13*ba677afaSXin Li 14*ba677afaSXin Li// ParseTagValues takes a list of (tag, value) pairs, parses it and returns 15*ba677afaSXin Li// a pointer to a parsed SPDX Document. 16*ba677afaSXin Lifunc ParseTagValues(tvs []reader.TagValuePair) (*v2_1.Document, error) { 17*ba677afaSXin Li parser := tvParser2_1{} 18*ba677afaSXin Li for _, tv := range tvs { 19*ba677afaSXin Li err := parser.parsePair2_1(tv.Tag, tv.Value) 20*ba677afaSXin Li if err != nil { 21*ba677afaSXin Li return nil, err 22*ba677afaSXin Li } 23*ba677afaSXin Li } 24*ba677afaSXin Li if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_1 { 25*ba677afaSXin Li return nil, fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName) 26*ba677afaSXin Li } 27*ba677afaSXin Li if parser.pkg != nil && parser.pkg.PackageSPDXIdentifier == nullSpdxElementId2_1 { 28*ba677afaSXin Li return nil, fmt.Errorf("package with PackageName %s does not have SPDX identifier", parser.pkg.PackageName) 29*ba677afaSXin Li } 30*ba677afaSXin Li 31*ba677afaSXin Li return parser.doc, nil 32*ba677afaSXin Li} 33*ba677afaSXin Li 34*ba677afaSXin Lifunc (parser *tvParser2_1) parsePair2_1(tag string, value string) error { 35*ba677afaSXin Li switch parser.st { 36*ba677afaSXin Li case psStart2_1: 37*ba677afaSXin Li return parser.parsePairFromStart2_1(tag, value) 38*ba677afaSXin Li case psCreationInfo2_1: 39*ba677afaSXin Li return parser.parsePairFromCreationInfo2_1(tag, value) 40*ba677afaSXin Li case psPackage2_1: 41*ba677afaSXin Li return parser.parsePairFromPackage2_1(tag, value) 42*ba677afaSXin Li case psFile2_1: 43*ba677afaSXin Li return parser.parsePairFromFile2_1(tag, value) 44*ba677afaSXin Li case psSnippet2_1: 45*ba677afaSXin Li return parser.parsePairFromSnippet2_1(tag, value) 46*ba677afaSXin Li case psOtherLicense2_1: 47*ba677afaSXin Li return parser.parsePairFromOtherLicense2_1(tag, value) 48*ba677afaSXin Li case psReview2_1: 49*ba677afaSXin Li return parser.parsePairFromReview2_1(tag, value) 50*ba677afaSXin Li default: 51*ba677afaSXin Li return fmt.Errorf("parser state %v not recognized when parsing (%s, %s)", parser.st, tag, value) 52*ba677afaSXin Li } 53*ba677afaSXin Li} 54*ba677afaSXin Li 55*ba677afaSXin Lifunc (parser *tvParser2_1) parsePairFromStart2_1(tag string, value string) error { 56*ba677afaSXin Li // fail if not in Start parser state 57*ba677afaSXin Li if parser.st != psStart2_1 { 58*ba677afaSXin Li return fmt.Errorf("got invalid state %v in parsePairFromStart2_1", parser.st) 59*ba677afaSXin Li } 60*ba677afaSXin Li 61*ba677afaSXin Li // create an SPDX Document data struct if we don't have one already 62*ba677afaSXin Li if parser.doc == nil { 63*ba677afaSXin Li parser.doc = &v2_1.Document{ 64*ba677afaSXin Li ExternalDocumentReferences: []v2_1.ExternalDocumentRef{}, 65*ba677afaSXin Li } 66*ba677afaSXin Li } 67*ba677afaSXin Li 68*ba677afaSXin Li switch tag { 69*ba677afaSXin Li case "SPDXVersion": 70*ba677afaSXin Li parser.doc.SPDXVersion = value 71*ba677afaSXin Li case "DataLicense": 72*ba677afaSXin Li parser.doc.DataLicense = value 73*ba677afaSXin Li case "SPDXID": 74*ba677afaSXin Li eID, err := extractElementID(value) 75*ba677afaSXin Li if err != nil { 76*ba677afaSXin Li return err 77*ba677afaSXin Li } 78*ba677afaSXin Li parser.doc.SPDXIdentifier = eID 79*ba677afaSXin Li case "DocumentName": 80*ba677afaSXin Li parser.doc.DocumentName = value 81*ba677afaSXin Li case "DocumentNamespace": 82*ba677afaSXin Li parser.doc.DocumentNamespace = value 83*ba677afaSXin Li case "ExternalDocumentRef": 84*ba677afaSXin Li documentRefID, uri, alg, checksum, err := extractExternalDocumentReference(value) 85*ba677afaSXin Li if err != nil { 86*ba677afaSXin Li return err 87*ba677afaSXin Li } 88*ba677afaSXin Li edr := v2_1.ExternalDocumentRef{ 89*ba677afaSXin Li DocumentRefID: documentRefID, 90*ba677afaSXin Li URI: uri, 91*ba677afaSXin Li Checksum: common.Checksum{Algorithm: common.ChecksumAlgorithm(alg), Value: checksum}, 92*ba677afaSXin Li } 93*ba677afaSXin Li parser.doc.ExternalDocumentReferences = append(parser.doc.ExternalDocumentReferences, edr) 94*ba677afaSXin Li case "DocumentComment": 95*ba677afaSXin Li parser.doc.DocumentComment = value 96*ba677afaSXin Li default: 97*ba677afaSXin Li // move to Creation Info parser state 98*ba677afaSXin Li parser.st = psCreationInfo2_1 99*ba677afaSXin Li return parser.parsePairFromCreationInfo2_1(tag, value) 100*ba677afaSXin Li } 101*ba677afaSXin Li 102*ba677afaSXin Li return nil 103*ba677afaSXin Li} 104