xref: /aosp_15_r20/external/spdx-tools/tvloader/parser2v1/parser.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
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