Skip to content

Commit

Permalink
#349 Use jsonld package without n3 package
Browse files Browse the repository at this point in the history
  • Loading branch information
Fletcher91 committed Oct 2, 2019
1 parent 10bc304 commit d22d57d
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 33 deletions.
18 changes: 12 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"dependencies": {
"@babel/runtime": "^7.5.5",
"async": "^3.1.x",
"jsonld": "^1.6.2",
"jsonld": "^1.8.0",
"n3": "^1.2.0",
"solid-auth-cli": "^1.0.8",
"solid-auth-client": "^2.3.0",
Expand Down
96 changes: 96 additions & 0 deletions src/jsonldparser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import jsonld from 'jsonld'

const rdf = {
first: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first',
rest: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest',
nil: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil'
}

/**
* Parses json-ld formatted JS objects to a rdf Term.
* @param kb - The DataFactory to use.
* @param obj - The json-ld object to process.
* @return {Literal|Literal|Literal|NamedNode|NamedNode|NamedNode}
*/
export function jsonldObjectToTerm (kb, obj) {
if (typeof obj === 'string') {
return kb.literal(obj)
}

if (Object.prototype.hasOwnProperty.call(obj, '@list')) {
return listToStatements(kb, obj)
}

if (Object.prototype.hasOwnProperty.call(obj, '@id')) {
return kb.namedNode(obj['@id'])
}

if (Object.prototype.hasOwnProperty.call(obj, '@language')) {
return kb.literal(obj['@value'], obj['@language'])
}

if (Object.prototype.hasOwnProperty.call(obj, '@type')) {
return kb.literal(obj['@value'], kb.namedNode(obj['@type']))
}

return kb.literal(obj['@value'])
}

/**
* Adds the statements in a json-ld list object to {kb}.
*/
function listToStatements (kb, obj) {
const listId = obj['@id'] ? kb.namedNode(obj['@id']) : kb.blankNode()

obj['@list'].reduce((id, listObj, i, listArr) => {
kb.addStatement(kb.quad(id, kb.namedNode(rdf.first), jsonldObjectToTerm(kb, listArr[i])))

let nextNode
if (i < listArr.length - 1) {
nextNode = kb.blankNode()
kb.addStatement(kb.quad(id, kb.namedNode(rdf.rest), nextNode))
} else {
kb.addStatement(kb.quad(id, kb.namedNode(rdf.rest), kb.namedNode(rdf.nil)))
}

return nextNode
}, listId)

return listId
}

/**
* Takes a json-ld formatted string {str} and adds its statements to {kb}.
*
* Make sure that kb implements the DataFactory interface.
*/
export default function jsonldParser (str, kb, base, callback) {
const baseString = Object.prototype.hasOwnProperty.call(base, 'termType')
? base.value
: base

return jsonld
.flatten(JSON.parse(str), null, { base: baseString })
.then((flattened) => flattened.reduce((store, flatResource) => {
const id = flatResource['@id']
? kb.namedNode(flatResource['@id'])
: kb.blankNode()

for (const property of Object.keys(flatResource)) {
if (property === '@id') {
continue
}
const value = flatResource[property]
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
kb.addStatement(kb.quad(id, kb.namedNode(property), jsonldObjectToTerm(kb, value[i])))
}
} else {
kb.addStatement(kb.quad(id, kb.namedNode(property), jsonldObjectToTerm(kb, value)))
}
}

return kb
}, kb))
.finally(callback)
}
25 changes: 5 additions & 20 deletions src/parse.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import BlankNode from './blank-node'
import DataFactory from './data-factory'
import jsonld from 'jsonld'
import Literal from './literal'
import jsonldParser from './jsonldparser'
import { Parser as N3jsParser } from 'n3' // @@ Goal: remove this dependency
import N3Parser from './n3parser'
import NamedNode from './named-node'
import { parseRDFaDOM } from './rdfaparser'
import RDFParser from './rdfxmlparser'
import sparqlUpdateParser from './patch-parser'
Expand Down Expand Up @@ -37,24 +34,12 @@ export default function parse (str, kb, base, contentType, callback) {
} else if (contentType === 'application/sparql-update') { // @@ we handle a subset
sparqlUpdateParser(str, kb, base)
executeCallback()
} else if (contentType === 'application/ld+json' ||
contentType === 'application/nquads' ||
} else if (contentType === 'application/ld+json') {
jsonldParser(str, kb, base, executeCallback)
} else if (contentType === 'application/nquads' ||
contentType === 'application/n-quads') {
var n3Parser = new N3jsParser({ factory: DataFactory })
var triples = []
if (contentType === 'application/ld+json') {
var jsonDocument
try {
jsonDocument = JSON.parse(str)
} catch (parseErr) {
return callback(parseErr, null)
}
jsonld.toRDF(jsonDocument,
{format: 'application/nquads', base},
nquadCallback)
} else {
nquadCallback(null, str)
}
nquadCallback(null, str)
} else {
throw new Error("Don't know how to parse " + contentType + ' yet')
}
Expand Down
95 changes: 89 additions & 6 deletions tests/unit/parse-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,103 @@ describe('Parse', () => {
"homepage": {
"@id": "http://xmlns.com/foaf/0.1/homepage",
"@type": "@id"
}
},
"name": {
"@id": "http://xmlns.com/foaf/0.1/name",
"@container": "@language"
},
"height": {
"@id": "http://schema.org/height",
"@type": "xsd:float"
},
"list": {
"@id": "https://example.org/ns#listProp",
"@container": "@list"
},
"xsd": "http://www.w3.org/2001/XMLSchema#"
},
"@id": "../#me",
"homepage": "xyz"
"homepage": "xyz",
"name": {
"en": "The Queen",
"de": [ "Die Königin", "Ihre Majestät" ]
},
"height": "173.9",
"list": [
"list item 0",
"list item 1",
"list item 2"
]
}`
store = DataFactory.graph()
parse(content, store, base, mimeType, done)
})

it('uses the specified base IRI', () => {
expect(store.statements).to.have.length(1);
const statement = store.statements[0]
expect(statement.subject.value).to.equal('https://www.example.org/#me')
expect(statement.object.value).to.equal('https://www.example.org/abc/xyz')
const homePageHeight = 5 // homepage + height + 3 x name
const list = 2 * 3 + 1 // (rdf:first + rdf:rest) * 3 items + listProp
expect(store.statements).to.have.length(homePageHeight + list);

const height = store.statements[0]
expect(height.subject.value).to.equal('https://www.example.org/#me')
expect(height.predicate.value).to.equal('http://schema.org/height')
expect(height.object.datatype.value).to.equal('http://www.w3.org/2001/XMLSchema#float')
expect(height.object.value).to.equal('173.9')

const homepage = store.statements[1]
expect(homepage.subject.value).to.equal('https://www.example.org/#me')
expect(homepage.predicate.value).to.equal('http://xmlns.com/foaf/0.1/homepage')
expect(homepage.object.value).to.equal('https://www.example.org/abc/xyz')

const nameDe1 = store.statements[2]
expect(nameDe1.subject.value).to.equal('https://www.example.org/#me')
expect(nameDe1.predicate.value).to.equal('http://xmlns.com/foaf/0.1/name')
expect(nameDe1.object.value).to.equal('Die Königin')

const nameDe2 = store.statements[3]
expect(nameDe2.subject.value).to.equal('https://www.example.org/#me')
expect(nameDe2.predicate.value).to.equal('http://xmlns.com/foaf/0.1/name')
expect(nameDe2.object.value).to.equal('Ihre Majestät')

const nameEn = store.statements[4]
expect(nameEn.subject.value).to.equal('https://www.example.org/#me')
expect(nameEn.predicate.value).to.equal('http://xmlns.com/foaf/0.1/name')
expect(nameEn.object.value).to.equal('The Queen')

const list0First = store.statements[5]
expect(list0First.subject.value).to.equal('n1')
expect(list0First.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#first')
expect(list0First.object.value).to.equal('list item 0')

const list0Rest = store.statements[6]
expect(list0Rest.subject.value).to.equal('n1')
expect(list0Rest.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#rest')
expect(list0Rest.object.value).to.equal(store.statements[7].subject.value)

const list1First = store.statements[7]
expect(list1First.subject.value).to.equal('n2')
expect(list1First.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#first')
expect(list1First.object.value).to.equal('list item 1')

const list1Rest = store.statements[8]
expect(list1Rest.subject.value).to.equal('n2')
expect(list1Rest.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#rest')
expect(list1Rest.object.value).to.equal(store.statements[9].subject.value)

const list2First = store.statements[9]
expect(list2First.subject.value).to.equal('n3')
expect(list2First.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#first')
expect(list2First.object.value).to.equal('list item 2')

const list2Rest = store.statements[10]
expect(list2Rest.subject.value).to.equal('n3')
expect(list2Rest.predicate.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#rest')
expect(list2Rest.object.value).to.equal('http://www.w3.org/1999/02/22-rdf-syntax-ns#nil')

const listProp = store.statements[11]
expect(listProp.subject.value).to.equal('https://www.example.org/#me')
expect(listProp.predicate.value).to.equal('https://example.org/ns#listProp')
expect(listProp.object.value).to.equal('n1')
})
})
})
Expand Down

0 comments on commit d22d57d

Please sign in to comment.