Mercurial > code > home > repos > streamed-graph
diff src/layout/Layout.ts @ 110:3cdbbd913f1d
table displays now just barely
author | drewp@bigasterisk.com |
---|---|
date | Fri, 18 Mar 2022 23:41:24 -0700 |
parents | 5e6840229a05 |
children | 4b33a479dc2f |
line wrap: on
line diff
--- a/src/layout/Layout.ts Fri Mar 18 12:00:33 2022 -0700 +++ b/src/layout/Layout.ts Fri Mar 18 23:41:24 2022 -0700 @@ -2,7 +2,7 @@ import Immutable from "immutable"; // mostly using this for the builtin equals() testing, since NamedNode(x)!=NamedNode(x) import { NamedNode, Quad, Store, Term } from "n3"; -import { rdf } from "./namespaces"; +import { rdf, rdfs } from "./namespaces"; import { uniqueSortedTerms } from "./rdf_value"; import { TableDesc, ViewConfig } from "./ViewConfig"; @@ -16,7 +16,8 @@ export interface AlignedTable { columnHeaders: ColumnHeader[]; - rows: (Term | null)[][]; // each row is 1 wider than columnHeaders since the 1st element is the subject for that row + rowHeaders: NamedNode[]; + rows: Term[][][]; } export interface PredRow { @@ -37,51 +38,72 @@ sections: (AlignedTable | FreeStatements)[]; } +interface ISP { + subj: NamedNode; + pred: NamedNode; +} +const makeSP = Immutable.Record<ISP>({ + subj: new NamedNode(""), + pred: new NamedNode(""), +}); + class AlignedTableBuilder { - columnPreds = Immutable.List<NamedNode>(); - subjRowIndices = Immutable.Map<NamedNode, number>(); - rows: (Term | null)[][] = []; + subjSet = Immutable.Set<NamedNode>(); + predSet = Immutable.Set<NamedNode>(); + cell = Immutable.Map<string, Immutable.Set<Term>>(); constructor( public rdfType: NamedNode /* plus join types, sort instructions */ ) {} addQuad(q: Quad) { + const subj = q.subject as NamedNode; const pred = q.predicate as NamedNode; - const omittedColumn = pred.equals(rdf.type); - if (!this.columnPreds.contains(pred) && !omittedColumn) { - this.columnPreds = this.columnPreds.push(pred); // this is putting cols in random order - this.rows.forEach((r) => r.push(null)); + this.subjSet = this.subjSet.add(subj); + this.predSet = this.predSet.add(pred); + + const key =subj.id+pred.id//makeSP({ subj, pred }); + const cur = this.cell.get(key, undefined); + const newval = + cur === undefined ? Immutable.Set([q.object]) : cur.add(q.object); + + this.cell = this.cell.set(key, newval); + } + + value(): AlignedTable { + let preds = uniqueSortedTerms(this.predSet); + const tagged = preds.map((p, i)=>{ + if (p.equals(rdf.type)) { + i=999; + } + if (p.equals(rdfs.label)) { + i=-1 + } + return {sort:i, val: p} + }) + tagged.sort((a,b)=>{ + return a.sort - b.sort; + }); + preds = tagged.map((e)=>e.val); + + // const omittedColumn = pred.equals(rdf.type); + const subjs = uniqueSortedTerms(this.subjSet); + const outputGrid: Term[][][] = []; + for (let subj of subjs) { + const row: Term[][] = []; + preds.forEach((pred) => { + const key = subj.id+pred.id;//makeSP({ subj, pred }); + const objs = this.cell.get(key, Immutable.Set<Term>([])); + const uniq = uniqueSortedTerms(objs); + console.log("cell objs", objs.size, uniq.length); + row.push(uniq); + }); + outputGrid.push(row); } - const predIndex = omittedColumn ? null : this.columnPreds.indexOf(pred); - let rowIndex = this.subjRowIndices.get(q.subject as NamedNode); - if (rowIndex === undefined) { - const newRow = new Array(1 + this.columnPreds.size).fill(null); - newRow[0] = q.subject; - this.rows.push(newRow); - rowIndex = this.rows.length - 1; - this.subjRowIndices = this.subjRowIndices.set( - q.subject as NamedNode, - rowIndex - ); - } - if (predIndex !== null) { - this.rows[rowIndex][1 + predIndex] = q.object; - } - } - - value(): AlignedTable { - this.rows.sort((a, b) => { - const uriA = (a[0] as NamedNode).value, - uriB = (b[0] as NamedNode).value; - return uriA.localeCompare(uriB); + const headers = preds.map((pred) => { + return { rdfType: this.rdfType, pred: pred }; }); - const headers = this.columnPreds - .map((pred) => { - return { rdfType: this.rdfType, pred: pred }; - }) - .toArray(); - return { columnHeaders: headers, rows: this.rows }; + return { columnHeaders: headers, rowHeaders: subjs, rows: outputGrid }; } } @@ -95,11 +117,13 @@ return Immutable.Set(typesToGather); } -function findSubjectsWithTypes(graph: Store, typesToGatherSet: UriSet): UriSet { +function findSubjectsWithTypes(graph: Store, typesToGather: UriSet): UriSet { const subjectsToGather: NamedNode[] = []; + const ft = typesToGather.toArray()[0]; graph.forEach( (q: Quad) => { - if (typesToGatherSet.contains(q.object as NamedNode)) { + if (q.object.equals(ft)) { + //typesToGather.has(q.object as NamedNode)) { subjectsToGather.push(q.subject as NamedNode); } }, @@ -142,22 +166,30 @@ export class Layout { constructor(public viewConfig?: ViewConfig) {} plan(graph: Store): LayoutResult { - const typesToGatherSet = findTypesNeededForTables(this.viewConfig); + const typesToTable = findTypesNeededForTables(this.viewConfig); - const subjectsToGatherSet = findSubjectsWithTypes(graph, typesToGatherSet); + const subjectsToTable = findSubjectsWithTypes(graph, typesToTable); const ungrouped: Quad[] = []; const vc = this.viewConfig; const table = vc && vc.tables.length > 0 - ? new AlignedTableBuilder(vc.tables[0].primary) + ? new AlignedTableBuilder(vc.tables[0].primary) //todo multiple tables : null; graph.forEach( (q: Quad) => { - if (!subjectsToGatherSet.contains(q.subject as NamedNode) || !table) { + let contains = false; + subjectsToTable.forEach((s) => { + if (s.equals(q.subject)) { + contains = true; + } + }); + + // if (subjectsToTable.has(q.subject as NamedNode) && table) { // not working + if (contains && table) { + table.addQuad(q); + } else { ungrouped.push(q); - } else { - table.addQuad(q); } }, null, @@ -167,6 +199,7 @@ ); const res: LayoutResult = { sections: [] }; if (table) { + console.log("table value"); res.sections.push(table.value()); } res.sections.push(freeStatmentsSection(ungrouped)); @@ -174,15 +207,6 @@ } } -// 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[];