Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for multiple input strings #634

Merged
merged 3 commits into from
Oct 13, 2023
Merged
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
22 changes: 21 additions & 1 deletion __test_utils__/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { Quad } from '@rdfjs/types';
import 'jest-rdf';
import { DataFactory, Parser, Store } from 'n3';
import { data, dataStar, query, queryAll, result } from '../data/socrates';
import { data, dataSplit, dataStar, query, queryAll, result } from '../data/socrates';
import { n3reasoner } from '../dist';
import { data as blogicData, result as blogicResult } from '../data/blogic';
import { data as regexData, result as regexResult } from '../data/regex';
Expand Down Expand Up @@ -138,16 +138,36 @@ export function universalTests() {
expect<Quad[]>(quads).toBeRdfIsomorphic(resultQuads);
});

it('should execute the n3reasoner [string single list input string output]', async () => {
const resultStr: string = await n3reasoner([data], query);
const quads = (new Parser({ format: 'text/n3' })).parse(resultStr);
expect<Quad[]>(quads).toBeRdfIsomorphic(resultQuads);
});

it('should execute the n3reasoner [string input explicit string output]', async () => {
const resultStr: string = await n3reasoner(data, query, { outputType: 'string' });
const quads = (new Parser({ format: 'text/n3' })).parse(resultStr);
expect<Quad[]>(quads).toBeRdfIsomorphic(resultQuads);
});

it('should execute the n3reasoner [string single list input explicit string output]', async () => {
const resultStr: string = await n3reasoner(data, query, { outputType: 'string' });
const quads = (new Parser({ format: 'text/n3' })).parse(resultStr);
expect<Quad[]>(quads).toBeRdfIsomorphic(resultQuads);
});

it('should execute the n3reasoner [string input explicit quad output]', () => expect<Promise<Quad[]>>(
n3reasoner(data, query, { outputType: 'quads' }),
).resolves.toBeRdfIsomorphic(resultQuads));

it('should execute the n3reasoner [string single list input explicit quad output]', () => expect<Promise<Quad[]>>(
n3reasoner([data], query, { outputType: 'quads' }),
).resolves.toBeRdfIsomorphic(resultQuads));

it('should execute the n3reasoner [string single list input explicit quad output]', () => expect<Promise<Quad[]>>(
n3reasoner(dataSplit, query, { outputType: 'quads' }),
).resolves.toBeRdfIsomorphic(resultQuads));

it('should execute the n3reasoner without query quads', () => expect(
n3reasoner(dataQuads),
).resolves.toBeRdfIsomorphic([socratesMortal]));
Expand Down
20 changes: 16 additions & 4 deletions data/socrates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,28 @@ export const queryAll = `
{?S ?P ?O} => {?S ?P ?O}.
`;

export const data = `
export const socratesPrefixes = `
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix : <http://example.org/socrates#>.
`

:Socrates a :Human.
:Human rdfs:subClassOf :Mortal.
export const socratesHuman = ':Socrates a :Human.';
export const humanMortal = ':Human rdfs:subClassOf :Mortal.';
export const subClassOf = '{?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}.'

{?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}.
export const data = `${socratesPrefixes}
${socratesHuman}
${humanMortal}

${subClassOf}
`;

export const dataSplit: [string, ...string[]] = [
socratesPrefixes + socratesHuman,
socratesPrefixes + humanMortal,
socratesPrefixes + subClassOf,
]

export const result = `
@prefix : <http://example.org/socrates#>.

Expand Down
50 changes: 32 additions & 18 deletions lib/transformers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,23 @@ export function SwiplEye(options?: Partial<EmscriptenModule> | undefined) {
*/
export function runQuery(
Module: SWIPLModule,
data: string,
data: [string, ...string[]],
queryString?: string,
{ output }: Options = {},
): SWIPLModule {
const args: string[] = ['--nope', '--quiet', 'data.nq'];
const args = ['--nope', '--quiet'];

for (let i = 0; i < data.length; i += 1) {
args.push(`data_${i}.n3s`);
Module.FS.writeFile(`data_${i}.n3s`, data[i]);
}

if (queryString) {
if (output) {
throw new Error('Cannot use explicit output with explicit query');
}
Module.FS.writeFile('query.nq', queryString);
args.push('--query', './query.nq');
Module.FS.writeFile('query.n3s', queryString);
args.push('--query', './query.n3s');
} else {
switch (output) {
case undefined:
Expand All @@ -76,8 +81,6 @@ export function runQuery(
}
}

Module.FS.writeFile('data.nq', data);

queryOnce(Module, 'main', args);
return Module;
}
Expand All @@ -92,8 +95,19 @@ function parse(res: string) {
}

export type Data = Quad[] | string
export type InputData = Data | [string, ...string[]]
export type Query = Data | undefined

function inputDataToStrings(data: InputData): [string, ...string[]] {
if (typeof data === 'string') {
return [data];
}
if (typeof data[0] === 'string') {
return data as [string, ...string[]];
}
return [write(data as Quad[])];
}

/**
* Executes a basic query using the EYE Reasoner and default build of SWIPL
* @param data The data for the query as RDF/JS quads
Expand All @@ -105,12 +119,12 @@ export type Query = Data | undefined
* @returns The result of the query as RDF/JS quads
*/
/* eslint-disable max-len */
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query: Query, options: { outputType: 'string' } & Options): Promise<string>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query: Query, options: { outputType: 'quads' } & Options): Promise<Quad[]>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query: Query, options: { outputType: 'string' } & Options): Promise<string>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query: Query, options: { outputType: 'quads' } & Options): Promise<Quad[]>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Quad[], query?: Query, options?: { outputType?: undefined } & Options): Promise<Quad[]>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: string, query?: Query, options?: { outputType?: undefined } & Options): Promise<string>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query?: Query, options?: Options): Promise<Quad[] | string>;
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query?: Query, options?: Options): Promise<Quad[] | string> {
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: string | [string, ...string[]], query?: Query, options?: { outputType?: undefined } & Options): Promise<string>
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query?: Query, options?: Options): Promise<Quad[] | string>;
export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query?: Query, options?: Options): Promise<Quad[] | string> {
/* eslint-enable max-len */
const outputType = options?.outputType;

Expand All @@ -122,7 +136,7 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer
});
runQuery(
Module,
typeof data === 'string' ? data : write(data),
inputDataToStrings(data),
query && (typeof query === 'string' ? query : write(query)),
options,
);
Expand All @@ -131,7 +145,7 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer
throw new Error(`Error while executing query: ${err.join('\n')}`);
}

return (outputType === 'quads' || (typeof data !== 'string' && outputType !== 'string'))
return (outputType === 'quads' || (typeof data !== 'string' && typeof data[0] !== 'string' && outputType !== 'string'))
? parse(res)
: res;
}
Expand All @@ -147,12 +161,12 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer
* @returns The result of the query as RDF/JS quads
*/
/* eslint-disable max-len */
export async function n3reasoner(data: Data, query: Query, options: { outputType: 'string' } & Options): Promise<string>
export async function n3reasoner(data: Data, query: Query, options: { outputType: 'quads' } & Options): Promise<Quad[]>
export async function n3reasoner(data: InputData, query: Query, options: { outputType: 'string' } & Options): Promise<string>
export async function n3reasoner(data: InputData, query: Query, options: { outputType: 'quads' } & Options): Promise<Quad[]>
export async function n3reasoner(data: Quad[], query?: Query, options?: { outputType?: undefined } & Options): Promise<Quad[]>
export async function n3reasoner(data: string, query?: Query, options?: { outputType?: undefined } & Options): Promise<string>
export async function n3reasoner(data: Data, query?: Query, options?: Options): Promise<Quad[] | string>;
export async function n3reasoner(data: Data, query?: Query, options?: Options): Promise<Quad[] | string> {
export async function n3reasoner(data: string | [string, ...string[]], query?: Query, options?: { outputType?: undefined } & Options): Promise<string>
export async function n3reasoner(data: InputData, query?: Query, options?: Options): Promise<Quad[] | string>;
export async function n3reasoner(data: InputData, query?: Query, options?: Options): Promise<Quad[] | string> {
/* eslint-enable max-len */
return executeBasicEyeQuery(options?.SWIPL || SWIPL, data, query, options);
}
Loading