Skip to content

Commit

Permalink
Add vocabulary handler
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Jun 23, 2022
1 parent 7abbe6b commit ee35529
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 2 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,27 @@ Generated shape:
<http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/hasMaliciousCreator> <http://www.ldbc.eu/ldbc_socialnet/1.0/data/pers00000019791209301543>.
```

#### Vocabuary Handler

Generates vocabulary information.

```json
{
"handlers": [
{
"@type": "EnhancementHandlerVocabulary"
}
]
}
```

Generated shape:
```turtle
<http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/id> a rdf:Property.
<http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/hasCreator> a rdf:Property.
<http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/Person> a rdfs:Class.
```

### Parameter Emitters

Certain handlers allow their internal parameters to be emitted.
Expand Down
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './lib/handlers/EnhancementHandlerPersonNoise';
export * from './lib/handlers/EnhancementHandlerPostAuthors';
export * from './lib/handlers/EnhancementHandlerPostContents';
export * from './lib/handlers/EnhancementHandlerPosts';
export * from './lib/handlers/EnhancementHandlerVocabulary';
export * from './lib/handlers/IEnhancementContext';
export * from './lib/handlers/IEnhancementHandler';
export * from './lib/logging/ILogger';
Expand Down
35 changes: 33 additions & 2 deletions lib/Enhancer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as fs from 'fs';
import type { Writable } from 'stream';
import { PassThrough } from 'stream';
import type * as RDF from '@rdfjs/types';
import { DataFactory } from 'rdf-data-factory';
import { RdfObjectLoader } from 'rdf-object';
import rdfParser from 'rdf-parse';
import rdfSerializer from 'rdf-serialize';
Expand All @@ -11,6 +12,8 @@ import type { ILogger } from './logging/ILogger';
import type { IParameterEmitter } from './parameters/IParameterEmitter';
import type { IDataSelector } from './selector/IDataSelector';

const DF = new DataFactory();

/**
* Enhances a given dataset.
*/
Expand Down Expand Up @@ -62,7 +65,14 @@ export class Enhancer {

// Prepare context
this.logger?.log('Reading background data: people');
const { people, peopleLocatedInCities, peopleKnows, peopleKnownBy } = await this.extractPeople();
const {
people,
peopleLocatedInCities,
peopleKnows,
peopleKnownBy,
predicates,
classes,
} = await this.extractPeople();
this.logger?.log('Reading background data: activities');
const { posts, comments } = await this.extractActivities();
this.logger?.log('Reading background data: cities');
Expand All @@ -77,6 +87,8 @@ export class Enhancer {
posts,
comments,
cities,
predicates,
classes,
};

// Generate data
Expand All @@ -95,6 +107,8 @@ export class Enhancer {
peopleLocatedInCities: Record<string, RDF.NamedNode>;
peopleKnows: Record<string, RDF.NamedNode[]>;
peopleKnownBy: Record<string, RDF.NamedNode[]>;
predicates: RDF.NamedNode[];
classes: RDF.NamedNode[];
}> {
return new Promise((resolve, reject) => {
// Prepare RDF terms to compare with
Expand All @@ -108,6 +122,8 @@ export class Enhancer {
const peopleLocatedInCities: Record<string, RDF.NamedNode> = {};
const peopleKnows: Record<string, RDF.NamedNode[]> = {};
const peopleKnownBy: Record<string, RDF.NamedNode[]> = {};
const predicates: Set<string> = new Set<string>();
const classes: Set<string> = new Set<string>();
const stream = rdfParser.parse(fs.createReadStream(this.personsPath), { path: this.personsPath });

// Temporary variables to determine knows relationships
Expand Down Expand Up @@ -155,9 +171,24 @@ export class Enhancer {
currentKnowsPerson = undefined;
currentKnowsNode = undefined;
}

// Determine predicates
predicates.add(quad.predicate.value);

// Determine classes
if (quad.predicate.equals(termType)) {
classes.add(quad.object.value);
}
});
stream.on('end', () => {
resolve({ people, peopleLocatedInCities, peopleKnows, peopleKnownBy });
resolve({
people,
peopleLocatedInCities,
peopleKnows,
peopleKnownBy,
predicates: [ ...predicates ].map(value => DF.namedNode(value)),
classes: [ ...classes ].map(value => DF.namedNode(value)),
});
});
});
}
Expand Down
27 changes: 27 additions & 0 deletions lib/handlers/EnhancementHandlerVocabulary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Writable } from 'stream';
import type * as RDF from '@rdfjs/types';
import { DataFactory } from 'rdf-data-factory';
import type { IEnhancementContext } from './IEnhancementContext';
import type { IEnhancementHandler } from './IEnhancementHandler';

const DF = new DataFactory();

/**
* Generates vocabulary information.
*/
export class EnhancementHandlerVocabulary implements IEnhancementHandler {
public async generate(writeStream: RDF.Stream & Writable, context: IEnhancementContext): Promise<void> {
const rdf_type = DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
const rdfs_property = DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#Property');
const rdfs_class = DF.namedNode('http://www.w3.org/2000/01/rdf-schema#Class');

// Write predicates
for (const predicate of context.predicates) {
writeStream.write(DF.quad(predicate, rdf_type, rdfs_property));
}
// Write classes
for (const clazz of context.classes) {
writeStream.write(DF.quad(clazz, rdf_type, rdfs_class));
}
}
}
8 changes: 8 additions & 0 deletions lib/handlers/IEnhancementContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,12 @@ export interface IEnhancementContext {
* An array of IRIs of all cities in the dataset.
*/
cities: RDF.NamedNode[];
/**
* An array of all predicates.
*/
predicates: RDF.NamedNode[];
/**
* An array of all classes.
*/
classes: RDF.NamedNode[];
}
20 changes: 20 additions & 0 deletions test/Enhancer-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ sn:post00000000000000000003 rdf:type snvoc:Post .`;
expect.anything(),
expect.anything(),
],
predicates: [
DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
DF.namedNode('http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/isLocatedIn'),
],
classes: [
DF.namedNode('http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/Person'),
],
};
expect(handlers[0].generate).toHaveBeenCalledWith(expect.any(PassThrough), context);
expect(handlers[1].generate).toHaveBeenCalledWith(expect.any(PassThrough), context);
Expand Down Expand Up @@ -153,6 +160,13 @@ sn:post00000000000000000003 rdf:type snvoc:Post .`;
expect.anything(),
expect.anything(),
],
predicates: [
DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
DF.namedNode('http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/isLocatedIn'),
],
classes: [
DF.namedNode('http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/Person'),
],
};
expect(handlers[0].generate).toHaveBeenCalledWith(expect.any(PassThrough), context);
expect(handlers[1].generate).toHaveBeenCalledWith(expect.any(PassThrough), context);
Expand All @@ -172,6 +186,10 @@ sn:post00000000000000000003 rdf:type snvoc:Post .`;
peopleLocatedInCities: {},
peopleKnownBy: {},
peopleKnows: {},
predicates: [
DF.namedNode('ex:p'),
],
classes: [],
});
});

Expand All @@ -182,6 +200,8 @@ sn:post00000000000000000003 rdf:type snvoc:Post .`;
peopleLocatedInCities: {},
peopleKnownBy: {},
peopleKnows: {},
predicates: [],
classes: [],
});
});

Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerComments-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ describe('EnhancementHandlerComments', () => {
],
comments: [],
cities: [],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPersonNames-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ describe('EnhancementHandlerPersonNames', () => {
DF.namedNode('ex:cit3'),
DF.namedNode('ex:cit4'),
],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPersonNamesCities-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ describe('EnhancementHandlerPersonNamesCities', () => {
DF.namedNode('ex:cit3'),
DF.namedNode('ex:cit4'),
],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPersonNoise-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ describe('EnhancementHandlerPersonNoise', () => {
posts: [],
comments: [],
cities: [],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPostAuthors-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ describe('EnhancementHandlerPostAuthors', () => {
],
comments: [],
cities: [],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPostContents-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ describe('EnhancementHandlerPostContents', () => {
],
comments: [],
cities: [],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
2 changes: 2 additions & 0 deletions test/handlers/EnhancementHandlerPosts-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ describe('EnhancementHandlerPosts', () => {
posts: [],
comments: [],
cities: [],
predicates: [],
classes: [],
};
await context.rdfObjectLoader.context;
});
Expand Down
96 changes: 96 additions & 0 deletions test/handlers/EnhancementHandlerVocabulary-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { PassThrough } from 'stream';
import { DataFactory } from 'rdf-data-factory';
import { RdfObjectLoader } from 'rdf-object';
import { Enhancer } from '../../lib/Enhancer';
import { EnhancementHandlerVocabulary } from '../../lib/handlers/EnhancementHandlerVocabulary';
import type { IEnhancementContext } from '../../lib/handlers/IEnhancementContext';
import { DataSelectorSequential } from '../selector/DataSelectorSequential';
import 'jest-rdf';

const arrayifyStream = require('arrayify-stream');
const DF = new DataFactory();

describe('EnhancementHandlerVocabulary', () => {
let handler: EnhancementHandlerVocabulary;
let stream: PassThrough;
let rdfObjectLoader: RdfObjectLoader;
let context: IEnhancementContext;

beforeEach(async() => {
handler = new EnhancementHandlerVocabulary();
stream = new PassThrough({ objectMode: true });
rdfObjectLoader = new RdfObjectLoader({ context: Enhancer.CONTEXT_LDBC_SNB });
context = {
rdfObjectLoader,
dataSelector: new DataSelectorSequential(),
people: [],
peopleLocatedInCities: {},
peopleKnownBy: {},
peopleKnows: {},
posts: [],
comments: [],
cities: [],
predicates: [
DF.namedNode('ex:p1'),
DF.namedNode('ex:p2'),
DF.namedNode('ex:p3'),
DF.namedNode('ex:p4'),
],
classes: [
DF.namedNode('ex:C1'),
DF.namedNode('ex:C2'),
DF.namedNode('ex:C3'),
DF.namedNode('ex:C4'),
],
};
await context.rdfObjectLoader.context;
});

describe('generate', () => {
it('should handle for no predicates and classes', async() => {
context = { ...context, predicates: [], classes: []};
await handler.generate(stream, context);
stream.end();
expect(await arrayifyStream(stream)).toBeRdfIsomorphic(rdfObjectLoader.createCompactedResource({}).toQuads());
});

it('should handle', async() => {
await handler.generate(stream, context);
stream.end();
expect(await arrayifyStream(stream)).toBeRdfIsomorphic(rdfObjectLoader.createCompactedResources([
{
'@id': `ex:p1`,
type: 'rdf:Property',
},
{
'@id': `ex:p2`,
type: 'rdf:Property',
},
{
'@id': `ex:p3`,
type: 'rdf:Property',
},
{
'@id': `ex:p4`,
type: 'rdf:Property',
},
{
'@id': `ex:C1`,
type: 'rdfs:Class',
},
{
'@id': `ex:C2`,
type: 'rdfs:Class',
},
{
'@id': `ex:C3`,
type: 'rdfs:Class',
},
{
'@id': `ex:C4`,
type: 'rdfs:Class',
},
]).flatMap(resource => resource.toQuads()));
});
});
});

0 comments on commit ee35529

Please sign in to comment.