Mercurial > code > home > repos > streamed-graph
changeset 102:ab7dca42afbd
rewrite ViewConfig
author | drewp@bigasterisk.com |
---|---|
date | Fri, 11 Mar 2022 23:19:35 -0800 |
parents | 76c1a29a328f |
children | f12feced00ce |
files | src/ViewConfig.test.ts src/ViewConfig.ts src/fetchAndParse.ts src/view_loader.ts |
diffstat | 4 files changed, 119 insertions(+), 84 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ViewConfig.test.ts Fri Mar 11 23:19:35 2022 -0800 @@ -0,0 +1,25 @@ +import { Util } from "n3"; +import { ViewConfig } from "./ViewConfig"; + +describe("ViewModel", () => { + it("gets a table description", async () => { + const vc = new ViewConfig(); + + await vc.readFromGraph(` + @prefix ex: <http://example.com/> . + @prefix demo: <http://example.com/demo/> . + @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + @prefix : <http://bigasterisk.com/netRoutes/ns#> . + + <> a ex:View ; rdfs:label "repos" . + <> ex:table demo:table1 . + demo:table1 + ex:primaryType :FilteredNic; + ex:joinType :Traffic . + `); + const NET = Util.prefix("http://bigasterisk.com/netRoutes/ns#"); + + expect(vc.tables[0].primary).toEqual(NET("FilteredNic")); + expect(vc.tables[0].joins).toEqual([NET("Traffic")]); + }); +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ViewConfig.ts Fri Mar 11 23:19:35 2022 -0800 @@ -0,0 +1,70 @@ +// Load requested view (rdf data) and provide access to it +import { DataFactory, NamedNode, Store } from "n3"; +import { fetchAndParse, n3Graph } from "./fetchAndParse"; +import { EX, RDF } from "./namespaces"; +import { labelOrTail, uriValue } from "./rdf_value"; +const Uri = DataFactory.namedNode; + +function firstElem<E>(seq: Iterable<E>): E { + for (let e of seq) { + return e; + } + throw new Error("no elems"); +} + +export interface TableDesc { + uri: NamedNode; + primary: NamedNode; + joins: NamedNode[]; +} + +export class ViewConfig { + graph: Store; + viewRoot!: NamedNode; + url?: string; + tables: TableDesc[] = []; + + constructor() { + this.graph = new Store(); + } + + async readFromUrl(url: string | "") { + if (!url) { + return; + } + await fetchAndParse(url, this.graph); + + this._read(); + } + + async readFromGraph(n3: string) { + this.graph = await n3Graph(n3); + this._read(); + } + + _read() { + this.viewRoot = firstElem( + this.graph.getSubjects(RDF("type"), EX("View"), null) + ) as NamedNode; + for (let table of this.graph.getObjects(this.viewRoot, EX("table"), null)) { + const tableType = uriValue(this.graph, table, EX("primaryType")); + const joins: NamedNode[] = []; + for (let joinType of this.graph.getObjects(table, EX("joinType"), null)) { + joins.push(joinType as NamedNode); + } + joins.sort(); + this.tables.push({ + uri: table as NamedNode, + primary: tableType, + joins: joins, + }); + } + this.tables.sort(); + } + + label(): string { + return this.url !== undefined + ? labelOrTail(this.graph, Uri(this.url)) + : "unnamed"; + } +}
--- a/src/fetchAndParse.ts Fri Feb 11 23:24:41 2022 -0800 +++ b/src/fetchAndParse.ts Fri Mar 11 23:19:35 2022 -0800 @@ -1,21 +1,27 @@ -import { Store, Parser } from "n3"; +import { Store, Parser, Quad, Prefixes } from "n3"; + +export async function fetchAndParse( + url: string, + store?: Store +): Promise<Store> { + const res = await fetch(url); + const body = await res.text(); + return n3Graph(body, store); +} -export async function fetchAndParse(url: string): Promise<Store> { - const store = new Store(); - const res = await fetch(url); - const body = await res.text(); - const parser = new Parser({ format: "N3" }); - await new Promise((done, rej) => { - parser.parse(body, (err, quad, prefixes) => { - if (err) { - throw err; - } - if (quad) { - store.addQuad(quad); - } else { - done(null); - } - }); +export async function n3Graph(n3: string, store?: Store): Promise<Store> { + if (store === undefined) { + store = new Store(); + } + + const parser = new Parser({ format: "N3" }); + return new Promise((res, rej) => { + parser.parse(n3, (error, quad: Quad, prefixes: Prefixes) => { + if (quad) { + store!.addQuad(quad); + } else { + res(store!); + } }); - return store; + }); }
--- a/src/view_loader.ts Fri Feb 11 23:24:41 2022 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -// Load requested view and provide access to it -import { Store, NamedNode, DataFactory } from "n3"; -import { fetchAndParse } from "./fetchAndParse"; -import { RDF, EX } from "./namespaces"; -import { labelOrTail, uriValue } from "./rdf_value"; -const Uri = DataFactory.namedNode; - -function firstElem<E>(seq: Iterable<E>): E { - for (let e of seq) { - return e; - } - throw new Error("no elems"); -} - -export interface TableDesc { - uri: NamedNode; - primary: NamedNode; - joins: NamedNode[]; -} - - -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) { - fetchAndParse(url).then((s2) => { - this.graph = s2; - res(null); - }); - } else { - res(null); - } - }); - this.ready.then(() => { - this.viewRoot = firstElem( - this.graph.getSubjects(RDF("type"), EX("View"), null) - ) as NamedNode; - }); - } - - label() { - return labelOrTail(this.graph, Uri(this.url)); - } - - // filtered+ordered list of types to show at the top level - toplevelTables(typesPresent: NamedNode[]): TableDesc[] { - const ret: TableDesc[] = []; - for (let table of this.graph.getObjects(this.viewRoot, EX("table"), null)) { - const tableType = uriValue(this.graph, table, EX("primaryType")); - const joins: NamedNode[] = []; - for (let joinType of this.graph.getObjects(table, EX("joinType"), null)) { - joins.push(joinType as NamedNode); - } - joins.sort(); - ret.push({ uri: table as NamedNode, primary: tableType, joins: joins }); - } - ret.sort(); - return ret; - } -}