-
Notifications
You must be signed in to change notification settings - Fork 1
/
Statement.ts
160 lines (137 loc) · 4.84 KB
/
Statement.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import { Statement as wikidataStatement, Qualifiers as wikidataQualifiers } from '@wmde/wikibase-datamodel-types';
import Reference from './Reference';
import Snak from './Snak';
import { Snaks } from './types/SnaksType';
import { PString } from './types/strings';
import arrayEqual, { arrayEqualWith } from './utils/arrayEqual';
import normalizeOutput from './utils/normalizeOutput';
import snakGenerator from './utils/snakGenerator';
import sha256 from './utils/hash';
/**
* @class
*/
export default class Statement {
/** a place to store the internalID so that it does not change if the contents of the object changes */
private _internalID = '';
id: string | undefined;
type: 'statement';
rank: 'normal' | 'preferred' | 'deprecated';
mainsnak: Snaks;
references: Reference[];
qualifiers: Snak[];
qualifiersOrder: string[];
/**
*
* @param {wikidataStatement} statement the statement in a json format
* @example
* const statement = new Statement(json);
*/
constructor(statement: wikidataStatement) {
this.id = statement.id;
this.type = statement.type;
this.qualifiers = Object.values(statement.qualifiers ?? {})
.flat()
.map((snak) => snakGenerator(snak));
this.qualifiersOrder = statement['qualifiers-order'] ?? [];
this.rank = statement.rank;
this.mainsnak = snakGenerator(statement.mainsnak);
this.references = statement.references
? Object.values(statement.references).map((reference) => new Reference(reference))
: [];
}
/**
* gets the unique hash of the statement
*
* @returns {string} the id
*/
public get internalID(): string {
if (this._internalID === '') {
this._internalID = sha256(JSON.stringify(this.toJSON()));
}
return this._internalID;
}
/**
* gets the property of the statement
*
* @returns {PString | undefined} the property of the statement
* @example
* const property = statement.property;
*/
public get property(): PString | undefined {
return this.mainsnak.property;
}
/**
* @returns {wikidataStatement} the statement in a json format
* @example
* const json = statement.toJson();
*/
toJSON(): wikidataStatement {
const references = this.references.map((reference) => reference.toJSON());
const qualifiers = this.qualifiers
.map((qualifier) => qualifier.toJSON())
.reduce<wikidataQualifiers>(
(accumulator, value) => {
if (accumulator[value.property] === undefined) {
accumulator[value.property] = [];
}
accumulator[value.property].push(value);
return accumulator;
},
{}
);
return normalizeOutput({
mainsnak: this.mainsnak.toJSON(),
type: this.type,
qualifiers: Object.keys(qualifiers).length === 0 ? undefined : qualifiers,
'qualifiers-order': this.qualifiersOrder.length === 0 ? undefined : this.qualifiersOrder,
id: this.id,
rank: this.rank,
references: references.length === 0 ? undefined : references
}) as wikidataStatement;
}
/**
* creates a statement from a snak
*
* @param {Snak} snak the snak for the statement
* @returns {Statement} the statement
* @example
* const statement = Statement.fromSnak(snak);
*/
static fromSnak(snak: Snak): Statement {
return new Statement({
mainsnak: snak.toJSON(),
type: 'statement',
rank: 'normal'
});
}
/**
*
* @param {Statement} other the other statement
* @returns {boolean} if the two statements are equal
* @example
* if (statement1.equals(statement2)) {
* // do something
* }
*/
equals(other: Statement): boolean {
const idEqual = this.id === other.id;
const typeEqual = this.type === other.type;
const rankEqual = this.rank === other.rank;
const qualifiersOrderEqual = arrayEqual(this.qualifiersOrder, other.qualifiersOrder);
// @ts-expect-error
const snakEqual = this.mainsnak.datatype === other.mainsnak.datatype && this.mainsnak.equals(other.mainsnak);
const referencesEqual = arrayEqualWith(
this.references,
other.references,
(a: Reference, b: Reference) => a.equals(b)
);
const qualifiersEqual = arrayEqualWith(this.qualifiers, other.qualifiers, (a: Snak, b: Snak) => a.equals(b));
return idEqual
&& typeEqual
&& rankEqual
&& qualifiersOrderEqual
&& snakEqual
&& referencesEqual
&& qualifiersEqual;
}
}