Skip to content

Commit

Permalink
Literal and NamedNode to ts linkeddata#355
Browse files Browse the repository at this point in the history
  • Loading branch information
joepio committed Oct 7, 2019
1 parent 97be965 commit f078b3c
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 61 deletions.
87 changes: 58 additions & 29 deletions src/literal.js → src/literal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
'use strict'
import ClassOrder from './class-order'
import NamedNode from './named-node'
import Node from './node-internal'
import XSD from './xsd'
import { ValueType } from './types'
import classOrder from './class-order'

/**
* An RDF literal node, containing something different than a URI.
* @link https://rdf.js.org/data-model-spec/#literal-interface
*/
export default class Literal extends Node {
constructor (value, language, datatype) {
/**
* The language for the literal
*/
lang!: string

/**
* The literal's datatype as a named node
*/
datatype!: NamedNode

termType: string

/**
* Initializes this literal
* @param value The literal's lexical value
* @param language The language for the literal
* @param datatype The literal's datatype as a named node
*/
constructor (value: string, language?: string | null, datatype?: NamedNode) {
super()
this.termType = Literal.termType
this.termType = 'Literal'
this.value = value
if (language) {
this.lang = language
Expand All @@ -17,8 +40,14 @@ export default class Literal extends Node {
if (datatype) {
this.datatype = NamedNode.fromValue(datatype)
}
if (!datatype) {
this.datatype = XSD.string
}
}
copy () {
/**
* Gets a copy of this literal
*/
copy (): Literal {
return new Literal(this.value, this.lang, this.datatype)
}
equals (other) {
Expand All @@ -31,7 +60,10 @@ export default class Literal extends Node {
((!this.datatype && !other.datatype) ||
(this.datatype && this.datatype.equals(other.datatype)))
}
get language () {
/**
* The language for the literal
*/
get language (): string {
return this.lang
}
set language (language) {
Expand Down Expand Up @@ -61,23 +93,21 @@ export default class Literal extends Node {
toString () {
return '' + this.value
}

/**
* @method fromBoolean
* @static
* @param value {Boolean}
* @return {Literal}
* Builds a literal node from a boolean value
* @param value The value
*/
static fromBoolean (value) {
static fromBoolean(value: boolean): Literal {
let strValue = value ? '1' : '0'
return new Literal(strValue, null, XSD.boolean)
}

/**
* @method fromDate
* @static
* @param value {Date}
* @return {Literal}
* Builds a literal node from a date value
* @param value The value
*/
static fromDate (value) {
static fromDate(value: Date): Literal {
if (!(value instanceof Date)) {
throw new TypeError('Invalid argument to Literal.fromDate()')
}
Expand All @@ -89,13 +119,12 @@ export default class Literal extends Node {
d2(value.getUTCMinutes()) + ':' + d2(value.getUTCSeconds()) + 'Z'
return new Literal(date, null, XSD.dateTime)
}

/**
* @method fromNumber
* @static
* @param value {Number}
* @return {Literal}
* Builds a literal node from a number value
* @param value The value
*/
static fromNumber (value) {
static fromNumber(value: number): Literal {
if (typeof value !== 'number') {
throw new TypeError('Invalid argument to Literal.fromNumber()')
}
Expand All @@ -108,25 +137,26 @@ export default class Literal extends Node {
}
return new Literal(strValue, null, datatype)
}

/**
* @method fromValue
* @param value
* @return {Literal}
* Builds a literal node from an input value
* @param value The input value
*/
static fromValue (value) {
static fromValue(value: ValueType): Literal | Node | undefined | null {
if (typeof value === 'undefined' || value === null) {
return value
}
// @ts-ignore
if (typeof value === 'object' && value.termType) { // this is a Node instance
return value
return value as Node
}
switch (typeof value) {
case 'object':
if (value instanceof Date) {
return Literal.fromDate(value)
}
case 'boolean':
return Literal.fromBoolean(value)
return Literal.fromBoolean(value as boolean)
case 'number':
return Literal.fromNumber(value)
case 'string':
Expand All @@ -137,8 +167,7 @@ export default class Literal extends Node {

}
}
Literal.termType = 'Literal'
Literal.prototype.classOrder = ClassOrder['Literal']
Literal.prototype.datatype = XSD.string

Literal.prototype.classOrder = classOrder['Literal']
Literal.prototype.lang = ''
Literal.prototype.isVar = false
77 changes: 48 additions & 29 deletions src/named-node.js → src/named-node.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
'use strict'
import ClassOrder from './class-order'
import Node from './node-internal'
import { ValueType } from './types';

/**
* @class NamedNode
* @extends Node
*/
* A named (IRI) RDF node
*/
export default class NamedNode extends Node {
static termType: string;

/**
* @constructor
* @param iri {String}
* Initializes this node
* @param iri The IRI for this node
*/
constructor (iri) {
constructor (iri: NamedNode | string) {
super()
this.termType = NamedNode.termType

if (iri && iri.termType === NamedNode.termType) { // param is a named node
iri = iri.value
if (iri && (iri as NamedNode).termType === NamedNode.termType) { // param is a named node
iri = (iri as NamedNode).value
}

if (!iri) {
throw new Error('Missing IRI for NamedNode')
}

if (!iri.includes(':')) {
const iriString = iri as string

if (!iriString.includes(':')) {
throw new Error('NamedNode IRI "' + iri + '" must be absolute.')
}

if (iri.includes(' ')) {
if (iriString.includes(' ')) {
var message = 'Error: NamedNode IRI "' + iri + '" must not contain unencoded spaces.'
throw new Error(message)
}

this.value = iri
this.value = iriString
}
/**
* Returns an $rdf node for the containing directory, ending in slash.
* Returns an RDF node for the containing directory, ending in slash.
*/
dir () {
dir (): NamedNode | null{
var str = this.uri.split('#')[0]
var p = str.slice(0, -1).lastIndexOf('/')
var q = str.indexOf('//')
if ((q >= 0 && p < q + 2) || p < 0) return null
return new NamedNode(str.slice(0, p + 1))
}
/**
* Returns an NN for the whole web site, ending in slash.
* Contrast with the "origin" which does NOT have a trailing slash
*/
site () {

/**
* Returns an NamedNOde for the whole web site, ending in slash.
* Contrast with the "origin" which does NOT have a trailing slash
*/
site (): NamedNode {
var str = this.uri.split('#')[0]
var p = str.indexOf('//')
if (p < 0) throw new Error('This URI does not have a web site part (origin)')
Expand All @@ -59,43 +63,58 @@ export default class NamedNode extends Node {
return new NamedNode(str.slice(0, q + 1))
}
}
doc () {

/**
* Gets the named node for the document
*/
doc (): NamedNode {
if (this.uri.indexOf('#') < 0) {
return this
} else {
return new NamedNode(this.uri.split('#')[0])
}
}
toString () {

/**
* Returns the URI including <brackets>
*/
toString (): string {
return '<' + this.uri + '>'
}

/* The local identifier with the document
*/
/**
* The local identifier with the document
*/
id () {
return this.uri.split('#')[1]
}

/**
* Legacy getter and setter alias, node.uri
*/
get uri () {
get uri (): string {
return this.value
}
set uri (uri) {
set uri (uri: string) {
this.value = uri
}
static fromValue (value) {

/**
* Gets a named node from the specified input value
* @param value An input value
*/
static fromValue(value: ValueType): NamedNode | null | undefined | Node {
if (typeof value === 'undefined' || value === null) {
return value
}
// @ts-ignore
const isNode = value && value.termType
if (isNode) {
return value
return value as NamedNode
}
return new NamedNode(value)
return new NamedNode(value as string)
}
}
NamedNode.termType = 'NamedNode'
NamedNode.prototype.classOrder = ClassOrder['NamedNode']
NamedNode.prototype.isVar = 0
NamedNode.prototype.isVar = false
2 changes: 1 addition & 1 deletion src/node-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default abstract class Node {
/**
* Whether this node is a variable
*/
isVar!: boolean | 1 | 0;
isVar!: boolean;

/**
* The class order for this node
Expand Down
2 changes: 1 addition & 1 deletion src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default Node
* @method fromValue
* @param value - Any native Javascript value
*/
Node.fromValue = function (value: ValueType | null): Node | Literal | undefined | null | Collection {
Node.fromValue = function (value: ValueType): Node | Literal | undefined | null | Collection {
if (typeof value === 'undefined' || value === null) {
return value
}
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Node from './node-internal';
/**
* A type for values that serves as inputs
*/
export type ValueType = Node | Date | string | number | boolean | undefined;
export type ValueType = Node | Date | string | number | boolean | undefined | null;

export interface Bindings {
[id: string]: Node;
Expand Down

0 comments on commit f078b3c

Please sign in to comment.