Skip to content

Commit 16ed377

Browse files
committed
First go at wrapping map
1 parent f1c4c67 commit 16ed377

File tree

3 files changed

+251
-0
lines changed

3 files changed

+251
-0
lines changed

src/TermWrapper.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { DataFactory, DatasetCore, Quad_Object, Quad_Subject, Term } from "
22
import type { ITermMapping } from "./type/ITermMapping.js"
33
import type { IValueMapping } from "./type/IValueMapping.js"
44
import { WrappingSet } from "./WrappingSet.js"
5+
import { WrappingMap } from "./WrappingMap.js"
56

67

78
export class TermWrapper {
@@ -92,6 +93,10 @@ export class TermWrapper {
9293
return new WrappingSet(this, p, valueMapping, termMapping)
9394
}
9495

96+
protected map<TKey, TValue>(p: string, valueMapping: IValueMapping<[TKey, TValue]>, termMapping: ITermMapping<[TKey, TValue]>): Map<TKey, TValue> {
97+
return new WrappingMap(this, p, valueMapping, termMapping)
98+
}
99+
95100
private static isQuadSubject(term: Term): term is Quad_Subject {
96101
return ["NamedNode", "BlankNode", "Quad", "Variable"].includes(term.termType)
97102
}

src/WrappingMap.ts

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { TermWrapper } from "./TermWrapper.js"
2+
import type { IValueMapping } from "./type/IValueMapping.js"
3+
import type { ITermMapping } from "./type/ITermMapping.js"
4+
import type { Quad, Quad_Object, Quad_Subject } from "@rdfjs/types"
5+
6+
export class WrappingMap<TKey, TValue> implements Map<TKey, TValue> {
7+
constructor(private readonly subject: TermWrapper, private readonly predicate: string, private readonly valueMapping: IValueMapping<[TKey, TValue]>, private readonly termMapping: ITermMapping<[TKey, TValue]>) {
8+
}
9+
10+
clear(): void {
11+
for (const q of this.matches) {
12+
this.subject.dataset.delete(q)
13+
}
14+
}
15+
16+
delete(k: TKey): boolean {
17+
const p = this.subject.factory.namedNode(this.predicate)
18+
19+
for (const entry of this) {
20+
if (entry[0] !== k) {
21+
continue
22+
}
23+
24+
this.subject.dataset.delete(
25+
this.subject.factory.quad(
26+
this.subject.term as Quad_Subject,
27+
p,
28+
this.termMapping(entry, this.subject.dataset, this.subject.factory)!.term as Quad_Object))
29+
30+
return true
31+
}
32+
33+
return false
34+
}
35+
36+
forEach(callback: (value: TValue, key: TKey, map: Map<TKey, TValue>) => void, thisArg?: any): void {
37+
for (const [key, value] of this) {
38+
callback.call(thisArg, value, key, this)
39+
}
40+
}
41+
42+
get(k: TKey): TValue | undefined {
43+
for (const [key, value] of this) {
44+
if (key !== k) {
45+
continue
46+
}
47+
48+
return value
49+
}
50+
51+
return undefined
52+
}
53+
54+
has(k: TKey): boolean {
55+
return this.get(k) !== undefined
56+
}
57+
58+
set(k: TKey, v: TValue): this {
59+
this.delete(k)
60+
this.add(k, v)
61+
62+
return this
63+
}
64+
65+
get size(): number {
66+
return [...this.matches].length
67+
}
68+
69+
set size(_: number) {
70+
throw new Error("not supported")
71+
}
72+
73+
* entries(): MapIterator<[TKey, TValue]> {
74+
for (const quad of this.matches) {
75+
yield this.valueMapping(new TermWrapper(quad.object, this.subject.dataset, this.subject.factory))
76+
}
77+
}
78+
79+
* keys(): MapIterator<TKey> {
80+
for (const [key,] of this) {
81+
yield key
82+
}
83+
}
84+
85+
* values(): MapIterator<TValue> {
86+
for (const [, value] of this) {
87+
yield value
88+
}
89+
}
90+
91+
[Symbol.iterator](): MapIterator<[TKey, TValue]> {
92+
return this.entries()
93+
}
94+
95+
get [Symbol.toStringTag](): string {
96+
return "WrappingMap"
97+
}
98+
99+
private get matches(): Iterable<Quad> {
100+
const p = this.subject.factory.namedNode(this.predicate)
101+
102+
return this.subject.dataset.match(this.subject.term, p)
103+
}
104+
105+
private add(k: TKey, v: TValue) {
106+
const p = this.subject.factory.namedNode(this.predicate)
107+
108+
this.subject.dataset.add(
109+
this.subject.factory.quad(
110+
this.subject.term as Quad_Subject,
111+
p,
112+
this.termMapping([k, v], this.subject.dataset, this.subject.factory)!.term as Quad_Object))
113+
}
114+
}

test/unit/wrapping_map.test.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { describe, it } from "node:test"
2+
import { TermWrapper } from "rdfjs-wrapper"
3+
import { DataFactory, Literal } from "n3"
4+
import { datasetFromRdf } from "./util/datasetFromRdf.js"
5+
import assert from "node:assert"
6+
7+
class Wrapper extends TermWrapper {
8+
public get dict(): Map<string, string> {
9+
return this.map(
10+
"p",
11+
({term}) => [
12+
(term as Literal).language,
13+
(term as Literal).value
14+
],
15+
([key, value], dataset, factory) =>
16+
new TermWrapper(factory.literal(value, key), dataset, factory)
17+
)
18+
}
19+
}
20+
21+
describe("Wrapping map", () => {
22+
describe("size", () => {
23+
it("get", () => {
24+
const rdf = `<s> <p> "o1"@en, "o2"@hu, "o3"@he .`
25+
const wrapper = new Wrapper("s", datasetFromRdf(rdf), DataFactory)
26+
27+
assert.strictEqual(wrapper.dict.size, 3)
28+
})
29+
it("set not supported", () => {
30+
const rdf = `<s> <p> <o> .`
31+
const wrapper = new Wrapper("s", datasetFromRdf(rdf), DataFactory)
32+
33+
assert.throws(() => {
34+
(wrapper.dict as any)["size"] = undefined!
35+
}, /^Error: not supported$/)
36+
})
37+
})
38+
39+
describe("general", () => {
40+
it("get", () => {
41+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
42+
const wrapper = new Wrapper("s", datasetFromRdf(rdf), DataFactory)
43+
44+
assert.strictEqual(wrapper.dict.get("en"), "o1")
45+
assert.strictEqual(wrapper.dict.get("fr"), "o2")
46+
})
47+
it("clear", () => {
48+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
49+
const dataset = datasetFromRdf(rdf)
50+
const wrapper = new Wrapper("s", dataset, DataFactory)
51+
52+
wrapper.dict.clear()
53+
54+
assert.strictEqual(dataset.size, 0)
55+
})
56+
it("delete reports positive", () => {
57+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
58+
const dataset = datasetFromRdf(rdf)
59+
const wrapper = new Wrapper("s", dataset, DataFactory)
60+
61+
assert.strictEqual(wrapper.dict.delete("en"), true)
62+
})
63+
it("delete reports negative", () => {
64+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
65+
const dataset = datasetFromRdf(rdf)
66+
const wrapper = new Wrapper("s", dataset, DataFactory)
67+
68+
assert.strictEqual(wrapper.dict.delete("XX"), false)
69+
})
70+
it("delete deletes", () => {
71+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
72+
const dataset = datasetFromRdf(rdf)
73+
const wrapper = new Wrapper("s", dataset, DataFactory)
74+
75+
wrapper.dict.delete("en")
76+
77+
assert.strictEqual(wrapper.dict.has("en"), false)
78+
})
79+
it("delete reports negative", () => {
80+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
81+
const dataset = datasetFromRdf(rdf)
82+
const wrapper = new Wrapper("s", dataset, DataFactory)
83+
84+
wrapper.dict.delete("XX")
85+
86+
assert.strictEqual(wrapper.dict.has("en"), true)
87+
assert.strictEqual(wrapper.dict.has("fr"), true)
88+
})
89+
it("forEach", () => {
90+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
91+
const dataset = datasetFromRdf(rdf)
92+
const wrapper = new Wrapper("s", dataset, DataFactory)
93+
94+
const actual = {} as any
95+
wrapper.dict.forEach((value, key) => {
96+
actual[key] = value
97+
})
98+
99+
assert.deepStrictEqual(actual, {en: "o1", fr: "o2"})
100+
})
101+
it("set", () => {
102+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
103+
const dataset = datasetFromRdf(rdf)
104+
const wrapper = new Wrapper("s", dataset, DataFactory)
105+
106+
wrapper.dict.set("en", "ox")
107+
108+
assert.deepStrictEqual(wrapper.dict.get("en"), "ox")
109+
})
110+
it("keys", () => {
111+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
112+
const dataset = datasetFromRdf(rdf)
113+
const wrapper = new Wrapper("s", dataset, DataFactory)
114+
115+
assert.deepStrictEqual([...wrapper.dict.keys()], ["en", "fr"])
116+
})
117+
it("values", () => {
118+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
119+
const dataset = datasetFromRdf(rdf)
120+
const wrapper = new Wrapper("s", dataset, DataFactory)
121+
122+
assert.deepStrictEqual([...wrapper.dict.values()], ["o1", "o2"])
123+
})
124+
it("toStringTag", () => {
125+
const rdf = `<s> <p> "o1"@en, "o2"@fr .`
126+
const dataset = datasetFromRdf(rdf)
127+
const wrapper = new Wrapper("s", dataset, DataFactory)
128+
129+
assert.strictEqual(wrapper.dict.toString(), "[object WrappingMap]")
130+
})
131+
})
132+
})

0 commit comments

Comments
 (0)