Skip to content

Commit

Permalink
Handle type maps with string values
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Mar 16, 2020
1 parent bfdf5c6 commit 40cfe50
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 9 deletions.
33 changes: 24 additions & 9 deletions lib/containerhandler/ContainerHandlerType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,31 @@ export class ContainerHandlerType implements IContainerHandler {
public async handle(parsingContext: ParsingContext, util: Util, keys: string[], value: any, depth: number)
: Promise<void> {
if (!Array.isArray(value)) {
// Check needed for cases where entries don't have an explicit @id
const entryHasIdentifier = !!parsingContext.idStack[depth + 1];
if (typeof value === 'string') {
// String values refer to node references
const id = await util.createVocabOrBaseTerm(await parsingContext.getContext(keys), value);
if (id) {
// Handle the value of this node as @id, which will also cause the predicate from above to be emitted.
const subValue = { '@id': id.termType === 'NamedNode' ? id.value : value };
await parsingContext.newOnValueJob(keys, subValue, depth - 1, true);

// Handle the value of this node, which will also cause the type predicate from above to be emitted.
if (!entryHasIdentifier) {
delete parsingContext.idStack[depth]; // Force new (blank node) identifier
}
await parsingContext.newOnValueJob(keys, value, depth - 1, true);
if (!entryHasIdentifier) {
parsingContext.idStack[depth + 1] = parsingContext.idStack[depth]; // Copy the id to the child node, for @type
// Set the id in the stack so it can be used for the rdf:type handling later on
parsingContext.idStack[depth + 1] = [ id ];
}
} else {
// Other values are handled by handling them as a proper job

// Check needed for cases where entries don't have an explicit @id
const entryHasIdentifier = !!parsingContext.idStack[depth + 1];

// Handle the value of this node, which will also cause the predicate from above to be emitted.
if (!entryHasIdentifier) {
delete parsingContext.idStack[depth]; // Force new (blank node) identifier
}
await parsingContext.newOnValueJob(keys, value, depth - 1, true);
if (!entryHasIdentifier) {
parsingContext.idStack[depth + 1] = parsingContext.idStack[depth]; // Copy the id to the child node, for @type
}
}

// Identify the type to emit.
Expand Down
104 changes: 104 additions & 0 deletions test/JsonLdParser-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6154,6 +6154,110 @@ describe('JsonLdParser', () => {
]);
});

it('with @id and type map with string values expand to @id', async () => {
const stream = streamifyString(`
{
"@context": {
"@base": "http://example.com/entries/",
"ex": "http://ex.org/",
"p": { "@id": "http://ex.org/pred1", "@container": "@type" },
"value": "ex:value"
},
"@id": "http://ex.org/myid",
"p": {
"ex:Type1": "value1",
"ex:Type2": "value2"
}
}`);
return expect(await arrayifyStream(stream.pipe(parser))).toBeRdfIsomorphic([
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
namedNode('http://example.com/entries/value1')),
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
namedNode('http://example.com/entries/value2')),
triple(namedNode('http://example.com/entries/value1'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://ex.org/Type1')),
triple(namedNode('http://example.com/entries/value2'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://ex.org/Type2')),
]);
});

it('with @id and type map with string values expand to invalid @id', async () => {
const stream = streamifyString(`
{
"@context": {
"ex": "http://ex.org/",
"p": { "@id": "http://ex.org/pred1", "@container": "@type" },
"value": "ex:value"
},
"@id": "http://ex.org/myid",
"p": {
"ex:Type1": "value1",
"ex:Type2": "value2"
}
}`);
return expect(await arrayifyStream(stream.pipe(parser))).toBeRdfIsomorphic([]);
});

it('with @id and type map with string values expand to @id using @vocab', async () => {
const stream = streamifyString(`
{
"@context": {
"@base": "http://example.com/entries/",
"@vocab": "http://example.com/ns/",
"p": { "@id": "http://ex.org/pred1", "@container": "@type" },
"value": "ex:value"
},
"@id": "http://ex.org/myid",
"p": {
"Type1": "value1",
"Type2": "value2"
}
}`);
return expect(await arrayifyStream(stream.pipe(parser))).toBeRdfIsomorphic([
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
namedNode('http://example.com/ns/value1')),
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
namedNode('http://example.com/ns/value2')),
triple(namedNode('http://example.com/ns/value1'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.com/ns/Type1')),
triple(namedNode('http://example.com/ns/value2'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.com/ns/Type2')),
]);
});

it('with @id and type map with string values expand to @id using @vocab over blank nodes', async () => {
const stream = streamifyString(`
{
"@context": {
"@base": "http://example.com/entries/",
"@vocab": "http://example.com/ns/",
"p": { "@id": "http://ex.org/pred1", "@container": "@type" },
"value": "ex:value"
},
"@id": "http://ex.org/myid",
"p": {
"Type1": "_:value1",
"Type2": "_:value2"
}
}`);
return expect(await arrayifyStream(stream.pipe(parser))).toBeRdfIsomorphic([
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
blankNode('value1')),
triple(namedNode('http://ex.org/myid'), namedNode('http://ex.org/pred1'),
blankNode('value2')),
triple(blankNode('value1'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.com/ns/Type1')),
triple(blankNode('value2'),
namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
namedNode('http://example.com/ns/Type2')),
]);
});

it('with @id and type map without inner @id\'s', async () => {
const stream = streamifyString(`
{
Expand Down

0 comments on commit 40cfe50

Please sign in to comment.