import { NamedNode , BlankNode , Literal , Quad } from "rdf-js" ; import { XML , RDF } from "./consts" ; export type Node = NamedNode | BlankNode ; export type Subject = Node ; export type Predicate = Node ; export type Object = Node | Literal ; export interface Parser < T > { ( terms ) : T ; } export interface BoundGetter { < T > ( predicateName , parser ) : T ; } type StoreO = Object [ ] ; type StorePO = { [ predicateName ] : StoreO ; } ; type StoreSPO = { [ subjectName ] : StorePO ; } ; export class TripleStore { protected spo : StoreSPO ; constructor ( ) { this . spo = Object . create ( null ) ; } _getSubject ( subjectName ) { return this . spo [ subjectName ] ; } _getObjects ( subjectName , predicateName ) { const po = this . _getSubject ( subjectName ) ; return po ? po [ predicateName ] : undefined ; } has ( quad ) { const o = this . _getObjects ( quad . subject . value , quad . predicate . value ) ; if ( ! o ) { return false ; } for ( const objectTerm of o ) { if ( objectTerm . equals ( quad . object ) ) { return true ; } } return false ; } add ( quad ) { if ( this . has ( quad ) ) { return ; } const { spo } = this ; const subjectName = quad . subject . value ; const predicateName = quad . predicate . value ; const po = spo [ subjectName ] || ( spo [ subjectName ] = Object . create ( null ) ) ; const o = po [ predicateName ] || ( po [ predicateName ] = [ ] ) ; o . push ( < Object > quad . object ) ; } get < T > ( subjectName , predicateName , parser ) { const o = this . _getObjects ( subjectName , predicateName ) || [ ] ; return parser ( o ) ; } with < T > ( subjectName , block ) { return block ( ( predicateName , parser ) => this . get ( subjectName , predicateName , parser ) ) ; } } export const nodes = ( terms ) => terms . filter ( ( term ) => term . termType === "NamedNode" || term . termType === "BlankNode" ) . map ( ( term ) => term . value ) ; export const node = ( terms ) => nodes ( terms ) [ 0 ] ; export const text = ( ... languages ) : Parser < string | undefined > => ( terms ) => { const literals = < Literal [ ] > ( terms . filter ( ( term ) => term . termType === "Literal" ) ) ; const strings = literals . filter ( ( term ) => term . datatype . value === XML ( "string" ) ) ; const langStrings = literals . filter ( ( term ) => term . datatype . value === RDF ( "langString" ) ) ; for ( const language of languages ) { const result = language ? langStrings . find ( ( term ) => term . language === language ) : strings [ 0 ] || langStrings [ 0 ] ; if ( result ) { return result . value ; } } return undefined ; } ; export const anyText = text ( "" ) ; export const englishText = text ( "en" , "" ) ;