xref: /aosp_15_r20/external/spdx-tools/rdfloader/parser2v3/utils.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1*ba677afaSXin Li// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2*ba677afaSXin Li
3*ba677afaSXin Lipackage parser2v3
4*ba677afaSXin Li
5*ba677afaSXin Liimport (
6*ba677afaSXin Li	"errors"
7*ba677afaSXin Li	"fmt"
8*ba677afaSXin Li	"strings"
9*ba677afaSXin Li
10*ba677afaSXin Li	gordfParser "github.com/spdx/gordf/rdfloader/parser"
11*ba677afaSXin Li	"github.com/spdx/gordf/rdfwriter"
12*ba677afaSXin Li	urilib "github.com/spdx/gordf/uri"
13*ba677afaSXin Li	"github.com/spdx/tools-golang/spdx/common"
14*ba677afaSXin Li)
15*ba677afaSXin Li
16*ba677afaSXin Li// a uri is of type baseURI#fragment or baseFragment/subFragment
17*ba677afaSXin Li// returns fragment or subFragment when given as an input.
18*ba677afaSXin Lifunc getLastPartOfURI(uri string) string {
19*ba677afaSXin Li	if strings.Contains(uri, "#") {
20*ba677afaSXin Li		parts := strings.Split(uri, "#")
21*ba677afaSXin Li		return parts[len(parts)-1]
22*ba677afaSXin Li	}
23*ba677afaSXin Li	parts := strings.Split(uri, "/")
24*ba677afaSXin Li	return parts[len(parts)-1]
25*ba677afaSXin Li}
26*ba677afaSXin Li
27*ba677afaSXin Lifunc isUriValid(uri string) bool {
28*ba677afaSXin Li	_, err := urilib.NewURIRef(uri)
29*ba677afaSXin Li	return err == nil
30*ba677afaSXin Li}
31*ba677afaSXin Li
32*ba677afaSXin Lifunc getNodeTypeFromTriples(triples []*gordfParser.Triple, node *gordfParser.Node) (string, error) {
33*ba677afaSXin Li	if node == nil {
34*ba677afaSXin Li		return "", errors.New("empty node passed to find node type")
35*ba677afaSXin Li	}
36*ba677afaSXin Li	typeTriples := rdfwriter.FilterTriples(triples, &node.ID, &RDF_TYPE, nil)
37*ba677afaSXin Li	switch len(typeTriples) {
38*ba677afaSXin Li	case 0:
39*ba677afaSXin Li		return "", fmt.Errorf("node{%v} not associated with any type triple", node)
40*ba677afaSXin Li	case 1:
41*ba677afaSXin Li		return typeTriples[0].Object.ID, nil
42*ba677afaSXin Li	default:
43*ba677afaSXin Li		return "", fmt.Errorf("node{%v} is associated with more than one type triples", node)
44*ba677afaSXin Li	}
45*ba677afaSXin Li}
46*ba677afaSXin Li
47*ba677afaSXin Lifunc (parser *rdfParser2_3) nodeToTriples(node *gordfParser.Node) []*gordfParser.Triple {
48*ba677afaSXin Li	if node == nil {
49*ba677afaSXin Li		return []*gordfParser.Triple{}
50*ba677afaSXin Li	}
51*ba677afaSXin Li	return parser.nodeStringToTriples[node.String()]
52*ba677afaSXin Li}
53*ba677afaSXin Li
54*ba677afaSXin Li// returns which boolean was given as an input
55*ba677afaSXin Li// string(bool) is the only possible input for which it will not raise any error.
56*ba677afaSXin Lifunc boolFromString(boolString string) (bool, error) {
57*ba677afaSXin Li	switch strings.ToLower(boolString) {
58*ba677afaSXin Li	case "true":
59*ba677afaSXin Li		return true, nil
60*ba677afaSXin Li	case "false":
61*ba677afaSXin Li		return false, nil
62*ba677afaSXin Li	default:
63*ba677afaSXin Li		return false, fmt.Errorf("boolean string can be either true/false")
64*ba677afaSXin Li	}
65*ba677afaSXin Li}
66*ba677afaSXin Li
67*ba677afaSXin Li/* Function Below this line is taken from the tvloader/parser2v3/utils.go */
68*ba677afaSXin Li
69*ba677afaSXin Li// used to extract DocumentRef and SPDXRef values from an SPDX Identifier
70*ba677afaSXin Li// which can point either to this document or to a different one
71*ba677afaSXin Lifunc ExtractDocElementID(value string) (common.DocElementID, error) {
72*ba677afaSXin Li	docRefID := ""
73*ba677afaSXin Li	idStr := value
74*ba677afaSXin Li
75*ba677afaSXin Li	// check prefix to see if it's a DocumentRef ID
76*ba677afaSXin Li	if strings.HasPrefix(idStr, "DocumentRef-") {
77*ba677afaSXin Li		// extract the part that comes between "DocumentRef-" and ":"
78*ba677afaSXin Li		strs := strings.Split(idStr, ":")
79*ba677afaSXin Li		// should be exactly two, part before and part after
80*ba677afaSXin Li		if len(strs) < 2 {
81*ba677afaSXin Li			return common.DocElementID{}, fmt.Errorf("no colon found although DocumentRef- prefix present")
82*ba677afaSXin Li		}
83*ba677afaSXin Li		if len(strs) > 2 {
84*ba677afaSXin Li			return common.DocElementID{}, fmt.Errorf("more than one colon found")
85*ba677afaSXin Li		}
86*ba677afaSXin Li
87*ba677afaSXin Li		// trim the prefix and confirm non-empty
88*ba677afaSXin Li		docRefID = strings.TrimPrefix(strs[0], "DocumentRef-")
89*ba677afaSXin Li		if docRefID == "" {
90*ba677afaSXin Li			return common.DocElementID{}, fmt.Errorf("document identifier has nothing after prefix")
91*ba677afaSXin Li		}
92*ba677afaSXin Li		// and use remainder for element ID parsing
93*ba677afaSXin Li		idStr = strs[1]
94*ba677afaSXin Li	}
95*ba677afaSXin Li
96*ba677afaSXin Li	// check prefix to confirm it's got the right prefix for element IDs
97*ba677afaSXin Li	if !strings.HasPrefix(idStr, "SPDXRef-") {
98*ba677afaSXin Li		return common.DocElementID{}, fmt.Errorf("missing SPDXRef- prefix for element identifier")
99*ba677afaSXin Li	}
100*ba677afaSXin Li
101*ba677afaSXin Li	// make sure no colons are present
102*ba677afaSXin Li	if strings.Contains(idStr, ":") {
103*ba677afaSXin Li		// we know this means there was no DocumentRef- prefix, because
104*ba677afaSXin Li		// we would have handled multiple colons above if it was
105*ba677afaSXin Li		return common.DocElementID{}, fmt.Errorf("invalid colon in element identifier")
106*ba677afaSXin Li	}
107*ba677afaSXin Li
108*ba677afaSXin Li	// trim the prefix and confirm non-empty
109*ba677afaSXin Li	eltRefID := strings.TrimPrefix(idStr, "SPDXRef-")
110*ba677afaSXin Li	if eltRefID == "" {
111*ba677afaSXin Li		return common.DocElementID{}, fmt.Errorf("element identifier has nothing after prefix")
112*ba677afaSXin Li	}
113*ba677afaSXin Li
114*ba677afaSXin Li	// we're good
115*ba677afaSXin Li	return common.DocElementID{DocumentRefID: docRefID, ElementRefID: common.ElementID(eltRefID)}, nil
116*ba677afaSXin Li}
117*ba677afaSXin Li
118*ba677afaSXin Li// used to extract SPDXRef values only from an SPDX Identifier which can point
119*ba677afaSXin Li// to this document only. Use extractDocElementID for parsing IDs that can
120*ba677afaSXin Li// refer either to this document or a different one.
121*ba677afaSXin Lifunc ExtractElementID(value string) (common.ElementID, error) {
122*ba677afaSXin Li	// check prefix to confirm it's got the right prefix for element IDs
123*ba677afaSXin Li	if !strings.HasPrefix(value, "SPDXRef-") {
124*ba677afaSXin Li		return common.ElementID(""), fmt.Errorf("missing SPDXRef- prefix for element identifier")
125*ba677afaSXin Li	}
126*ba677afaSXin Li
127*ba677afaSXin Li	// make sure no colons are present
128*ba677afaSXin Li	if strings.Contains(value, ":") {
129*ba677afaSXin Li		return common.ElementID(""), fmt.Errorf("invalid colon in element identifier")
130*ba677afaSXin Li	}
131*ba677afaSXin Li
132*ba677afaSXin Li	// trim the prefix and confirm non-empty
133*ba677afaSXin Li	eltRefID := strings.TrimPrefix(value, "SPDXRef-")
134*ba677afaSXin Li	if eltRefID == "" {
135*ba677afaSXin Li		return common.ElementID(""), fmt.Errorf("element identifier has nothing after prefix")
136*ba677afaSXin Li	}
137*ba677afaSXin Li
138*ba677afaSXin Li	// we're good
139*ba677afaSXin Li	return common.ElementID(eltRefID), nil
140*ba677afaSXin Li}
141*ba677afaSXin Li
142*ba677afaSXin Li// used to extract key / value from embedded substrings
143*ba677afaSXin Li// returns subkey, subvalue, nil if no error, or "", "", error otherwise
144*ba677afaSXin Lifunc ExtractSubs(value string, sep string) (string, string, error) {
145*ba677afaSXin Li	// parse the value to see if it's a valid subvalue format
146*ba677afaSXin Li	sp := strings.SplitN(value, sep, 2)
147*ba677afaSXin Li	if len(sp) == 1 {
148*ba677afaSXin Li		return "", "", fmt.Errorf("invalid subvalue format for %s (no %s found)", value, sep)
149*ba677afaSXin Li	}
150*ba677afaSXin Li
151*ba677afaSXin Li	subkey := strings.TrimSpace(sp[0])
152*ba677afaSXin Li	subvalue := strings.TrimSpace(sp[1])
153*ba677afaSXin Li
154*ba677afaSXin Li	return subkey, subvalue, nil
155*ba677afaSXin Li}
156