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