sparnatural
Version:
Visual client-side SPARQL query builder and knowledge graph exploration tool
144 lines • 6.72 kB
JavaScript
import { DataFactory } from 'rdf-data-factory';
import { SHACLSpecificationEntry } from "./SHACLSpecificationEntry";
import { SHACLSpecificationEntity, SpecialSHACLSpecificationEntityRegistry } from "./SHACLSpecificationEntity";
import { SHACLSpecificationProperty } from "./SHACLSpecificationProperty";
import { Model, RDF, SH, ShaclModel, ShaclSparqlPostProcessor, StatisticsReader, XSD } from 'rdf-shacl-commons';
import { BaseRdfStore } from '../BaseRdfStore';
import { Dag } from '../../dag/Dag';
const factory = new DataFactory();
export class SHACLSpecificationProvider extends BaseRdfStore {
constructor(n3store, lang) {
super(n3store, lang);
// skolemize blank nodes
ShaclModel.skolemizeAnonymousPropertyShapes(this.store);
}
getAllSparnaturalEntities() {
const quadsArray = this.store.getQuads(null, RDF.TYPE, SH.NODE_SHAPE, null);
const itemsSet = new Set();
for (const quad of quadsArray) {
var nodeShapeId = quad.subject.value;
itemsSet.add(this.getEntity(nodeShapeId));
}
let items = SHACLSpecificationEntry.sort(Array.from(itemsSet));
return items.map(e => e.getId());
}
getEntitiesInDomainOfAnyProperty() {
// map to extract just the uri
return this.getInitialEntityList().map(e => e.getId());
}
getEntitiesTreeInDomainOfAnyProperty() {
// 1. get the entities that are in a domain of a property
let entities = this.getInitialEntityList();
// 2. add the children of these entities - recursively
// while the children of every entity is not found in our flat list of entity, continue adding children
while (!entities.every(entity => {
return entity.getChildren().every(child => {
// avoid testing deactivated shapes
return (this.isDeactivated(factory.namedNode(child))) || (entities.find(anotherEntity => anotherEntity.getId() === child) != undefined);
});
})) {
let childrenToAdd = [];
// for each entity in the initial list...
entities.forEach(entity => {
// foreach child of this entity...
entity.getChildren().forEach(child => {
// if this child is not in the list, add it
if (
// don't put deactivated shapes in the list
!this.isDeactivated(factory.namedNode(child))
&&
!entities.find(anotherEntity => anotherEntity.getId() === child)) {
childrenToAdd.push(this.getEntity(child));
}
});
});
childrenToAdd.forEach(p => entities.push(p));
}
// 3. complement the initial list with their parents
let disabledList = new Array();
while (!entities.every(entity => {
return entity.getParents().every(parent => {
return (entities.find(anotherEntity => anotherEntity.getId() === parent) != undefined);
});
})) {
let parentsToAdd = [];
entities.forEach(entity => {
entity.getParents().forEach(parent => {
if (!entities.find(anotherEntity => anotherEntity.getId() === parent)) {
parentsToAdd.push(this.getEntity(parent));
}
});
});
parentsToAdd.forEach(p => entities.push(p));
// also keep that as a disabled node
parentsToAdd.forEach(p => disabledList.push(p.getId()));
}
let dag = new Dag();
dag.initFromParentableAndIdAbleEntity(entities, disabledList);
let statisticsReader = new StatisticsReader(new Model(this.store));
// add count
dag.traverseBreadthFirst((node) => {
if (node.parents.length == 0) {
// if this is a root
// add a count to it
node.count = statisticsReader.getEntitiesCountForShape(factory.namedNode(node.payload.getId()));
}
else {
// otherwise make absolutely sure the count is undefined
node.count = undefined;
}
});
// sort tree
dag.sort(SHACLSpecificationEntity.compare);
return dag;
}
expandSparql(sparql, prefixes) {
let postProc = new ShaclSparqlPostProcessor(new ShaclModel(this.store));
return postProc.expandSparql(sparql, prefixes);
}
getLanguages() {
let shaclStoreModel = new ShaclModel(this.store);
return shaclStoreModel.readAllLanguages();
}
getEntity(uri) {
if (SpecialSHACLSpecificationEntityRegistry.getInstance().getRegistry().has(uri)) {
return SpecialSHACLSpecificationEntityRegistry.getInstance().getRegistry().get(uri);
}
return new SHACLSpecificationEntity(uri, this, this.store, this.lang);
}
getProperty(uri) {
if (!this.graph.hasTriple(factory.namedNode(uri), null, null)) {
console.warn("The requested property " + uri + " is unknown in the configuration. We cannot find any triple with this URI as subject.");
return undefined;
}
return new SHACLSpecificationProperty(uri, this, this.store, this.lang);
}
getInitialEntityList() {
const duplicatedNodeShapes = this.store.getQuads(null, SH.PROPERTY, null, null).map(triple => triple.subject);
let dedupNodeShapes = [...new Set(duplicatedNodeShapes)];
// remove from the initial list the NodeShapes that are marked with sh:deactivated
let that = this;
dedupNodeShapes = dedupNodeShapes.filter(node => {
return !that.isDeactivated(node);
});
// remove from the initial list the NodeShapes that are connected to only properties that Sparnatural will not use
// by checking the lenght of the list of properties we can make sure of that
dedupNodeShapes = dedupNodeShapes.filter(node => {
return this.getEntity(node.value).getProperties().length > 0;
});
var items = [];
for (const aNode of dedupNodeShapes) {
items.push(this.getEntity(aNode.value));
}
items = SHACLSpecificationEntry.sort(items);
return items;
}
/**
* @param node a NodeShape
* @returns true if the NodeShape is the subject of sh:deactivated true
*/
isDeactivated(node) {
return this.graph.hasTriple(node, SH.DEACTIVATED, factory.literal("true", XSD.BOOLEAN));
}
}
//# sourceMappingURL=SHACLSpecificationProvider.js.map