Mercurial > code > home > repos > streamed-graph
diff src/Layout.ts @ 103:f12feced00ce
WIP rewriting Layout
author | drewp@bigasterisk.com |
---|---|
date | Sat, 12 Mar 2022 00:42:00 -0800 |
parents | src/tabulate.ts@26c55d5d5202 |
children | 1aea03d306af |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Layout.ts Sat Mar 12 00:42:00 2022 -0800 @@ -0,0 +1,201 @@ +// Organize graph data into tables (column orders, etc) for the view layer. + +import Immutable from "immutable"; // mostly using this for the builtin equals() testing, since NamedNode(x)!=NamedNode(x) +import { + DataFactory, + NamedNode, + Quad, + Quad_Object, + Store, + Term, + Util, +} from "n3"; +import { ViewConfig } from "./ViewConfig"; + +const { namedNode } = DataFactory; + +// // import ns from 'n3/src/IRIs'; +// // const { rdf } = ns; + +type UriSet = Immutable.Set<NamedNode>; +export type TypeToSubjs = Immutable.Map<NamedNode, UriSet>; + +// https://github.com/rdfjs/N3.js/issues/265 +if ((NamedNode.prototype as any).hashCode === undefined) { + (NamedNode.prototype as any).hashCode = () => 0; +} + +interface ColumnHeader { + rdfType?: NamedNode; // could be more than one column that introduces an rdf:type for a join + pred: NamedNode; +} +interface AlignedTable { + columnHeaders: ColumnHeader[]; + rows: (Term | null)[][]; // each row is 1 wider than columnHeaders since the 1st element is the subject for that row +} +interface FreeStatements { + statements: Quad[]; +} +export interface LayoutResult { + sections: (AlignedTable | FreeStatements)[]; +} + +export class Layout { + constructor(public viewConfig?: ViewConfig) {} + plan(graph: Store): LayoutResult { + const ungrouped: Quad[] = []; + + graph.forEach( + (q: Quad) => { + ungrouped.push(q); + }, + null, + null, + null, + null + ); + return { sections: [{ statements: ungrouped }] }; + } +} + +// function getType(graph: Store, subj: NamedNode): NamedNode | null { +// let subjType: NamedNode | null = null; + +// graph.forObjects( +// (o: Quad_Object) => { +// subjType = o as NamedNode; +// }, +// subj, +// rdf.type, +// null +// ); +// return subjType; +// } + +// // When there are multiple types, an arbitrary one is used. +// export function groupByRdfType( +// graph: Store +// ): { +// byType: TypeToSubjs; +// typesPresent: NamedNode[]; +// untypedSubjs: NamedNode[]; +// } { +// let byType: TypeToSubjs = Immutable.Map(); +// let untyped: UriSet = Immutable.Set(); // subjs +// const internSubjs = new Map<string, NamedNode>(); +// graph.forEach( +// (q) => { +// if (!Util.isNamedNode(q.subject)) { +// throw new Error("unsupported " + q.subject.value); +// } +// const subj = q.subject as NamedNode; + +// const subjType = getType(graph, subj); + +// if (subjType !== null) { +// // (subj, rdf:type, subjType) in graph +// const oldKeys = Array.from(byType.keys()); +// const oldVal = byType.get(subjType, Immutable.Set<NamedNode>()); +// const newVal = oldVal.add(subj); +// byType = byType.set(subjType, newVal); +// } else { +// untyped = untyped.add(subj); +// } +// }, +// null, +// null, +// null, +// null +// ); + +// const typesPresent = Array.from(byType.keys()); +// typesPresent.sort(); + +// const untypedSubjs = Array.from(untyped.values()); +// untypedSubjs.sort(); +// return { +// byType: byType, +// typesPresent: typesPresent, +// untypedSubjs: untypedSubjs, +// }; +// } + +// export function predsForSubj(graph: Store, typeUri: NamedNode): NamedNode[] { +// const predsSet: Set<NamedNode> = new Set(); +// graph.forEach( +// (q: Quad) => { +// predsSet.add(q.predicate as NamedNode); +// }, +// typeUri, +// null, +// null, +// null +// ); +// const preds = Array.from(predsSet.values()); +// preds.sort(); +// return preds; +// } + +// interface ISP { +// subj: NamedNode; +// pred: NamedNode; +// } +// const SP = Immutable.Record<ISP>({ +// subj: new NamedNode(""), +// pred: new NamedNode(""), +// }); + +// // One table of rows with a common rdf:type. +// export class MultiSubjsTypeBlockLayout { +// subjs: NamedNode[]; +// preds: NamedNode[]; +// graphCells: Immutable.Map<ISP, Immutable.Set<Term>>; +// constructor(graph: Store, byType: TypeToSubjs, table: TableDesc) { +// const subjSet = byType.get(table.primary); +// this.subjs = subjSet ? Array.from(subjSet) : []; +// this.subjs.sort(); + +// let preds = Immutable.Set<NamedNode>(); + +// this.graphCells = Immutable.Map<ISP, Immutable.Set<Term>>().withMutations( +// (mutGraphCells) => { +// this.subjs.forEach((subj: NamedNode) => { +// graph.forEach( +// (q: Quad) => { +// if (!Util.isNamedNode(q.predicate)) { +// throw new Error(); +// } + +// const pred = q.predicate as NamedNode; +// if (pred.equals(rdf.type)) { +// // the whole block is labeled with the type +// return; +// } +// preds = preds.add(pred); +// const cellKey = this.makeCellKey(subj, pred); +// mutGraphCells.set( +// cellKey, +// mutGraphCells.get(cellKey, Immutable.Set<Term>()).add(q.object) +// ); +// }, +// subj, +// null, +// null, +// null +// ); +// }); +// } +// ); +// this.preds = Array.from(preds); +// this.preds.splice(this.preds.indexOf(rdf.type), 1); +// // also pull out label, which should be used on 1st column +// this.preds.sort(); +// } + +// makeCellKey(subj: NamedNode, pred: NamedNode): ISP { +// return SP({ +// subj: subj, +// pred: pred, +// }); +// } +// }