view src/layout/ViewConfig.ts @ 128:5a1a79f54779

big rewrite
author drewp@bigasterisk.com
date Fri, 05 May 2023 21:26:36 -0700
parents 2e8fa3fec0c8
children cf642d395be4
line wrap: on
line source

import Immutable from "immutable"; // mostly using this for the builtin equals() testing, since NamedNode(x)!=NamedNode(x)
import { DataFactory, NamedNode, Quad_Predicate, Term } from "n3";
import { MultiStore } from "../MultiStore";
import { EX } from "./namespaces";
import { 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 Link {
  // If you display a subject u1 with a `pred` edge to u2, then treat u2 as an alias of u1.
  pred: NamedNode;
}

interface TableDesc {
  uri: NamedNode;
  primary: NamedNode;
  joins: NamedNode[];
  links: Link[];
}

// High-level guide to how to draw the page, independent of the graph data.
// Layout.ts turns this plus the actual graph data into a structure that's
// close to the final render.
export class ViewConfig {
  viewRoot: NamedNode; // this structure...
  graph: MultiStore; // in this graph...
  tables: TableDesc[] = []; // populates all the rest of these fields for use by Layout
  freeStatementsHidePred: Immutable.Set<Quad_Predicate> = Immutable.Set();

  constructor(graph: MultiStore, viewUri: NamedNode) {
    this.graph = graph;
    this.viewRoot = viewUri;
    // todo
    const here = "https://bigasterisk.com/lanscape/";
    if (this.viewRoot.value.startsWith(here)) {
      this.viewRoot = new NamedNode(this.viewRoot.value.slice(here.length));
    }
    // todo: might need to reread if graph changes
    this.read();
  }

  private read() {
    for (let table of this.graph.getObjects(this.viewRoot, EX("table"), null)) {
      const t = this.readTable(table);
      this.tables.push(t);
    }
    this.tables.sort();

    this.readHides();
  }

  private readHides() {
    for (let hideInstruction of this.graph.getObjects(
      this.viewRoot,
      EX("freeStatementsHide"),
      null
    )) {
      for (let pred of this.graph.getObjects(
        hideInstruction,
        EX("predicate"),
        null
      )) {
        this.freeStatementsHidePred = this.freeStatementsHidePred.add(
          pred as Quad_Predicate
        );
      }
    }
  }

  private readTable(table: Term): TableDesc {
    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();

    const links: Link[] = [];
    for (let linkDesc of this.graph.getObjects(table, EX("link"), null)) {
      links.push({
        pred: uriValue(this.graph, linkDesc, EX("predicate")),
      });
    }

    return {
      uri: table as NamedNode,
      primary: tableType,
      joins: joins,
      links: links,
    };
  }
}