graph-explorer
Version:
Graph Explorer can be used to explore and RDF graphs in SPARQL endpoints or on the web.
177 lines (162 loc) • 5.41 kB
text/typescript
import { cloneDeep, keyBy, map, each } from "lodash";
import { DataProvider, LinkElementsParams, FilterParams } from "../provider";
import {
Dictionary,
ClassModel,
LinkType,
ElementModel,
LinkModel,
LinkCount,
ElementIri,
ElementTypeIri,
LinkTypeIri,
} from "../model";
export class DemoDataProvider implements DataProvider {
constructor(
private allClasses: ClassModel[],
private allLinkTypes: LinkType[],
private allElements: Dictionary<ElementModel>,
private allLinks: LinkModel[]
) {}
private simulateNetwork<T>(result: T) {
const MEAN_DELAY = 200;
const cloned = cloneDeep(result);
// simulate exponential distribution
const delay = -Math.log(Math.random()) * MEAN_DELAY;
return new Promise<T>((resolve) => {
setTimeout(() => resolve(cloned), delay);
});
}
classTree() {
return this.simulateNetwork(this.allClasses);
}
classInfo(params: { classIds: ElementTypeIri[] }) {
const classIds = params.classIds || [];
return this.simulateNetwork(
this.allClasses.filter((cl) => classIds.indexOf(cl.id))
);
}
linkTypes() {
return this.simulateNetwork(this.allLinkTypes);
}
linkTypesInfo(params: { linkTypeIds: LinkTypeIri[] }): Promise<LinkType[]> {
const types = keyBy(params.linkTypeIds);
const linkTypes = this.allLinkTypes.filter((type) => types[type.id]);
return this.simulateNetwork(linkTypes);
}
elementInfo(params: {
elementIds: ElementIri[];
}): Promise<Dictionary<ElementModel>> {
const elements = params.elementIds
.map((elementId) => this.allElements[elementId])
.filter((element) => element !== undefined);
return this.simulateNetwork(keyBy(elements, (element) => element.id));
}
linksInfo(params: { elementIds: ElementIri[]; linkTypeIds: LinkTypeIri[] }) {
const nodes = keyBy(params.elementIds);
const types = keyBy(params.linkTypeIds);
const links = this.allLinks.filter(
(link) =>
types[link.linkTypeId] && nodes[link.sourceId] && nodes[link.targetId]
);
return this.simulateNetwork(links);
}
linkTypesOf(params: { elementId: ElementIri }) {
const counts: Dictionary<LinkCount> = {};
for (const link of this.allLinks) {
if (
link.sourceId === params.elementId ||
link.targetId === params.elementId
) {
const linkCount = counts[link.linkTypeId];
const isSource = link.sourceId === params.elementId;
if (linkCount) {
if (isSource) {
linkCount.outCount++;
} else {
linkCount.inCount++;
}
} else {
counts[link.linkTypeId] = isSource
? { id: link.linkTypeId, inCount: 0, outCount: 1 }
: { id: link.linkTypeId, inCount: 1, outCount: 0 };
}
}
}
return this.simulateNetwork(map(counts));
}
linkElements(params: LinkElementsParams): Promise<Dictionary<ElementModel>> {
// for sparql we have rich filtering features and we just reuse filter.
return this.filter({
refElementId: params.elementId,
refElementLinkId: params.linkId,
linkDirection: params.direction,
limit: params.limit,
offset: params.offset,
languageCode: "",
});
}
filter(params: FilterParams): Promise<Dictionary<ElementModel>> {
if (params.limit === undefined) {
params.limit = 100;
}
if (params.offset > 0) {
return Promise.resolve({});
}
let filtered: Dictionary<ElementModel> = {};
if (params.elementTypeId) {
each(this.allElements, (element) => {
if (element.types.indexOf(params.elementTypeId) >= 0) {
filtered[element.id] = element;
}
});
} else if (params.refElementId) {
const filteredLinks = params.refElementLinkId
? this.allLinks.filter(
(link) => link.linkTypeId === params.refElementLinkId
)
: this.allLinks;
const nodeId = params.refElementId;
for (const link of filteredLinks) {
let linkedElementId: string;
if (link.sourceId === nodeId && params.linkDirection !== "in") {
linkedElementId = link.targetId;
} else if (link.targetId === nodeId && params.linkDirection !== "out") {
linkedElementId = link.sourceId;
}
if (linkedElementId !== undefined) {
const linkedElement = this.allElements[linkedElementId];
if (linkedElement) {
filtered[linkedElement.id] = linkedElement;
}
}
}
} else if (params.text) {
filtered = this.allElements; // filtering by text is done below
} else {
return Promise.reject(
new Error("This type of filter is not implemented")
);
}
if (params.text) {
const filteredByText: Dictionary<ElementModel> = {};
const text = params.text.toLowerCase();
each(filtered, (element) => {
let found = false;
if (element.id.toLowerCase().indexOf(text) >= 0) {
found = true;
} else {
found = element.label.values.some(
(label) => label.value.toLowerCase().indexOf(text) >= 0
);
}
if (found) {
filteredByText[element.id] = element;
}
});
return this.simulateNetwork(filteredByText);
} else {
return this.simulateNetwork(filtered);
}
}
}