292 lines
10 KiB
Go
292 lines
10 KiB
Go
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
|
|
|
package parser2v3
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
gordfParser "github.com/spdx/gordf/rdfloader/parser"
|
|
"github.com/spdx/gordf/rdfwriter"
|
|
)
|
|
|
|
// AnyLicense is a baseClass for all the licenses
|
|
// All the types of licenses is a sub-type of AnyLicense,
|
|
// either directly or indirectly.
|
|
// This function acts as a mux for all the licenses. Based on the input, it
|
|
// decides which type of license it is and passes control to that type of
|
|
// license parser to parse the given input.
|
|
func (parser *rdfParser2_3) getAnyLicenseFromNode(node *gordfParser.Node) (AnyLicenseInfo, error) {
|
|
|
|
currState := parser.cache[node.ID]
|
|
if currState == nil {
|
|
// there is no entry about the state of current package node.
|
|
// this is the first time we're seeing this node.
|
|
parser.cache[node.ID] = &nodeState{
|
|
object: nil, // not storing the object as we won't retrieve it later.
|
|
Color: WHITE,
|
|
}
|
|
} else if currState.Color == GREY {
|
|
// we have already started parsing this license node.
|
|
// We have a cyclic dependency!
|
|
return nil, errors.New("Couldn't parse license: found a cyclic dependency on " + node.ID)
|
|
}
|
|
|
|
// setting color of the state to grey to indicate that we've started to
|
|
// parse this node once.
|
|
parser.cache[node.ID].Color = GREY
|
|
|
|
// setting state color to black when we're done parsing this node.
|
|
defer func() { parser.cache[node.ID].Color = BLACK }()
|
|
|
|
associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
if len(associatedTriples) == 0 {
|
|
// just a license uri string was found.
|
|
return parser.getSpecialLicenseFromNode(node)
|
|
}
|
|
|
|
// we have some attributes associated with the license node.
|
|
nodeType, err := getNodeTypeFromTriples(associatedTriples, node)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing license triple: %v", err)
|
|
}
|
|
switch nodeType {
|
|
case SPDX_DISJUNCTIVE_LICENSE_SET:
|
|
return parser.getDisjunctiveLicenseSetFromNode(node)
|
|
case SPDX_CONJUNCTIVE_LICENSE_SET:
|
|
return parser.getConjunctiveLicenseSetFromNode(node)
|
|
case SPDX_EXTRACTED_LICENSING_INFO:
|
|
return parser.getExtractedLicensingInfoFromNode(node)
|
|
case SPDX_LISTED_LICENSE, SPDX_LICENSE:
|
|
return parser.getLicenseFromNode(node)
|
|
case SPDX_WITH_EXCEPTION_OPERATOR:
|
|
return parser.getWithExceptionOperatorFromNode(node)
|
|
case SPDX_OR_LATER_OPERATOR:
|
|
return parser.getOrLaterOperatorFromNode(node)
|
|
case SPDX_SIMPLE_LICENSING_INFO:
|
|
return parser.getSimpleLicensingInfoFromNode(node)
|
|
}
|
|
return nil, fmt.Errorf("Unknown subTag (%s) found while parsing AnyLicense", nodeType)
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getLicenseExceptionFromNode(node *gordfParser.Node) (exception LicenseException, err error) {
|
|
associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
for _, triple := range associatedTriples {
|
|
value := triple.Object.ID
|
|
switch triple.Predicate.ID {
|
|
case RDF_TYPE:
|
|
continue
|
|
case SPDX_LICENSE_EXCEPTION_ID:
|
|
exception.licenseExceptionId = value
|
|
case SPDX_LICENSE_EXCEPTION_TEXT:
|
|
exception.licenseExceptionText = value
|
|
case RDFS_SEE_ALSO:
|
|
if !isUriValid(value) {
|
|
return exception, fmt.Errorf("invalid uri (%s) for seeAlso attribute of LicenseException", value)
|
|
}
|
|
exception.seeAlso = value
|
|
case SPDX_NAME:
|
|
exception.name = value
|
|
case SPDX_EXAMPLE:
|
|
exception.example = value
|
|
case RDFS_COMMENT:
|
|
exception.comment = value
|
|
default:
|
|
return exception, fmt.Errorf("invalid predicate(%s) for LicenseException", triple.Predicate)
|
|
}
|
|
}
|
|
return exception, nil
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getSimpleLicensingInfoFromNode(node *gordfParser.Node) (SimpleLicensingInfo, error) {
|
|
simpleLicensingTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
return parser.getSimpleLicensingInfoFromTriples(simpleLicensingTriples)
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getWithExceptionOperatorFromNode(node *gordfParser.Node) (operator WithExceptionOperator, err error) {
|
|
associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
var memberFound bool
|
|
for _, triple := range associatedTriples {
|
|
switch triple.Predicate.ID {
|
|
case RDF_TYPE:
|
|
continue
|
|
case SPDX_MEMBER:
|
|
if memberFound {
|
|
return operator,
|
|
fmt.Errorf("more than one member found in the WithExceptionOperator (expected only 1)")
|
|
}
|
|
memberFound = true
|
|
member, err := parser.getSimpleLicensingInfoFromNode(triple.Object)
|
|
if err != nil {
|
|
return operator, fmt.Errorf("error parsing member of a WithExceptionOperator: %v", err)
|
|
}
|
|
operator.member = member
|
|
case SPDX_LICENSE_EXCEPTION:
|
|
operator.licenseException, err = parser.getLicenseExceptionFromNode(triple.Object)
|
|
if err != nil {
|
|
return operator, fmt.Errorf("error parsing licenseException of WithExceptionOperator: %v", err)
|
|
}
|
|
default:
|
|
return operator, fmt.Errorf("unknown predicate (%s) for a WithExceptionOperator", triple.Predicate.ID)
|
|
}
|
|
}
|
|
return operator, nil
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getOrLaterOperatorFromNode(node *gordfParser.Node) (operator OrLaterOperator, err error) {
|
|
associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
n := len(associatedTriples)
|
|
if n != 2 {
|
|
return operator, fmt.Errorf("orLaterOperator must be associated with exactly one tag. found %v triples", n-1)
|
|
}
|
|
for _, triple := range associatedTriples {
|
|
switch triple.Predicate.ID {
|
|
case RDF_TYPE:
|
|
continue
|
|
case SPDX_MEMBER:
|
|
operator.member, err = parser.getSimpleLicensingInfoFromNode(triple.Object)
|
|
if err != nil {
|
|
return operator, fmt.Errorf("error parsing simpleLicensingInfo of OrLaterOperator: %v", err)
|
|
}
|
|
default:
|
|
return operator, fmt.Errorf("unknown predicate %s", triple.Predicate.ID)
|
|
}
|
|
}
|
|
return operator, nil
|
|
}
|
|
|
|
// SpecialLicense is a type of license which is not defined in any of the
|
|
// spdx documents, it is a type of license defined for the sake of brevity.
|
|
// It can be [NONE|NOASSERTION|LicenseRef-<string>]
|
|
func (parser *rdfParser2_3) getSpecialLicenseFromNode(node *gordfParser.Node) (lic SpecialLicense, err error) {
|
|
uri := strings.TrimSpace(node.ID)
|
|
switch uri {
|
|
case SPDX_NONE_CAPS, SPDX_NONE_SMALL:
|
|
return SpecialLicense{
|
|
value: NONE,
|
|
}, nil
|
|
case SPDX_NOASSERTION_SMALL, SPDX_NOASSERTION_CAPS:
|
|
return SpecialLicense{
|
|
value: NOASSERTION,
|
|
}, nil
|
|
}
|
|
|
|
// the license is neither NONE nor NOASSERTION
|
|
// checking if the license is among the standardLicenses
|
|
licenseAbbreviation := getLastPartOfURI(uri)
|
|
for _, stdLicense := range AllStandardLicenseIDS() {
|
|
if licenseAbbreviation == stdLicense {
|
|
return SpecialLicense{
|
|
value: SpecialLicenseValue(stdLicense),
|
|
}, nil
|
|
}
|
|
}
|
|
return lic, fmt.Errorf("found a custom license uri (%s) without any associated fields", uri)
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getDisjunctiveLicenseSetFromNode(node *gordfParser.Node) (DisjunctiveLicenseSet, error) {
|
|
licenseSet := DisjunctiveLicenseSet{
|
|
members: []AnyLicenseInfo{},
|
|
}
|
|
for _, triple := range parser.nodeToTriples(node) {
|
|
switch triple.Predicate.ID {
|
|
case RDF_TYPE:
|
|
continue
|
|
case SPDX_MEMBER:
|
|
member, err := parser.getAnyLicenseFromNode(triple.Object)
|
|
if err != nil {
|
|
return licenseSet, fmt.Errorf("error parsing disjunctive license set: %v", err)
|
|
}
|
|
licenseSet.members = append(licenseSet.members, member)
|
|
}
|
|
}
|
|
return licenseSet, nil
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getConjunctiveLicenseSetFromNode(node *gordfParser.Node) (ConjunctiveLicenseSet, error) {
|
|
licenseSet := ConjunctiveLicenseSet{
|
|
members: []AnyLicenseInfo{},
|
|
}
|
|
for _, triple := range parser.nodeToTriples(node) {
|
|
switch triple.Predicate.ID {
|
|
case RDF_TYPE:
|
|
continue
|
|
case SPDX_MEMBER:
|
|
member, err := parser.getAnyLicenseFromNode(triple.Object)
|
|
if err != nil {
|
|
return licenseSet, fmt.Errorf("error parsing conjunctive license set: %v", err)
|
|
}
|
|
licenseSet.members = append(licenseSet.members, member)
|
|
default:
|
|
return licenseSet, fmt.Errorf("unknown subTag for ConjunctiveLicenseSet: %s", triple.Predicate.ID)
|
|
}
|
|
}
|
|
return licenseSet, nil
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getSimpleLicensingInfoFromTriples(triples []*gordfParser.Triple) (lic SimpleLicensingInfo, err error) {
|
|
for _, triple := range triples {
|
|
switch triple.Predicate.ID {
|
|
case RDFS_COMMENT:
|
|
lic.comment = triple.Object.ID
|
|
case SPDX_LICENSE_ID:
|
|
lic.licenseID = triple.Object.ID
|
|
case SPDX_NAME:
|
|
lic.name = triple.Object.ID
|
|
case RDFS_SEE_ALSO:
|
|
if !isUriValid(triple.Object.ID) {
|
|
return lic, fmt.Errorf("%s is not a valid uri for seeAlso attribute of a License", triple.Object.ID)
|
|
}
|
|
lic.seeAlso = append(lic.seeAlso, triple.Object.ID)
|
|
case SPDX_EXAMPLE:
|
|
lic.example = triple.Object.ID
|
|
case RDF_TYPE:
|
|
continue
|
|
default:
|
|
return lic, fmt.Errorf("unknown predicate(%s) for simple licensing info", triple.Predicate)
|
|
}
|
|
}
|
|
return lic, nil
|
|
}
|
|
|
|
func (parser *rdfParser2_3) getLicenseFromNode(node *gordfParser.Node) (lic License, err error) {
|
|
associatedTriples := rdfwriter.FilterTriples(parser.gordfParserObj.Triples, &node.ID, nil, nil)
|
|
var restTriples []*gordfParser.Triple
|
|
for _, triple := range associatedTriples {
|
|
value := triple.Object.ID
|
|
switch triple.Predicate.ID {
|
|
case SPDX_IS_OSI_APPROVED:
|
|
lic.isOsiApproved, err = boolFromString(value)
|
|
if err != nil {
|
|
return lic, fmt.Errorf("error parsing isOsiApproved attribute of a License: %v", err)
|
|
}
|
|
case SPDX_LICENSE_TEXT:
|
|
lic.licenseText = value
|
|
case SPDX_STANDARD_LICENSE_HEADER:
|
|
lic.standardLicenseHeader = value
|
|
case SPDX_STANDARD_LICENSE_TEMPLATE:
|
|
lic.standardLicenseTemplate = value
|
|
case SPDX_STANDARD_LICENSE_HEADER_TEMPLATE:
|
|
lic.standardLicenseHeaderTemplate = value
|
|
case SPDX_IS_DEPRECATED_LICENSE_ID:
|
|
lic.isDeprecatedLicenseID, err = boolFromString(value)
|
|
if err != nil {
|
|
return lic, fmt.Errorf("error parsing isDeprecatedLicenseId attribute of a License: %v", err)
|
|
}
|
|
case SPDX_IS_FSF_LIBRE:
|
|
lic.isFsfLibre, err = boolFromString(value)
|
|
if err != nil {
|
|
return lic, fmt.Errorf("error parsing isFsfLibre attribute of a License: %v", err)
|
|
}
|
|
default:
|
|
restTriples = append(restTriples, triple)
|
|
}
|
|
}
|
|
lic.SimpleLicensingInfo, err = parser.getSimpleLicensingInfoFromTriples(restTriples)
|
|
if err != nil {
|
|
return lic, fmt.Errorf("error setting simple licensing information of a License: %s", err)
|
|
}
|
|
return lic, nil
|
|
}
|