view src/view_loader.ts @ 97:26c55d5d5202

WIP on views & joins
author drewp@bigasterisk.com
date Fri, 11 Feb 2022 20:27:02 -0800
parents 47d3b5a5bd5e
children
line wrap: on
line source

// 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;
  }
}