Skip to content

Commit

Permalink
Add optional direction for literals
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Nov 9, 2023
1 parent 96fa318 commit 332f739
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 9 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Concretely, it provides an implementation of the following interfaces:
* [`DataFactory`](http://rdf.js.org/data-model-spec/#datafactory-interface): A factory for instantiating RDF terms and quads.
* [`NamedNode`](http://rdf.js.org/data-model-spec/#namednode-interface): A term that contains an IRI.
* [`BlankNode`](http://rdf.js.org/data-model-spec/#blanknode-interface): A term that represents an RDF blank node with a label.
* [`Literal`](http://rdf.js.org/data-model-spec/#literal-interface): A term that represents an RDF literal, containing a string with an optional language tag or datatype.
* [`Literal`](http://rdf.js.org/data-model-spec/#literal-interface): A term that represents an RDF literal, containing a string with an optional language tag and optional direction or datatype.
* [`Variable`](http://rdf.js.org/data-model-spec/#variable-interface): A term that represents a variable.
* [`DefaultGraph`](http://rdf.js.org/data-model-spec/#defaultgraph-interface): A singleton term instance that represents the default graph.

Expand Down Expand Up @@ -87,6 +87,7 @@ const term: RDF.Literal = factory.literal('abc');
console.log(term.value); // 'abc'
console.log(term.termType); // 'Literal'
console.log(term.language); // ''
console.log(term.direction); // ''
console.log(term.datatype); // namedNode('http://www.w3.org/2001/XMLSchema#string')
console.log(term.equals(term)); // true
```
Expand All @@ -97,16 +98,29 @@ const term: RDF.Literal = factory.literal('abc', 'en-us');
console.log(term.value); // 'abc'
console.log(term.termType); // 'Literal'
console.log(term.language); // 'en-us'
console.log(term.direction); // ''
console.log(term.datatype); // namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#langString')
console.log(term.equals(term)); // true
```

Directional languaged tagged string literal:
```typescript
const term: RDF.Literal = factory.literal('abc', { language: 'en-us', direction: 'ltr' });
console.log(term.value); // 'abc'
console.log(term.termType); // 'Literal'
console.log(term.language); // 'en-us'
console.log(term.direction); // 'ltr'
console.log(term.datatype); // namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString')
console.log(term.equals(term)); // true
```

Datatyped literal:
```typescript
const term: RDF.Literal = factory.literal('1.2', factory.namedNode('http://www.w3.org/2001/XMLSchema#double'));
console.log(term.value); // 'abc'
console.log(term.termType); // 'Literal'
console.log(term.language); // ''
console.log(term.direction); // ''
console.log(term.datatype); // namedNode('http://www.w3.org/2001/XMLSchema#double')
console.log(term.equals(term)); // true
```
Expand Down
9 changes: 6 additions & 3 deletions lib/DataFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,18 @@ export class DataFactory<Q extends RDF.BaseQuad = RDF.Quad> implements RDF.DataF

/**
* @param value The literal value.
* @param languageOrDatatype The optional language or datatype.
* @param languageOrDatatype The optional language, datatype, or directional language.
* If `languageOrDatatype` is a NamedNode,
* then it is used for the value of `NamedNode.datatype`.
* Otherwise `languageOrDatatype` is used for the value
* If `languageOrDatatype` is a NamedNode, it is used for the value
* of `NamedNode.language`.
* Otherwise, it is used as a directional language,
* from which the language is set to `languageOrDatatype.language`
* and the direction to `languageOrDatatype.direction`.
* @return A new instance of Literal.
* @see Literal
*/
public literal(value: string, languageOrDatatype?: string | RDF.NamedNode): Literal {
public literal(value: string, languageOrDatatype?: string | RDF.NamedNode | RDF.DirectionalLanguage): Literal {

Check failure on line 56 in lib/DataFactory.ts

View workflow job for this annotation

GitHub Actions / lint

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 56 in lib/DataFactory.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 12.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 56 in lib/DataFactory.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 14.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 56 in lib/DataFactory.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 16.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.
return new Literal(value, languageOrDatatype);
}

Expand Down
28 changes: 23 additions & 5 deletions lib/Literal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,54 @@ import type * as RDF from '@rdfjs/types';
import { NamedNode } from './NamedNode';

/**
* A term that represents an RDF literal, containing a string with an optional language tag or datatype.
* A term that represents an RDF literal,
* containing a string with an optional language tag and optional direction
* or datatype.
*/
export class Literal implements RDF.Literal {
public readonly termType = 'Literal';
public readonly value: string;
public readonly language: string;
public readonly datatype: RDF.NamedNode;
public readonly direction: 'ltr' | 'rtl' | '';

public static readonly RDF_LANGUAGE_STRING: RDF.NamedNode =
new NamedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#langString');

public static readonly RDF_DIRECTIONAL_LANGUAGE_STRING: RDF.NamedNode =
new NamedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString');

public static readonly XSD_STRING: RDF.NamedNode =
new NamedNode('http://www.w3.org/2001/XMLSchema#string');

public constructor(value: string, languageOrDatatype?: string | RDF.NamedNode) {
public constructor(value: string, languageOrDatatype?: string | RDF.NamedNode | RDF.DirectionalLanguage) {

Check failure on line 25 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / lint

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 25 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 12.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 25 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 14.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.

Check failure on line 25 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 16.x)

Namespace '"/home/runner/work/rdf-data-factory.js/rdf-data-factory.js/node_modules/@rdfjs/types/index"' has no exported member 'DirectionalLanguage'.
this.value = value;
if (typeof languageOrDatatype === 'string') {
this.language = languageOrDatatype;
this.datatype = Literal.RDF_LANGUAGE_STRING;
this.direction = '';
} else if (languageOrDatatype) {
this.language = '';
this.datatype = languageOrDatatype;
if ('termType' in languageOrDatatype) {
this.language = '';
this.datatype = languageOrDatatype;
this.direction = '';
} else {
this.language = languageOrDatatype.language;
this.datatype = languageOrDatatype.direction ?
Literal.RDF_DIRECTIONAL_LANGUAGE_STRING :
Literal.RDF_LANGUAGE_STRING;
this.direction = languageOrDatatype.direction || '';
}
} else {
this.language = '';
this.datatype = Literal.XSD_STRING;
this.direction = '';
}
}

public equals(other?: RDF.Term | null): boolean {
return !!other && other.termType === 'Literal' && other.value === this.value &&
other.language === this.language && this.datatype.equals(other.datatype);
other.language === this.language && other.direction === this.direction &&

Check failure on line 52 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / lint

Property 'direction' does not exist on type 'Literal'.

Check failure on line 52 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 12.x)

Property 'direction' does not exist on type 'Literal'.

Check failure on line 52 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 14.x)

Property 'direction' does not exist on type 'Literal'.

Check failure on line 52 in lib/Literal.ts

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 16.x)

Property 'direction' does not exist on type 'Literal'.
this.datatype.equals(other.datatype);
}
}
42 changes: 42 additions & 0 deletions test/DataFactory-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('DataFactory', () => {
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('');
expect(literal.datatype).toEqual(factory.namedNode('http://www.w3.org/2001/XMLSchema#string'));
expect(literal.direction).toEqual('');
});

it('should produce a valid language tagged literal', () => {
Expand All @@ -83,6 +84,34 @@ describe('DataFactory', () => {
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('en-us');
expect(literal.datatype).toEqual(factory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'));
expect(literal.direction).toEqual('');
});

it('should produce a valid language tagged literal in extended form', () => {
const literal: RDF.Literal = factory.literal('abc', { language: 'en-us' });
expect(literal.termType).toEqual('Literal');
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('en-us');
expect(literal.datatype).toEqual(factory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#langString'));
expect(literal.direction).toEqual('');
});

it('should produce a valid language tagged literal with ltr direction', () => {
const literal: RDF.Literal = factory.literal('abc', { language: 'en-us', direction: 'ltr' });
expect(literal.termType).toEqual('Literal');
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('en-us');
expect(literal.datatype).toEqual(factory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString'));
expect(literal.direction).toEqual('ltr');
});

it('should produce a valid language tagged literal with rtl direction', () => {
const literal: RDF.Literal = factory.literal('abc', { language: 'en-us', direction: 'rtl' });
expect(literal.termType).toEqual('Literal');
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('en-us');
expect(literal.datatype).toEqual(factory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString'));
expect(literal.direction).toEqual('rtl');
});

it('should produce a valid datatyped literal', () => {
Expand All @@ -91,6 +120,7 @@ describe('DataFactory', () => {
expect(literal.value).toEqual('abc');
expect(literal.language).toEqual('');
expect(literal.datatype).toEqual(factory.namedNode('ex:dt'));
expect(literal.direction).toEqual('');
});

it('should handle equals', () => {
Expand All @@ -104,6 +134,11 @@ describe('DataFactory', () => {
.equals(factory.literal('a', 'en-us'))).toEqual(true);
expect(factory.literal('a', factory.namedNode('ex:dt'))
.equals(factory.literal('a', factory.namedNode('ex:dt')))).toEqual(true);
expect(factory.literal('a', { language: 'en-us' })
.equals(factory.literal('a', 'en-us'))).toEqual(true);

expect(factory.literal('a', { language: 'en-us', direction: 'ltr' })
.equals(factory.literal('a', { language: 'en-us', direction: 'ltr' }))).toEqual(true);

expect(factory.literal('a')
.equals(factory.literal('a', 'en-us'))).toEqual(false);
Expand All @@ -112,6 +147,13 @@ describe('DataFactory', () => {
expect(factory.literal('a')
.equals(factory.literal('a', factory.namedNode('http://www.w3.org/2001/XMLSchema#string')))).toEqual(true);

expect(factory.literal('a', { language: 'en-us', direction: 'ltr' })
.equals(factory.literal('a', { language: 'en-us', direction: 'rtl' }))).toEqual(false);
expect(factory.literal('a', { language: 'en-us' })
.equals(factory.literal('a', { language: 'en-us', direction: 'rtl' }))).toEqual(false);
expect(factory.literal('a', 'en-us')
.equals(factory.literal('a', { language: 'en-us', direction: 'rtl' }))).toEqual(false);

expect(factory.literal('a', 'en-us')
.equals(factory.literal('a'))).toEqual(false);
expect(factory.literal('a', 'en-us')
Expand Down

0 comments on commit 332f739

Please sign in to comment.