xref: /aosp_15_r20/external/spdx-tools/rdfloader/parser2v2/parse_license.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3package parser2v2
4
5import (
6	"errors"
7	"fmt"
8	"strings"
9
10	gordfParser "github.com/spdx/gordf/rdfloader/parser"
11	"github.com/spdx/gordf/rdfwriter"
12)
13
14// AnyLicense is a baseClass for all the licenses
15// All the types of licenses is a sub-type of AnyLicense,
16// either directly or indirectly.
17// This function acts as a mux for all the licenses. Based on the input, it
18// decides which type of license it is and passes control to that type of
19// license parser to parse the given input.
20func (parser *rdfParser2_2) getAnyLicenseFromNode(node *gordfParser.Node) (AnyLicenseInfo, error) {
21
22	currState := parser.cache[node.ID]
23	if currState == nil {
24		// there is no entry about the state of current package node.
25		// this is the first time we're seeing this node.
26		parser.cache[node.ID] = &nodeState{
27			object: nil, // not storing the object as we won't retrieve it later.
28			Color:  WHITE,
29		}
30	} else if currState.Color == GREY {
31		// we have already started parsing this license node.
32		// We have a cyclic dependency!
33		return nil, errors.New("Couldn't parse license: found a cyclic dependency on " + node.ID)
34	}
35
36	// setting color of the state to grey to indicate that we've started to
37	// parse this node once.
38	parser.cache[node.ID].Color = GREY
39
40	// setting state color to black when we're done parsing this node.
41	defer func() { parser.cache[node.ID].Color = BLACK }()
42
43	associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
44	if len(associatedTriples) == 0 {
45		// just a license uri string was found.
46		return parser.getSpecialLicenseFromNode(node)
47	}
48
49	// we have some attributes associated with the license node.
50	nodeType, err := getNodeTypeFromTriples(associatedTriples, node)
51	if err != nil {
52		return nil, fmt.Errorf("error parsing license triple: %v", err)
53	}
54	switch nodeType {
55	case SPDX_DISJUNCTIVE_LICENSE_SET:
56		return parser.getDisjunctiveLicenseSetFromNode(node)
57	case SPDX_CONJUNCTIVE_LICENSE_SET:
58		return parser.getConjunctiveLicenseSetFromNode(node)
59	case SPDX_EXTRACTED_LICENSING_INFO:
60		return parser.getExtractedLicensingInfoFromNode(node)
61	case SPDX_LISTED_LICENSE, SPDX_LICENSE:
62		return parser.getLicenseFromNode(node)
63	case SPDX_WITH_EXCEPTION_OPERATOR:
64		return parser.getWithExceptionOperatorFromNode(node)
65	case SPDX_OR_LATER_OPERATOR:
66		return parser.getOrLaterOperatorFromNode(node)
67	case SPDX_SIMPLE_LICENSING_INFO:
68		return parser.getSimpleLicensingInfoFromNode(node)
69	}
70	return nil, fmt.Errorf("Unknown subTag (%s) found while parsing AnyLicense", nodeType)
71}
72
73func (parser *rdfParser2_2) getLicenseExceptionFromNode(node *gordfParser.Node) (exception LicenseException, err error) {
74	associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
75	for _, triple := range associatedTriples {
76		value := triple.Object.ID
77		switch triple.Predicate.ID {
78		case RDF_TYPE:
79			continue
80		case SPDX_LICENSE_EXCEPTION_ID:
81			exception.licenseExceptionId = value
82		case SPDX_LICENSE_EXCEPTION_TEXT:
83			exception.licenseExceptionText = value
84		case RDFS_SEE_ALSO:
85			if !isUriValid(value) {
86				return exception, fmt.Errorf("invalid uri (%s) for seeAlso attribute of LicenseException", value)
87			}
88			exception.seeAlso = value
89		case SPDX_NAME:
90			exception.name = value
91		case SPDX_EXAMPLE:
92			exception.example = value
93		case RDFS_COMMENT:
94			exception.comment = value
95		default:
96			return exception, fmt.Errorf("invalid predicate(%s) for LicenseException", triple.Predicate)
97		}
98	}
99	return exception, nil
100}
101
102func (parser *rdfParser2_2) getSimpleLicensingInfoFromNode(node *gordfParser.Node) (SimpleLicensingInfo, error) {
103	simpleLicensingTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
104	return parser.getSimpleLicensingInfoFromTriples(simpleLicensingTriples)
105}
106
107func (parser *rdfParser2_2) getWithExceptionOperatorFromNode(node *gordfParser.Node) (operator WithExceptionOperator, err error) {
108	associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
109	var memberFound bool
110	for _, triple := range associatedTriples {
111		switch triple.Predicate.ID {
112		case RDF_TYPE:
113			continue
114		case SPDX_MEMBER:
115			if memberFound {
116				return operator,
117					fmt.Errorf("more than one member found in the WithExceptionOperator (expected only 1)")
118			}
119			memberFound = true
120			member, err := parser.getSimpleLicensingInfoFromNode(triple.Object)
121			if err != nil {
122				return operator, fmt.Errorf("error parsing member of a WithExceptionOperator: %v", err)
123			}
124			operator.member = member
125		case SPDX_LICENSE_EXCEPTION:
126			operator.licenseException, err = parser.getLicenseExceptionFromNode(triple.Object)
127			if err != nil {
128				return operator, fmt.Errorf("error parsing licenseException of WithExceptionOperator: %v", err)
129			}
130		default:
131			return operator, fmt.Errorf("unknown predicate (%s) for a WithExceptionOperator", triple.Predicate.ID)
132		}
133	}
134	return operator, nil
135}
136
137func (parser *rdfParser2_2) getOrLaterOperatorFromNode(node *gordfParser.Node) (operator OrLaterOperator, err error) {
138	associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
139	n := len(associatedTriples)
140	if n != 2 {
141		return operator, fmt.Errorf("orLaterOperator must be associated with exactly one tag. found %v triples", n-1)
142	}
143	for _, triple := range associatedTriples {
144		switch triple.Predicate.ID {
145		case RDF_TYPE:
146			continue
147		case SPDX_MEMBER:
148			operator.member, err = parser.getSimpleLicensingInfoFromNode(triple.Object)
149			if err != nil {
150				return operator, fmt.Errorf("error parsing simpleLicensingInfo of OrLaterOperator: %v", err)
151			}
152		default:
153			return operator, fmt.Errorf("unknown predicate %s", triple.Predicate.ID)
154		}
155	}
156	return operator, nil
157}
158
159// SpecialLicense is a type of license which is not defined in any of the
160// spdx documents, it is a type of license defined for the sake of brevity.
161// It can be [NONE|NOASSERTION|LicenseRef-<string>]
162func (parser *rdfParser2_2) getSpecialLicenseFromNode(node *gordfParser.Node) (lic SpecialLicense, err error) {
163	uri := strings.TrimSpace(node.ID)
164	switch uri {
165	case SPDX_NONE_CAPS, SPDX_NONE_SMALL:
166		return SpecialLicense{
167			value: NONE,
168		}, nil
169	case SPDX_NOASSERTION_SMALL, SPDX_NOASSERTION_CAPS:
170		return SpecialLicense{
171			value: NOASSERTION,
172		}, nil
173	}
174
175	// the license is neither NONE nor NOASSERTION
176	// checking if the license is among the standardLicenses
177	licenseAbbreviation := getLastPartOfURI(uri)
178	for _, stdLicense := range AllStandardLicenseIDS() {
179		if licenseAbbreviation == stdLicense {
180			return SpecialLicense{
181				value: SpecialLicenseValue(stdLicense),
182			}, nil
183		}
184	}
185	return lic, fmt.Errorf("found a custom license uri (%s) without any associated fields", uri)
186}
187
188func (parser *rdfParser2_2) getDisjunctiveLicenseSetFromNode(node *gordfParser.Node) (DisjunctiveLicenseSet, error) {
189	licenseSet := DisjunctiveLicenseSet{
190		members: []AnyLicenseInfo{},
191	}
192	for _, triple := range parser.nodeToTriples(node) {
193		switch triple.Predicate.ID {
194		case RDF_TYPE:
195			continue
196		case SPDX_MEMBER:
197			member, err := parser.getAnyLicenseFromNode(triple.Object)
198			if err != nil {
199				return licenseSet, fmt.Errorf("error parsing disjunctive license set: %v", err)
200			}
201			licenseSet.members = append(licenseSet.members, member)
202		}
203	}
204	return licenseSet, nil
205}
206
207func (parser *rdfParser2_2) getConjunctiveLicenseSetFromNode(node *gordfParser.Node) (ConjunctiveLicenseSet, error) {
208	licenseSet := ConjunctiveLicenseSet{
209		members: []AnyLicenseInfo{},
210	}
211	for _, triple := range parser.nodeToTriples(node) {
212		switch triple.Predicate.ID {
213		case RDF_TYPE:
214			continue
215		case SPDX_MEMBER:
216			member, err := parser.getAnyLicenseFromNode(triple.Object)
217			if err != nil {
218				return licenseSet, fmt.Errorf("error parsing conjunctive license set: %v", err)
219			}
220			licenseSet.members = append(licenseSet.members, member)
221		default:
222			return licenseSet, fmt.Errorf("unknown subTag for ConjunctiveLicenseSet: %s", triple.Predicate.ID)
223		}
224	}
225	return licenseSet, nil
226}
227
228func (parser *rdfParser2_2) getSimpleLicensingInfoFromTriples(triples []*gordfParser.Triple) (lic SimpleLicensingInfo, err error) {
229	for _, triple := range triples {
230		switch triple.Predicate.ID {
231		case RDFS_COMMENT:
232			lic.comment = triple.Object.ID
233		case SPDX_LICENSE_ID:
234			lic.licenseID = triple.Object.ID
235		case SPDX_NAME:
236			lic.name = triple.Object.ID
237		case RDFS_SEE_ALSO:
238			if !isUriValid(triple.Object.ID) {
239				return lic, fmt.Errorf("%s is not a valid uri for seeAlso attribute of a License", triple.Object.ID)
240			}
241			lic.seeAlso = append(lic.seeAlso, triple.Object.ID)
242		case SPDX_EXAMPLE:
243			lic.example = triple.Object.ID
244		case RDF_TYPE:
245			continue
246		default:
247			return lic, fmt.Errorf("unknown predicate(%s) for simple licensing info", triple.Predicate)
248		}
249	}
250	return lic, nil
251}
252
253func (parser *rdfParser2_2) getLicenseFromNode(node *gordfParser.Node) (lic License, err error) {
254	associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
255	var restTriples []*gordfParser.Triple
256	for _, triple := range associatedTriples {
257		value := triple.Object.ID
258		switch triple.Predicate.ID {
259		case SPDX_IS_OSI_APPROVED:
260			lic.isOsiApproved, err = boolFromString(value)
261			if err != nil {
262				return lic, fmt.Errorf("error parsing isOsiApproved attribute of a License: %v", err)
263			}
264		case SPDX_LICENSE_TEXT:
265			lic.licenseText = value
266		case SPDX_STANDARD_LICENSE_HEADER:
267			lic.standardLicenseHeader = value
268		case SPDX_STANDARD_LICENSE_TEMPLATE:
269			lic.standardLicenseTemplate = value
270		case SPDX_STANDARD_LICENSE_HEADER_TEMPLATE:
271			lic.standardLicenseHeaderTemplate = value
272		case SPDX_IS_DEPRECATED_LICENSE_ID:
273			lic.isDeprecatedLicenseID, err = boolFromString(value)
274			if err != nil {
275				return lic, fmt.Errorf("error parsing isDeprecatedLicenseId attribute of a License: %v", err)
276			}
277		case SPDX_IS_FSF_LIBRE:
278			lic.isFsfLibre, err = boolFromString(value)
279			if err != nil {
280				return lic, fmt.Errorf("error parsing isFsfLibre attribute of a License: %v", err)
281			}
282		default:
283			restTriples = append(restTriples, triple)
284		}
285	}
286	lic.SimpleLicensingInfo, err = parser.getSimpleLicensingInfoFromTriples(restTriples)
287	if err != nil {
288		return lic, fmt.Errorf("error setting simple licensing information of a License: %s", err)
289	}
290	return lic, nil
291}
292