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