Skip to content

Commit

Permalink
Distinguish between 'sources' and 'source' in context
Browse files Browse the repository at this point in the history
This partially reverts comunica#78 to enable proper distinction
between singular sources and multiple (federatable) sources.

This lays the groundwork for representing multiple sources
in datastructures different than arrays.
  • Loading branch information
rubensworks committed Jul 31, 2018
1 parent 7f882d9 commit efa5165
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export class ActorRdfResolveQuadPatternFederated extends ActorRdfResolveQuadPatt

public async test(action: IActionRdfResolveQuadPattern): Promise<IActorTest> {
const sources = this.getContextSources(action.context);
if (!sources || sources.length < 2) {
throw new Error('Actor ' + this.name + ' can only resolve quad pattern queries against a set of sources.');
if (!sources || sources.length < 1) {
throw new Error('Actor ' + this.name + ' can only resolve quad pattern queries against a sources array.');
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
IActionRdfResolveQuadPattern, IActorRdfResolveQuadPatternOutput,
ILazyQuadSource, KEY_CONTEXT_SOURCES,
ILazyQuadSource, KEY_CONTEXT_SOURCE, KEY_CONTEXT_SOURCES,
} from "@comunica/bus-rdf-resolve-quad-pattern";
import {ActionContext, Actor, IActorTest, Mediator} from "@comunica/core";
import {AsyncIterator, EmptyIterator} from "asynciterator";
Expand Down Expand Up @@ -139,8 +139,8 @@ export class FederatedQuadSource implements ILazyQuadSource {
};

// Prepare the context for this specific source
const context: ActionContext = this.contextDefault.set(KEY_CONTEXT_SOURCES,
[{ type: source.type, value: source.value }]);
const context: ActionContext = this.contextDefault.set(KEY_CONTEXT_SOURCE,
{ type: source.type, value: source.value });

return new PromiseProxyIterator(async () => {
let output: IActorRdfResolveQuadPatternOutput;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,19 @@ describe('ActorRdfResolveQuadPatternFederated', () => {
{ name: 'actor', bus, mediatorResolveQuadPattern, skipEmptyPatterns });
});

it('should test with >= 2 sources', () => {
it('should test with >= 1 sources', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{}, {}] }) })).resolves.toBeTruthy();
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{}] }) })).resolves.toBeTruthy();
});

it('should not test with < 2 sources', () => {
it('should not test with < 1 sources', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{}] }) })).rejects.toBeTruthy();
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [] }) })).rejects.toBeTruthy();
});

it('should not test with a single source', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:source': {} }) })).rejects.toBeTruthy();
});

it('should not test without sources', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('FederatedQuadSource', () => {
beforeEach(() => {
mediator = {
mediate: (action) => {
const type = action.context.get('@comunica/bus-rdf-resolve-quad-pattern:sources')[0].type;
const type = action.context.get('@comunica/bus-rdf-resolve-quad-pattern:source').type;
if (type === 'emptySource') {
return Promise.resolve({ data: new EmptyIterator(),
metadata: () => Promise.resolve({ totalItems: 0 }) });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class ActorRdfResolveQuadPatternFile extends ActorRdfResolveQuadPatternSo
}

protected async getSource(context: ActionContext): Promise<ILazyQuadSource> {
const file: string = this.getContextSources(context)[0].value;
const file: string = this.getContextSource(context).value;
if (!this.stores[file]) {
await this.initializeFile(file, context);
}
Expand All @@ -59,7 +59,7 @@ export class ActorRdfResolveQuadPatternFile extends ActorRdfResolveQuadPatternSo
// Attach totalItems to the output
const output: IActorRdfResolveQuadPatternOutput = await super.getOutput(source, pattern, context);
output.metadata = () => new Promise((resolve, reject) => {
const file: string = this.getContextSources(context)[0].value;
const file: string = this.getContextSource(context).value;
this.stores[file].then((store) => {
const totalItems: number = store.countTriplesByIRI(
N3StoreIterator.termToString(pattern.subject),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('ActorRdfResolveQuadPatternFile', () => {

it('should test', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'file', value: 'abc' }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'file', value: 'abc' }}) }))
.resolves.toBeTruthy();
});

Expand All @@ -68,54 +68,56 @@ describe('ActorRdfResolveQuadPatternFile', () => {

it('should not test on an invalid file', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ sources: [{ type: 'file', value: null }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'file', value: null }}) }))
.rejects.toBeTruthy();
});

it('should not test on no file', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ sources: [{ type: 'entrypoint', value: null }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'entrypoint', value: null }}) }))
.rejects.toBeTruthy();
});

it('should not test on no sources', () => {
return expect(actor.test({ pattern: null, context: ActionContext({ sources: [] }) }))
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [] }) }))
.rejects.toBeTruthy();
});

it('should not test on multiple sources', () => {
return expect(actor.test(
{ pattern: null, context: ActionContext(
{ sources: [{ type: 'file', value: 'a' }, { type: 'file', value: 'b' }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'file', value: 'a' },
{ type: 'file', value: 'b' }] }) }))
.rejects.toBeTruthy();
});

it('should allow file initialization with a valid file', () => {
return expect(actor.initializeFile('myfile')).resolves.toBeTruthy();
return expect(actor.initializeFile('myfile', null)).resolves.toBeTruthy();
});

it('should fail on file initialization with an invalid file', () => {
return expect(actor.initializeFile(null)).rejects.toBeTruthy();
return expect(actor.initializeFile(null, null)).rejects.toBeTruthy();
});

it('should allow a file quad source to be created for a context with a valid file', () => {
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: 'myFile' }] }))).resolves.toBeTruthy();
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: 'myFile' }}))).resolves.toBeTruthy();
});

it('should fail on creating a file quad source for a context with an invalid file', () => {
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: null }] }))).rejects.toBeTruthy();
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: null }}))).rejects.toBeTruthy();
});

it('should create only a file quad source only once per file', () => {
let doc1 = null;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: 'myFile' }] }))
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: 'myFile' }}))
.then((file: any) => {
doc1 = file.store;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: 'myFile' }] }));
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: 'myFile' }}));
})
.then((file: any) => {
expect(file.store).toBe(doc1);
Expand All @@ -124,12 +126,12 @@ describe('ActorRdfResolveQuadPatternFile', () => {

it('should create different documents in file quad source for different files', () => {
let doc1 = null;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: 'myFile1' }] }))
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: 'myFile1' }}))
.then((file: any) => {
doc1 = file.store;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'file', value: 'myFile2' }] }));
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'file', value: 'myFile2' }}));
})
.then((file: any) => {
expect(file.store).not.toBe(doc1);
Expand All @@ -146,7 +148,7 @@ describe('ActorRdfResolveQuadPatternFile', () => {
it('should run on ? ? ?', () => {
const pattern = quad('?', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'file', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'file', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 8 });
expect(await arrayifyStream(output.data)).toEqual([
Expand All @@ -165,7 +167,7 @@ describe('ActorRdfResolveQuadPatternFile', () => {
it('should run on s1 ? ?', () => {
const pattern = quad('s1', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'file', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'file', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 4 });
expect(await arrayifyStream(output.data)).toEqual([
Expand All @@ -180,7 +182,7 @@ describe('ActorRdfResolveQuadPatternFile', () => {
it('should run on s3 ? ?', () => {
const pattern = quad('s3', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'file', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'file', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 0 });
expect(await arrayifyStream(output.data)).toEqual([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class ActorRdfResolveQuadPatternHdt extends ActorRdfResolveQuadPatternSou
}

protected async getSource(context: ActionContext): Promise<ILazyQuadSource> {
const hdtFile: string = this.getContextSources(context)[0].value;
const hdtFile: string = this.getContextSource(context).value;
if (!this.hdtDocuments[hdtFile]) {
await this.initializeHdt(hdtFile);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {

it('should test', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) }))
.resolves.toBeTruthy();
});

Expand All @@ -66,26 +66,26 @@ describe('ActorRdfResolveQuadPatternHdt', () => {

it('should not test on an invalid file', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ sources: [{ type: 'hdtFile', value: null }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: null }}) }))
.rejects.toBeTruthy();
});

it('should not test on no file', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ sources: [{ type: 'entrypoint', value: null }] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'entrypoint', value: null }}) }))
.rejects.toBeTruthy();
});

it('should not test on no sources', () => {
return expect(actor.test({ pattern: null, context: ActionContext(
{ sources: [] }) }))
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [] }) }))
.rejects.toBeTruthy();
});

it('should not test on multiple sources', () => {
return expect(actor.test(
{ pattern: null, context: ActionContext(
{ sources: [{ type: 'hdtFile', value: 'a' }, { type: 'hdtFile', value: 'b' }] }) }))
{ pattern: null, context: ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'a' }, { type: 'hdtFile', value: 'b' }] }) }))
.rejects.toBeTruthy();
});

Expand All @@ -98,23 +98,24 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
});

it('should allow a HDT quad source to be created for a context with a valid file', () => {
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'myFile' }] })))
return expect((<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'hdtFile', value: 'myFile' }})))
.resolves.toBeTruthy();
});

it('should fail on creating a HDT quad source for a context with an invalid file', () => {
return expect((<any> actor).getSource({ sources: [{ type: 'hdtFile', value: null }] })).rejects.toBeTruthy();
return expect((<any> actor).getSource({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
{ type: 'hdtFile', value: null }})).rejects.toBeTruthy();
});

it('should create only a HDT quad source only once per file', () => {
let doc1 = null;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'myFile' }] }))
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'hdtFile', value: 'myFile' }}))
.then((file: any) => {
doc1 = file.hdtDocument;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'myFile' }] }));
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'hdtFile', value: 'myFile' }}));
})
.then((file: any) => {
expect(file.hdtDocument).toBe(doc1);
Expand All @@ -123,13 +124,13 @@ describe('ActorRdfResolveQuadPatternHdt', () => {

it('should create different documents in HDT quad source for different files', () => {
let doc1 = null;
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'myFile1' }] }))
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'hdtFile', value: 'myFile1' }}))
.then((file: any) => {
doc1 = file.hdtDocument;
require('hdt').__setMockedDocument(new MockedHdtDocument([]));
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:sources':
[{ type: 'hdtFile', value: 'myFile2' }] }));
return (<any> actor).getSource(ActionContext({ '@comunica/bus-rdf-resolve-quad-pattern:source':
{ type: 'hdtFile', value: 'myFile2' }}));
})
.then((file: any) => {
expect(file.hdtDocument).not.toBe(doc1);
Expand All @@ -145,7 +146,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
it('should run on ? ? ?', () => {
const pattern = quad('?', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 8 });
expect(await arrayifyStream(output.data)).toEqual([
Expand All @@ -164,7 +165,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
it('should run on ? ? ? without data', () => {
const pattern = quad('?', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 8 });
});
Expand All @@ -173,7 +174,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
it('should run on s1 ? ?', () => {
const pattern = quad('s1', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 4 });
expect(await arrayifyStream(output.data)).toEqual([
Expand All @@ -188,7 +189,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
it('should run on s3 ? ?', () => {
const pattern = quad('s3', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) })
.then(async (output) => {
expect(await output.metadata()).toEqual({ totalItems: 0 });
expect(await arrayifyStream(output.data)).toEqual([]);
Expand All @@ -208,7 +209,7 @@ describe('ActorRdfResolveQuadPatternHdt', () => {
expect((<any> actor).shouldClose).toBe(true);
const pattern = quad('s3', '?', '?');
return actor.run({ pattern, context: ActionContext(
{ '@comunica/bus-rdf-resolve-quad-pattern:sources': [{ type: 'hdtFile', value: 'abc' }] }) })
{ '@comunica/bus-rdf-resolve-quad-pattern:source': { type: 'hdtFile', value: 'abc' }}) })
.then(async (output) => {
expect(await arrayifyStream(output.data)).toBeTruthy();
expect((<any> actor).shouldClose).toBe(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class ActorRdfResolveQuadPatternQpf extends ActorRdfResolveQuadPatternSou
const uriConstructor = async (subject?: RDF.Term, predicate?: RDF.Term, object?: RDF.Term, graph?: RDF.Term) => {
if (!chosenForm) {
// Collect metadata of the hypermedia
const hypermedia: string = this.getContextSources(context)[0].value;
const hypermedia: string = this.getContextSource(context).value;

// Save the form, so it is determined only once per source.
chosenForm = this.chooseForm(hypermedia, context);
Expand All @@ -110,7 +110,7 @@ export class ActorRdfResolveQuadPatternQpf extends ActorRdfResolveQuadPatternSou

protected async getSource(context: ActionContext): Promise<ILazyQuadSource> {
// Cache the source object for each hypermedia entrypoint
const hypermedia: string = this.getContextSources(context)[0].value;
const hypermedia: string = this.getContextSource(context).value;
if (this.sources[hypermedia]) {
return this.sources[hypermedia];
}
Expand Down
Loading

0 comments on commit efa5165

Please sign in to comment.