-
Notifications
You must be signed in to change notification settings - Fork 1
/
Reference.ts
132 lines (118 loc) · 3.78 KB
/
Reference.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { Reference as WikidataReference, ReferenceSnaks as wikidataReferenceSnaks, Snaks } from '@wmde/wikibase-datamodel-types';
import Snak from './Snak';
import arrayEqual, { arrayEqualWith } from './utils/arrayEqual';
import normalizeOutput from './utils/normalizeOutput';
import snakGenerator from './utils/snakGenerator';
import sha256 from './utils/hash';
/**
* Reduces an array of snaks into a object grouped by PropertyID
*
* @private
* @param {object} accumulator the accumulator object
* @param {Snak} value the Snak
* @returns {object} an Object with groups of snaks by ID
*/
function groupByPropertyReducer(accumulator: Record<string, Snaks[]>, value: Snaks): Record<string, Snaks[]> {
if (accumulator[value.property] === undefined) {
accumulator[value.property] = [];
}
accumulator[value.property].push(value);
return accumulator;
}
/**
* A class for References
*
* @class
*/
export default class Reference {
/** a place to store the internalID so that it does not change if the contents of the object changes */
private _internalID = '';
hash: string | undefined;
snaksOrder: string[] | undefined;
snaks: Snak[];
/**
*
* @param {WikidataReference} reference the Reference in json format
* @example
* const reference = new Reference(json);
*/
constructor(reference: WikidataReference) {
this.hash = reference.hash;
this.snaksOrder = reference['snaks-order'];
this.snaks = Object.values(reference.snaks)
.flat()
.map((snak) => snakGenerator(snak));
}
/**
* create a unique id for the Reference
*
* @returns {string} the id
*/
public get internalID(): string {
if (this._internalID === '') {
this._internalID = sha256(JSON.stringify(this.toJSON()));
}
return this._internalID;
}
/**
* @returns {WikidataReference} the Reference in a json format
* @example
* const json = reference.toJson();
*/
toJSON(): WikidataReference {
return normalizeOutput({
hash: this.hash,
snaks: this.snaks
.map((snak) => snak.toJSON())
.reduce<wikidataReferenceSnaks>(
(accumulator, value) => groupByPropertyReducer(accumulator, value),
{}
),
'snaks-order': this.snaksOrder
});
}
/**
* this function checks if References are equal
*
* @param {Reference} other the other snak
* @returns {boolean} true if the snaks are equal
* @example
* const reference = Reference.fromSnaks([
* new Snak('P123', 'Q42'),
* new Snak('P456', 'Q43')
* ]);
*
* const reference2 = Reference.fromSnaks([
* new Snak('P123', 'Q42')
* ]);
*
* reference.equals(reference2); // false
*/
equals(other: Reference): boolean {
return arrayEqualWith(this.snaks, other.snaks, (a: Snak, b: Snak) => a.equals(b))
&& arrayEqual(this.snaksOrder, other.snaksOrder)
&& this.hash === other.hash;
}
/**
* creates a new reference from snaks
*
* @static
* @param {Snak} snaks the snaks for the reference
* @returns {Reference} the reference objects
* @example
* const reference = Reference.fromSnaks([
* new Snak('P123', 'Q42'),
* new Snak('P456', 'Q43')
* ]);
*/
static fromSnaks(snaks: Snak[]): Reference {
return new Reference({
snaks: snaks
.map((snak) => snak.toJSON())
.reduce<wikidataReferenceSnaks>(
(accumulator, value) => groupByPropertyReducer(accumulator, value),
{}
)
});
}
}