comparison 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
comparison
equal deleted inserted replaced
102:ab7dca42afbd 103:f12feced00ce
1 // Organize graph data into tables (column orders, etc) for the view layer.
2
3 import Immutable from "immutable"; // mostly using this for the builtin equals() testing, since NamedNode(x)!=NamedNode(x)
4 import {
5 DataFactory,
6 NamedNode,
7 Quad,
8 Quad_Object,
9 Store,
10 Term,
11 Util,
12 } from "n3";
13 import { ViewConfig } from "./ViewConfig";
14
15 const { namedNode } = DataFactory;
16
17 // // import ns from 'n3/src/IRIs';
18 // // const { rdf } = ns;
19
20 type UriSet = Immutable.Set<NamedNode>;
21 export type TypeToSubjs = Immutable.Map<NamedNode, UriSet>;
22
23 // https://github.com/rdfjs/N3.js/issues/265
24 if ((NamedNode.prototype as any).hashCode === undefined) {
25 (NamedNode.prototype as any).hashCode = () => 0;
26 }
27
28 interface ColumnHeader {
29 rdfType?: NamedNode; // could be more than one column that introduces an rdf:type for a join
30 pred: NamedNode;
31 }
32 interface AlignedTable {
33 columnHeaders: ColumnHeader[];
34 rows: (Term | null)[][]; // each row is 1 wider than columnHeaders since the 1st element is the subject for that row
35 }
36 interface FreeStatements {
37 statements: Quad[];
38 }
39 export interface LayoutResult {
40 sections: (AlignedTable | FreeStatements)[];
41 }
42
43 export class Layout {
44 constructor(public viewConfig?: ViewConfig) {}
45 plan(graph: Store): LayoutResult {
46 const ungrouped: Quad[] = [];
47
48 graph.forEach(
49 (q: Quad) => {
50 ungrouped.push(q);
51 },
52 null,
53 null,
54 null,
55 null
56 );
57 return { sections: [{ statements: ungrouped }] };
58 }
59 }
60
61 // function getType(graph: Store, subj: NamedNode): NamedNode | null {
62 // let subjType: NamedNode | null = null;
63
64 // graph.forObjects(
65 // (o: Quad_Object) => {
66 // subjType = o as NamedNode;
67 // },
68 // subj,
69 // rdf.type,
70 // null
71 // );
72 // return subjType;
73 // }
74
75 // // When there are multiple types, an arbitrary one is used.
76 // export function groupByRdfType(
77 // graph: Store
78 // ): {
79 // byType: TypeToSubjs;
80 // typesPresent: NamedNode[];
81 // untypedSubjs: NamedNode[];
82 // } {
83 // let byType: TypeToSubjs = Immutable.Map();
84 // let untyped: UriSet = Immutable.Set(); // subjs
85 // const internSubjs = new Map<string, NamedNode>();
86 // graph.forEach(
87 // (q) => {
88 // if (!Util.isNamedNode(q.subject)) {
89 // throw new Error("unsupported " + q.subject.value);
90 // }
91 // const subj = q.subject as NamedNode;
92
93 // const subjType = getType(graph, subj);
94
95 // if (subjType !== null) {
96 // // (subj, rdf:type, subjType) in graph
97 // const oldKeys = Array.from(byType.keys());
98 // const oldVal = byType.get(subjType, Immutable.Set<NamedNode>());
99 // const newVal = oldVal.add(subj);
100 // byType = byType.set(subjType, newVal);
101 // } else {
102 // untyped = untyped.add(subj);
103 // }
104 // },
105 // null,
106 // null,
107 // null,
108 // null
109 // );
110
111 // const typesPresent = Array.from(byType.keys());
112 // typesPresent.sort();
113
114 // const untypedSubjs = Array.from(untyped.values());
115 // untypedSubjs.sort();
116 // return {
117 // byType: byType,
118 // typesPresent: typesPresent,
119 // untypedSubjs: untypedSubjs,
120 // };
121 // }
122
123 // export function predsForSubj(graph: Store, typeUri: NamedNode): NamedNode[] {
124 // const predsSet: Set<NamedNode> = new Set();
125 // graph.forEach(
126 // (q: Quad) => {
127 // predsSet.add(q.predicate as NamedNode);
128 // },
129 // typeUri,
130 // null,
131 // null,
132 // null
133 // );
134 // const preds = Array.from(predsSet.values());
135 // preds.sort();
136 // return preds;
137 // }
138
139 // interface ISP {
140 // subj: NamedNode;
141 // pred: NamedNode;
142 // }
143 // const SP = Immutable.Record<ISP>({
144 // subj: new NamedNode(""),
145 // pred: new NamedNode(""),
146 // });
147
148 // // One table of rows with a common rdf:type.
149 // export class MultiSubjsTypeBlockLayout {
150 // subjs: NamedNode[];
151 // preds: NamedNode[];
152 // graphCells: Immutable.Map<ISP, Immutable.Set<Term>>;
153 // constructor(graph: Store, byType: TypeToSubjs, table: TableDesc) {
154 // const subjSet = byType.get(table.primary);
155 // this.subjs = subjSet ? Array.from(subjSet) : [];
156 // this.subjs.sort();
157
158 // let preds = Immutable.Set<NamedNode>();
159
160 // this.graphCells = Immutable.Map<ISP, Immutable.Set<Term>>().withMutations(
161 // (mutGraphCells) => {
162 // this.subjs.forEach((subj: NamedNode) => {
163 // graph.forEach(
164 // (q: Quad) => {
165 // if (!Util.isNamedNode(q.predicate)) {
166 // throw new Error();
167 // }
168
169 // const pred = q.predicate as NamedNode;
170 // if (pred.equals(rdf.type)) {
171 // // the whole block is labeled with the type
172 // return;
173 // }
174 // preds = preds.add(pred);
175 // const cellKey = this.makeCellKey(subj, pred);
176 // mutGraphCells.set(
177 // cellKey,
178 // mutGraphCells.get(cellKey, Immutable.Set<Term>()).add(q.object)
179 // );
180 // },
181 // subj,
182 // null,
183 // null,
184 // null
185 // );
186 // });
187 // }
188 // );
189 // this.preds = Array.from(preds);
190 // this.preds.splice(this.preds.indexOf(rdf.type), 1);
191 // // also pull out label, which should be used on 1st column
192 // this.preds.sort();
193 // }
194
195 // makeCellKey(subj: NamedNode, pred: NamedNode): ISP {
196 // return SP({
197 // subj: subj,
198 // pred: pred,
199 // });
200 // }
201 // }