Mercurial > code > home > repos > streamed-graph
diff src/view_loader.ts @ 94:a5f53d397526
view: pick types to show at top-level
author | drewp@bigasterisk.com |
---|---|
date | Wed, 12 Jan 2022 22:09:20 -0800 |
parents | 955cde1550c3 |
children | 47d3b5a5bd5e |
line wrap: on
line diff
--- a/src/view_loader.ts Wed Jan 12 20:26:57 2022 -0800 +++ b/src/view_loader.ts Wed Jan 12 22:09:20 2022 -0800 @@ -1,5 +1,9 @@ // Load requested view and provide access to it -import { Store, Parser } from "n3"; +import { Store, Parser, Term, NamedNode, DataFactory, Util } from "n3"; +const Uri = DataFactory.namedNode; +const RDFS = Util.prefix("http://www.w3.org/2000/01/rdf-schema#"); +const RDF = Util.prefix("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); +const EX = Util.prefix("http://example.com/"); async function fetchAndParse(url: string): Promise<Store> { const store = new Store(); @@ -21,10 +25,65 @@ return store; } +function _singleValue(g: Store, s: Term, p: Term): Term { + const quads = g.getQuads(s, p, null, null); + const objs = new Set(quads.map((q) => q.object)); + if (objs.size == 0) { + throw new Error("no value for " + s.value + " " + p.value); + } else if (objs.size == 1) { + const obj = objs.values().next().value; + return obj as Term; + } else { + throw new Error("too many different values: " + JSON.stringify(quads)); + } +} + +function stringValue(g: Store, s: Term, p: Term): string { + const ret = _singleValue(g, s, p); + if (ret.termType != "Literal") { + throw new Error(`ret=${ret}`); + } + return ret.value as string; +} + +function uriValue(g: Store, s: Term, p: Term): NamedNode { + const ret = _singleValue(g, s, p); + if (ret.termType != "NamedNode") { + throw new Error(`ret=${ret}`); + } + + return ret; +} + +function labelOrTail(g: Store, uri: NamedNode): string { + let ret: string; + try { + ret = stringValue(g, uri, RDFS("label")); + } catch (e) { + const words = uri.value.split("/"); + ret = words[words.length - 1]; + } + if (!ret) { + ret = uri.value; + } + return ret; +} +function objects(g: Store, subj: NamedNode, pred: NamedNode): Term[] { + return g.getObjects(subj, pred, null); +} +function firstElem<E>(seq: Iterable<E>): E { + for (let e of seq) { + return e; + } + throw new Error("no elems"); +} + export class View { graph: Store; ready: Promise<null>; + viewRoot!: NamedNode; constructor(public url: string | "") { + (window as any).v = this; //debug this.graph = new Store(); this.ready = new Promise((res, rej) => { if (url) { @@ -36,8 +95,23 @@ res(null); } }); + this.ready.then(() => { + this.viewRoot = firstElem( + this.graph.getSubjects(RDF("type"), EX("View"), null) + ) as NamedNode; + }); } label() { - return "nicelabel"; + return labelOrTail(this.graph, Uri(this.url)); + } + // filtered+ordered list of types to show at the top level + typesToShow(typesPresent: NamedNode[]): NamedNode[] { + const ret: NamedNode[] = []; + for (let table of this.graph.getObjects(this.viewRoot, EX("table"), null)) { + const tableType = uriValue(this.graph, table, EX("showsType")); + ret.push(tableType); + } + ret.sort(); + return ret; } }