Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions rdfloader/parser/node.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package parser

import "fmt"
import (
"fmt"
"sync/atomic"
)

type NODETYPE string

Expand All @@ -22,14 +25,18 @@ func (node *Node) String() string {
}

type BlankNodeGetter struct {
lastid int
lastid atomic.Int64
}

func (getter *BlankNodeGetter) set(i int) {
getter.lastid.Store(int64(i))
}

func (getter *BlankNodeGetter) Get() Node {
getter.lastid += 1
lastid := getter.lastid.Add(1)
return Node{
NodeType: BLANK,
ID: fmt.Sprintf("N%v", getter.lastid),
ID: fmt.Sprintf("N%v", lastid),
}
}

Expand Down
6 changes: 3 additions & 3 deletions rdfloader/parser/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ func TestBlankNodeGetter_Get(t *testing.T) {
}

// blank node getter with custom lastid.
blankNodeGetter = BlankNodeGetter{
lastid: -1,
}
blankNodeGetter = BlankNodeGetter{}

// last id -1 means that first node should start from N0
blankNodeGetter.set(-1)
firstBlankNode = blankNodeGetter.Get()
if firstBlankNode.ID != "N0" {
t.Errorf("Expected node to be %v, found %v", "N0", firstBlankNode.ID)
Expand Down
50 changes: 34 additions & 16 deletions rdfloader/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,19 @@ func getLastURI(tag xmlreader.Tag, lastURI string) string {
func New() (parser *Parser) {
// creates a new parser object
rdfNS, _ := uri.NewURIRef(RDFNS)
return &Parser{
parser = &Parser{
setTriples: map[string]*Triple{},
setNodes: map[string]*Node{},
Triples: []*Triple{},
writeLock: sync.RWMutex{},
nodesWriteLock: sync.RWMutex{},
SchemaDefinition: map[string]uri.URIRef{"": uri.URIRef{}},
blankNodeGetter: BlankNodeGetter{-1},
blankNodeGetter: BlankNodeGetter{},
wg: sync.WaitGroup{},
rdfNS: rdfNS,
}
parser.blankNodeGetter.set(-1)
return parser
}

func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI string, errp *error) {
Expand Down Expand Up @@ -133,13 +135,23 @@ func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI
*/
node = parser.resolveNode(node)
defer parser.wg.Done()
setError := func(err error) {
parser.writeLock.Lock()
defer parser.writeLock.Unlock()
*errp = err
}
getError := func() error {
parser.writeLock.RLock()
defer parser.writeLock.RUnlock()
return *errp
}
lastURI = getLastURI(currBlock.OpeningTag, lastURI)
if len(currBlock.Children) == 0 {
// adding only one triple which identifies the type of the current block.
predicateURI := parser.rdfNS.AddFragment("type")
openingTagUri, newErr := parser.uriFromPair(currBlock.OpeningTag.SchemaName, currBlock.OpeningTag.Name)
if newErr != nil {
*errp = newErr
setError(newErr)
return
}
parser.appendTriple(&Triple{
Expand All @@ -154,14 +166,14 @@ func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI
// according to https://www.w3.org/TR/rdf-concepts/#dfn-predicate
predicateURI, newErr := parser.uriFromPair(predicateBlock.OpeningTag.SchemaName, predicateBlock.OpeningTag.Name)
if newErr != nil {
*errp = fmt.Errorf("error creating a reference URI link for the predicate block. %v", newErr)
setError(fmt.Errorf("error creating a reference URI link for the predicate block. %v", newErr))
return
}
predicateNode := &Node{NodeType: IRI, ID: predicateURI.String()}

openingTagUri, newErr := parser.uriFromPair(currBlock.OpeningTag.SchemaName, currBlock.OpeningTag.Name)
if newErr != nil {
*errp = newErr
setError(newErr)
return
}

Expand All @@ -180,13 +192,13 @@ func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI
Object: nil,
}
resIdx, newErr := parser.getRDFAttributeIndex(predicateBlock.OpeningTag, "resource")
*errp = newErr
if *errp != nil {
if newErr != nil{
setError(newErr)
return
}
nodeidIdx, newErr := parser.getRDFAttributeIndex(predicateBlock.OpeningTag, "nodeID")
*errp = newErr
if *errp != nil {
if newErr != nil{
setError(newErr)
return
}

Expand Down Expand Up @@ -220,7 +232,7 @@ func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI
for _, objectBlock := range predicateBlock.Children {
objectNode, newErr := parser.nodeFromTag(objectBlock.OpeningTag, lastURI)
if newErr != nil {
*errp = newErr
setError(newErr)
return
}

Expand All @@ -231,7 +243,7 @@ func (parser *Parser) parseBlock(currBlock *xmlreader.Block, node *Node, lastURI
})
parser.wg.Add(1)
go parser.parseBlock(objectBlock, objectNode, lastURI, errp)
if *errp != nil {
if getError() != nil {
return
}
}
Expand All @@ -246,19 +258,25 @@ func (parser *Parser) Parse(rootBlock xmlreader.Block) (err error) {
}
parser.SchemaDefinition = schemaDefinition

getError := func() error {
parser.writeLock.RLock()
defer parser.writeLock.RUnlock()
return err
}
// root tag is set now.
var childNode *Node
var lerr error
xmlns := schemaDefinition[""]
xmlnsString := xmlns.String()
for _, child := range rootBlock.Children {
childNode, err = parser.nodeFromTag(child.OpeningTag, xmlnsString)
if err != nil {
return err
childNode, lerr = parser.nodeFromTag(child.OpeningTag, xmlnsString)
if lerr != nil {
return lerr
}
parser.wg.Add(1)
go parser.parseBlock(child, childNode, xmlnsString, &err)
if err != nil {
return err
if lerr := getError(); lerr != nil {
return lerr
}
}
parser.wg.Wait() // wait for all the go routines to finish executing.
Expand Down
11 changes: 11 additions & 0 deletions rdfwriter/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/spdx/gordf/rdfloader/parser"
"github.com/spdx/gordf/uri"
"slices"
"strings"
)

Expand Down Expand Up @@ -80,6 +81,16 @@ func getUniqueTriples(triples []*parser.Triple) []*parser.Triple {
for key := range set {
retList = append(retList, set[key])
}
slices.SortFunc(retList, func(a, b *parser.Triple) int {
c := strings.Compare(a.Subject.String(), b.Subject.String())
if c == 0 {
c = strings.Compare(a.Predicate.String(), b.Predicate.String())
}
if c == 0 {
c = strings.Compare(a.Object.String(), b.Predicate.String())
}
return c
})
return retList
}

Expand Down
12 changes: 12 additions & 0 deletions rdfwriter/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ func TestTopologicalSortTriples(t *testing.T) {
{Subject: nodes[0], Predicate: nodes[2], Object: nodes[3]},
{Subject: nodes[3], Predicate: nodes[4], Object: nodes[0]},
}
t.Logf("Got %d sortedTriples:", len(sortedTriples))
for k, v := range sortedTriples {
t.Logf(" sortedTriples[%v]=%s", k, v)
}
t.Logf("Want %d expectedTriples", len(expectedTriples))
for k, v := range expectedTriples {
t.Logf(" expectedTriples[%v]=%s", k, v)
}
t.Logf("Or %d anotherConfig", len(anotherConfig))
for k, v := range anotherConfig {
t.Logf(" anotherConfig[%v]=%s", k, v)
}
if !reflect.DeepEqual(sortedTriples, expectedTriples) && !reflect.DeepEqual(sortedTriples, anotherConfig) {
t.Errorf("sorted triples are not in correct order")
}
Expand Down