• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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