UNPKG

sparnatural

Version:

Visual client-side SPARQL query builder and knowledge graph exploration tool

816 lines (698 loc) 32.3 kB
import { BaseRDFReader, RDF, RDFS } from "../BaseRDFReader"; import { DataFactory, NamedNode } from 'rdf-data-factory'; import { DASH, SH, SHACLSpecificationProvider, SKOS, VOLIPI, XSD } from "./SHACLSpecificationProvider"; import { SHACLSpecificationEntry } from "./SHACLSpecificationEntry"; import { SHACLSpecificationProperty } from "./SHACLSpecificationProperty"; import ISHACLSpecificationEntity from "./ISHACLSpecificationEntity"; import { GEOSPARQL } from "../../components/widgets/MapWidget"; import { RdfStore } from "rdf-stores"; import { Quad_Subject, Term } from "@rdfjs/types"; import { StoreModel } from "../StoreModel"; import { DagIfc, Dag } from "../../dag/Dag"; import ISpecificationEntity from "../ISpecificationEntity"; import ISpecificationProperty from "../ISpecificationProperty"; const factory = new DataFactory(); export class SHACLSpecificationEntity extends SHACLSpecificationEntry implements ISHACLSpecificationEntity { constructor(uri:string, provider: SHACLSpecificationProvider, n3store: RdfStore, lang: string) { super(uri, provider, n3store, lang); } getLabel(): string { // first try to read an rdfs:label let label = this.graph.readSinglePropertyInLang(factory.namedNode(this.uri), RDFS.LABEL, this.lang)?.value; if(!label) { // attempt to read it on the targetClass, if we have it if(this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET_CLASS, null)) { let targetClass = this.graph.readSingleProperty(factory.namedNode(this.uri), SH.TARGET_CLASS); label = this.graph.readSinglePropertyInLang(targetClass as Term, RDFS.LABEL, this.lang)?.value; } } if(!label) { // attempt to read the local part of the targetClass URI if(this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET_CLASS, null)) { let targetClass = this.graph.readSingleProperty(factory.namedNode(this.uri), SH.TARGET_CLASS); label = StoreModel.getLocalName(targetClass.value) as string; } } if(!label) { // default : read the local part of the URI label = StoreModel.getLocalName(this.uri) as string; } return label; } getTooltip(): string | undefined { let tooltip = this.graph.readSinglePropertyInLang(factory.namedNode(this.uri), VOLIPI.MESSAGE, this.lang)?.value; if(!tooltip) { // try with sh:description tooltip = this.graph.readSinglePropertyInLang(factory.namedNode(this.uri), SH.DESCRIPTION, this.lang)?.value; } if(this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET_CLASS, null)) { if(!tooltip) { // try to read an rdfs:comment on the class itself // note that we try to read the value even in case the target is a blank node, e.g. SPARQL target tooltip = this.graph.readSinglePropertyInLang( this.graph.readSingleProperty(factory.namedNode(this.uri), SH.TARGET_CLASS) as Term, SKOS.DEFINITION, this.lang)?.value; } if(!tooltip) { // try to read an rdfs:comment on the class itself // note that we try to read the value even in case the target is a blank node, e.g. SPARQL target tooltip = this.graph.readSinglePropertyInLang( this.graph.readSingleProperty(factory.namedNode(this.uri), SH.TARGET_CLASS) as Term, RDFS.COMMENT, this.lang)?.value; } } return tooltip; } getConnectingProperties(range: string): string[] { // read all sh:property and find the ones that can target the selected class var items: string[] = []; let propShapes = this.getProperties(); propShapes.forEach(ps => { let prop = new SHACLSpecificationProperty(ps, this.provider, this.store, this.lang); let pRange = prop.getRange(); if(pRange.indexOf(range) > -1) { items.push(ps); } }); // add properties available from parents - recursively let parents = this.provider.getEntity(range).getParents(); parents.forEach(aParent => { items = [...items, ...this.getConnectingProperties(aParent)]; }) // dedup, although probably dedup is not necessary here var dedupItems = [...new Set(items)]; // sort dedups var sortedDedups = SHACLSpecificationEntry.sort(dedupItems.map(s => new SHACLSpecificationProperty(s, this.provider, this.store, this.lang))); // return dedup array of strings return sortedDedups.map(e => e.getId()); } /** * Return the tree of properties connecting this entity to the specified range entity * @param range The URI of the selected target entity * @returns */ getConnectingPropertiesTree(range: string): DagIfc<ISpecificationProperty> { // 1. get list of properties let properties:ISpecificationProperty[] = this.getConnectingProperties(range).map(s => this.provider.getProperty(s)) as ISpecificationProperty[]; // retrive the potential parents while(!properties.every(property => { return property.getParents().every(parent => { return (properties.find(anotherProperty => anotherProperty.getId() === parent) != undefined); }); })) { let parentsToAdd:ISpecificationProperty[] = []; properties.forEach(property => { property.getParents().forEach(parent => { if(!properties.find(anotherProperty => anotherProperty.getId() === parent)) { parentsToAdd.push(this.provider.getProperty(parent) as ISpecificationProperty); } }) }); parentsToAdd.forEach(p => properties.push(p)); } // 2. turn it into a flat tree let dag:Dag<ISpecificationProperty> = new Dag<ISpecificationProperty>(); // dag.initFlatTreeFromFlatList(properties); dag.initFromParentableAndIdAbleEntity(properties, []); // sort the tree with compare function dag.sort(SHACLSpecificationProperty.compare); return dag; } getConnectedEntities(): string[] { var items: string[] = []; // read all properties that make sense for Sparnatural let propShapes = this.getProperties(); propShapes .forEach(ps => { // read the property let prop = new SHACLSpecificationProperty(ps, this.provider, this.store, this.lang); // and then read their ranges items.push(...prop.getRange()); }); // dedup var dedupItems = [...new Set(items)]; // sort dedups var sortedDedups = SHACLSpecificationEntry.sort(dedupItems.map(s => new SHACLSpecificationEntity(s, this.provider, this.store, this.lang))); // return dedup array of strings return sortedDedups.map(e => e.getId()); } getConnectedEntitiesTree(): DagIfc<ISpecificationEntity> { // 1. get directly connected entities let entities:SHACLSpecificationEntity[] = this.getConnectedEntities().map(s => this.provider.getEntity(s)) as SHACLSpecificationEntity[]; // 2. add the children of these entities - recursively while(!entities.every(entity => { return entity.getChildren().every(child => { return (entities.find(anotherEntity => anotherEntity.getId() === child) != undefined); }); })) { let childrenToAdd:SHACLSpecificationEntity[] = []; entities.forEach(entity => { entity.getChildren().forEach(child => { if(!entities.find(anotherEntity => anotherEntity.getId() === child)) { childrenToAdd.push(this.provider.getEntity(child) as SHACLSpecificationEntity); } }) }); childrenToAdd.forEach(p => entities.push(p)); } // 3. complement the initial list with their parents let disabledList:string[] = new Array<string>(); // while not all parents of all entities are not part of the list... while(!entities.every(entity => { return entity.getParents().every(parent => { return (entities.find(anotherEntity => anotherEntity.getId() === parent) != undefined); }); })) { let parentsToAdd:SHACLSpecificationEntity[] = []; entities.forEach(entity => { entity.getParents().forEach(parent => { if(!entities.find(anotherEntity => anotherEntity.getId() === parent)) { parentsToAdd.push(this.provider.getEntity(parent) as SHACLSpecificationEntity); } }) }); parentsToAdd.forEach(p => entities.push(p)); // also keep that as a disabled node parentsToAdd.forEach(p => disabledList.push(p.getId())); } let dag:Dag<ISpecificationEntity> = new Dag<ISpecificationEntity>(); dag.initFromParentableAndIdAbleEntity(entities, disabledList); // sort the tree with compare function dag.sort(SHACLSpecificationEntity.compare); return dag; } hasConnectedEntities(): boolean { return (this.getConnectedEntities().length > 0) } /** * @returns all (non-deactivated) properties available on this node shape, including inherited properties from superclasses */ getProperties(): string[] { var items: string[] = []; // read all sh:property let propShapes = this.graph.readProperty(factory.namedNode(this.uri), SH.PROPERTY) .map(node => node.value); // add all properties from parents (either through sh:node or sh:targetClass/rdfs:subClassOf/^sh:targetClass) let parents:string[] = this.getParents(); parents.forEach(p => { let parentEntity = new SHACLSpecificationEntity(p,this.provider, this.store, this.lang); propShapes.push(...parentEntity.getProperties()); }); // filter properties not to be shown propShapes .forEach(ps => { if(SHACLSpecificationProperty.isSparnaturalSHACLSpecificationProperty(ps, this.store)) { items.push(ps); } }); // dedup, although probably dedup is not necessary here var dedupItems = [...new Set(items)]; // sort dedups var sortedDedups = SHACLSpecificationEntry.sort(dedupItems.map(s => new SHACLSpecificationProperty(s, this.provider, this.store, this.lang))); // return dedup array of strings return sortedDedups.map(e => e.getId()); } /** * * @returns true if sh:nodeKind = sh:Literal, or if sh:datatype is present, or if sh:languageIn is present */ isLiteralEntity(): boolean { var hasNodeKindLiteral = this.graph.hasTriple(factory.namedNode(this.uri), SH.NODE_KIND, SH.LITERAL); var hasDatatype = this.graph.hasTriple(factory.namedNode(this.uri), SH.DATATYPE, null); var hasLanguageIn = this.graph.hasTriple(factory.namedNode(this.uri), SH.LANGUAGE_IN, null); var hasUniqueLang = this.graph.hasTriple(factory.namedNode(this.uri), SH.UNIQUE_LANG, null); return hasNodeKindLiteral || hasDatatype || hasLanguageIn || hasUniqueLang; } /** * @returns true if this shape has a target, either a targetClass or sh:target, or is itself a Class */ hasTypeCriteria(): boolean { var hasTargetClass = this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET_CLASS, null); var hasTarget = this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET, null); var isItselfClass = this.graph.hasTriple(factory.namedNode(this.uri), RDF.TYPE, RDFS.CLASS); return (hasTargetClass || hasTarget || isItselfClass); } /** * @returns a property labelled with dash:propertyRole = dash:LabelRole */ getDefaultLabelProperty(): string | undefined { var items: any[] = []; // read all properties let propShapes = this.graph.readProperty(factory.namedNode(this.uri), SH.PROPERTY); propShapes.forEach(ps => { if (this.store.getQuads( ps, DASH.PROPERTY_ROLE, DASH.LABEL_ROLE, null ).length > 0) { items.push(ps); } }); // nothing found, see if we can inherit it if(items.length == 0) { let parents = this.getParents(); let parentDefaultLabelProp:string|undefined; parents.forEach(p => { // if not found already, set it to the parent default label prop - otherwise keep the value we found if(!parentDefaultLabelProp) { let parentEntity = new SHACLSpecificationEntity(p,this.provider, this.store, this.lang); parentDefaultLabelProp = parentEntity.getDefaultLabelProperty(); } }); // could be undefined or a string return parentDefaultLabelProp; } else { // return the first one found return items[0].value } } getParents(): string[] { let parentsFromSuperClasses = this.#findShapesTargetingClassIn(this.getImmediateSuperClassesOfTargetClass()); if(parentsFromSuperClasses.length == 0) { parentsFromSuperClasses = this.#findShapesTargetingClassIn(this.getSuperClassesOfTargetClass(2)); } if(parentsFromSuperClasses.length == 0) { parentsFromSuperClasses = this.#findShapesTargetingClassIn(this.getSuperClassesOfTargetClass(3)); } if(parentsFromSuperClasses.length == 0) { parentsFromSuperClasses = this.#findShapesTargetingClassIn(this.getSuperClassesOfTargetClass(4)); } if(parentsFromSuperClasses.length == 0) { parentsFromSuperClasses = this.#findShapesTargetingClassIn(this.getSuperClassesOfTargetClass(5)); } // get the parents from sh:node let parentsFromShNode = this.#getShNode(); // concat parents from superclasses and from node - deduplicated let parents = [...new Set([...parentsFromSuperClasses, ...parentsFromShNode])]; return parents // and simply return the string value .map(term => term.value); } #findShapesTargetingClassIn(classes: Term[]) { // note : we exclude blank nodes return classes.filter(term => term.termType == "NamedNode") // we find the shape targeting this class - it can be the class itself .map(term => { if(this.graph.hasTriple(term as Quad_Subject, RDF.TYPE, RDFS.CLASS)) { return term; } else { return this.graph.findSingleSubjectOf(SH.TARGET_CLASS, term); } }) // remove those for which the shape was not found .filter(term => (term != undefined)); } getChildren(): string[] { let cildrenFromSuperClasses = this.getSubClassesOfTargetClass() // note : we exclude blank nodes .filter(term => term.termType == "NamedNode") // we find the shape targeting this class - it can be the class itself .map(term => { if(this.graph.hasTriple(term as Quad_Subject, RDF.TYPE, RDFS.CLASS)) { return term; } else { return this.graph.findSingleSubjectOf(SH.TARGET_CLASS, term); } }) // remove those for which the shape was not found .filter(term => (term != undefined)); // get the children from sh:node let childrenFromShNode = this.#getInverseOfShNodeForExplicitNodeShapes(); // concat parents from superclasses and from node - deduplicated let children = [...new Set([...cildrenFromSuperClasses, ...childrenFromShNode])]; return children // and simply return the string value .map(term => term.value); } /** * @returns the recursive superclasses of the target class of this Shape (can be the shape itself) */ getAllSuperClassesOfTargetClass(): Term[] { // retrieve target classes let targetClasses:Term[] = this.#getTargetClasses(); // then retrieve super classes of those classes let superClasses:Term[] = []; targetClasses.forEach(tc => { let allSuperClasses = this.graph.readPropertyRec(tc, RDFS.SUBCLASS_OF); superClasses.push(...allSuperClasses); }); return superClasses; } /** * @returns the immediate superclasses of the target class of this Shape (can be the shape itself) */ getImmediateSuperClassesOfTargetClass(): Term[] { return this.getSuperClassesOfTargetClass(1); } getSuperClassesOfTargetClass(level: number): Term[] { // retrieve target classes let targetClasses:Term[] = this.#getTargetClasses(); // then retrieve super classes of those classes let superClasses:Term[] = []; targetClasses.forEach(tc => { let currentSuperClasses = this.#getSuperClassesAtLevel(tc, level); superClasses.push(...currentSuperClasses); }); return superClasses; } /** * @returns the immediate subclasses of the target class of this Shape (can be the shape itself) */ getSubClassesOfTargetClass(): Term[] { // retrieve target classes let targetClasses:Term[] = this.#getTargetClasses(); // then retrieve sub classes of those classes let subClasses:Term[] = []; targetClasses.forEach(tc => { let currentSubClasses = this.graph.findSubjectsOf(RDFS.SUBCLASS_OF, tc) subClasses.push(...currentSubClasses); }); return subClasses; } /** * @returns all super classes, recursively, of the provided classes. This is currently not used. */ #getSuperClassesRec(classNode:Term): Term[] { var items: Term[] = []; let superClasses = this.graph.readProperty(classNode, RDFS.SUBCLASS_OF); items.push(...superClasses); superClasses.forEach(sc => { items.push(...this.#getSuperClassesRec(sc)); }); return items; } /** * @returns the superClasses of the provided class, at a certain level */ #getSuperClassesAtLevel(classNode:Term, level:number): Term[] { if(level < 1) { return null; } var items: Term[] = []; let superClasses = this.graph.readProperty(classNode, RDFS.SUBCLASS_OF); items.push(...superClasses); if(level == 1) { return items; } else { var result: Term[] = []; items.forEach(i => result.push(...this.#getSuperClassesAtLevel(i, (level-1)))); return result; } } /** * @returns the NodeShape IRI that are referenced from this one with sh:node - this is like subClassOf */ #getShNode(): Term[] { return this.graph.readProperty(factory.namedNode(this.uri), SH.NODE); } /** * @returns the NodeShapes IRI that reference this one with sh:node */ #getInverseOfShNodeForExplicitNodeShapes(): Term[] { let subjects:Quad_Subject[] = this.graph.findSubjectsOf(SH.NODE, factory.namedNode(this.uri)); // keep only the sh:node references from NodeShapes, not property shapes or sh:or on property shapes // there could be more precise ways of doing this return subjects.filter(term => term.termType == "NamedNode" && this.graph.hasTriple(term, RDF.TYPE, SH.NODE_SHAPE) ) } isRangeOf(n3store:RdfStore, shapeUri:any) { return (SHACLSpecificationProperty.readShClassAndShNodeOn(n3store, shapeUri).indexOf(this.uri) > -1); } /** * @returns all targeted classes, either implicitly or explicitly through sh:targetClass */ #getTargetClasses():Term[] { if(this.#isNodeShapeAndClass()) { return [factory.namedNode(this.uri)]; } else { return this.getShTargetClass(); } } /** * @returns true if this entity is both a NodeShape and a Class */ #isNodeShapeAndClass():boolean { return ( this.graph.hasTriple(factory.namedNode(this.uri), RDF.TYPE, RDFS.CLASS) && this.graph.hasTriple(factory.namedNode(this.uri), RDF.TYPE, SH.NODE_SHAPE) ); } /** * @returns all values of sh:targetClass on this entity, as RDF Terms */ getShTargetClass():Term[] { return this.graph.readProperty(factory.namedNode(this.uri), SH.TARGET_CLASS); } /** * @returns true if this shape as an sh:target predicate (indicating it is associated to a SPARQL query target) */ hasShTarget():boolean { console.log("hasShTarget "+this.uri+" "+this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET, null)) return this.graph.hasTriple(factory.namedNode(this.uri), SH.TARGET, null); } static compare(item1: SHACLSpecificationEntity, item2: SHACLSpecificationEntity) { return SHACLSpecificationEntry.compare(item1, item2); } } export class SpecialSHACLSpecificationEntity implements ISHACLSpecificationEntity { private id:string; private icon:string; private label:string; private isRangeOfFunction:Function; constructor(id:string, icon:string,label:string, isRangeOfFunction:Function) { this.id = id; this.icon = icon; this.label = label; this.isRangeOfFunction = isRangeOfFunction; } getConnectedEntities(): string[] { return new Array<string>(); } getConnectedEntitiesTree(): DagIfc<ISpecificationEntity> { return new Dag<ISpecificationEntity>(); } hasConnectedEntities(): boolean { return false; } getConnectingProperties(range: string): string[] { return new Array<string>(); } getConnectingPropertiesTree(range: string): DagIfc<ISpecificationProperty> { return new Dag<ISpecificationProperty>(); } isLiteralEntity(): boolean { return true; } hasTypeCriteria(): boolean { return false; } getDefaultLabelProperty(): string | undefined { return undefined; } getId(): string { return this.id; } getLabel(): string { return this.label; } getOrder(): string|undefined { return undefined; } getTooltip(): string | undefined { return undefined; } getColor(): string | undefined { // return "slategray"; return undefined; } getDatasource(): any { return null; } getTreeChildrenDatasource(): any { return null; } getTreeRootsDatasource(): any { return null; } getIcon(): string { return this.icon; } getHighlightedIcon(): string { return ""; } isRangeOf(n3store:RdfStore, shapeUri:any):boolean { return this.isRangeOfFunction(n3store, shapeUri); } getParents(): string[] { return []; } getChildren(): string[] { return []; } } export class SpecialSHACLSpecificationEntityRegistry { private registry:Map<string,SpecialSHACLSpecificationEntity> = new Map<string,SpecialSHACLSpecificationEntity>(); public static SPECIAL_SHACL_ENTITY_DATES = "http://special/Z_Date"; public static SPECIAL_SHACL_ENTITY_LOCATION = "http://special/Z_Location"; public static SPECIAL_SHACL_ENTITY_TEXT = "http://special/Z_Text"; public static SPECIAL_SHACL_ENTITY_NUMBER = "http://special/Z_Number"; public static SPECIAL_SHACL_ENTITY_OTHER = "http://special/ZZ_Other"; static instance = new SpecialSHACLSpecificationEntityRegistry(); /** * The Singleton's constructor should always be private to prevent direct * construction calls with the `new` operator. */ private constructor() { this.registry.set( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_OTHER, new SpecialSHACLSpecificationEntity( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_OTHER, "fa-solid fa-ellipsis", "Other", function(n3store:RdfStore, shapeUri:any):boolean { // this is in range if nothing else is in range let graph:StoreModel = new StoreModel(n3store); return ( !graph.hasTriple(factory.namedNode(shapeUri), SH.NODE, null) && !graph.hasTriple(factory.namedNode(shapeUri), SH.CLASS, null) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DATE) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DATE_TIME) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.GYEAR) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, GEOSPARQL.WKT_LITERAL) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.STRING) && !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, RDF.LANG_STRING) ); } ) ) this.registry.set( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_DATES, new SpecialSHACLSpecificationEntity( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_DATES, "fa-solid fa-calendar", "Date", function(n3store:RdfStore, shapeUri:any):boolean { let graph:StoreModel = new StoreModel(n3store); return ( graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DATE) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DATE_TIME) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.GYEAR) ); } ) ) this.registry.set( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_LOCATION, new SpecialSHACLSpecificationEntity( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_LOCATION, "fa-solid fa-map-location-dot", "Location", function(n3store:RdfStore, shapeUri:any):boolean { let graph:StoreModel = new StoreModel(n3store); return graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, GEOSPARQL.WKT_LITERAL) } ) ) this.registry.set( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_TEXT, new SpecialSHACLSpecificationEntity( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_TEXT, "fa-solid fa-font", "Text", function(n3store:RdfStore, shapeUri:any):boolean { let graph:StoreModel = new StoreModel(n3store); return ( graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.STRING) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, RDF.LANG_STRING) || // no datatype but we know it is a Literal ( graph.hasTriple(factory.namedNode(shapeUri), SH.NODE_KIND, SH.LITERAL) && ( !graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, null) || ( !graph.readSingleProperty(factory.namedNode(shapeUri), SH.DATATYPE)?.value.startsWith("http://www.w3.org/2001/XMLSchema#") && !graph.readSingleProperty(factory.namedNode(shapeUri), SH.DATATYPE)?.value.startsWith("http://www.opengis.net/ont/geosparql#") ) ) ) ); } ) ) this.registry.set( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_NUMBER, new SpecialSHACLSpecificationEntity( SpecialSHACLSpecificationEntityRegistry.SPECIAL_SHACL_ENTITY_NUMBER, "fa-solid fa-1", "Number", function(n3store:RdfStore, shapeUri:any):boolean { let graph:StoreModel = new StoreModel(n3store); return ( graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.BYTE) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DECIMAL) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.DOUBLE) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.FLOAT) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.INT) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.INTEGER) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.LONG) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.NONNEGATIVE_INTEGER) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.SHORT) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.UNSIGNED_BYTE) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.UNSIGNED_INT) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.UNSIGNED_LONG) || graph.hasTriple(factory.namedNode(shapeUri), SH.DATATYPE, XSD.UNSIGNED_SHORT) ); } ) ) } /** * The static method that controls the access to the singleton instance. * * This implementation let you subclass the Singleton class while keeping * just one instance of each subclass around. */ public static getInstance(): SpecialSHACLSpecificationEntityRegistry { if (!SpecialSHACLSpecificationEntityRegistry.instance) { SpecialSHACLSpecificationEntityRegistry.instance = new SpecialSHACLSpecificationEntityRegistry(); } return SpecialSHACLSpecificationEntityRegistry.instance; } public getRegistry(): Map<string,SpecialSHACLSpecificationEntity> { return this.registry; } }