wikibase-sdk
Version:
utils functions to query a Wikibase instance and simplify its results
192 lines • 7.48 kB
JavaScript
import { isPlainObject, typedEntries, uniq } from '../utils/utils.js';
import { parseSnak } from './parse_snak.js';
import { truthyPropertyClaims, nonDeprecatedPropertyClaims } from './rank.js';
/**
* Tries to replace wikidata deep snak object by a simple value
* e.g. a string, an entity Qid or an epoch time number
* Expects a single snak object
* Ex: entity.claims.P369[0]
*/
export function simplifySnak(snak, options = {}) {
const { keepTypes, keepSnaktypes, keepHashes } = parseKeepOptions(options);
let value;
const { datatype, datavalue, snaktype, hash } = snak;
if (datavalue) {
value = parseSnak(datatype, datavalue, options);
}
else {
if (snaktype === 'somevalue')
value = options.somevalueValue;
else if (snaktype === 'novalue')
value = options.novalueValue;
else
throw new Error('no datavalue or special snaktype found');
}
// No need to test keepHashes as it has no effect if neither
// keepQualifiers or keepReferences is true
if (keepTypes || keepSnaktypes || keepHashes) {
// When keeping qualifiers or references, the value becomes an object
// instead of a direct value
const valueObj = { value };
if (keepTypes)
valueObj.type = datatype;
if (keepSnaktypes)
valueObj.snaktype = snaktype;
if (keepHashes)
valueObj.hash = hash;
return valueObj;
}
else {
return value;
}
}
export function simplifyClaim(claim, options = {}) {
const { keepQualifiers, keepReferences, keepIds, keepTypes, keepSnaktypes, keepRanks } = parseKeepOptions(options);
const { mainsnak, rank } = claim;
const value = simplifySnak(mainsnak, options);
// No need to test keepHashes as it has no effect if neither
// keepQualifiers or keepReferences is true
if (!(keepQualifiers || keepReferences || keepIds || keepTypes || keepSnaktypes || keepRanks)) {
return value;
}
// When keeping other attributes, the value becomes an object instead of a direct value
let valueObj = { value };
if (isPlainObject(value) && 'value' in value) {
valueObj = value;
}
else {
valueObj = { value };
}
if (keepRanks)
valueObj.rank = rank;
if (keepQualifiers) {
valueObj.qualifiers = simplifyQualifiers(claim.qualifiers, options);
}
if (keepReferences) {
claim.references = claim.references || [];
valueObj.references = simplifyReferences(claim.references, options);
}
if (keepIds)
valueObj.id = claim.id;
return valueObj;
}
export function simplifyClaims(claims, options = {}) {
const { propertyPrefix } = options;
const simplified = {};
for (let [propertyId, propertyArray] of typedEntries(claims)) {
if (propertyPrefix) {
propertyId = propertyPrefix + ':' + propertyId;
}
simplified[propertyId] = simplifyPropertyClaims(propertyArray, options);
}
return simplified;
}
export function simplifyPropertyClaims(propertyClaims, options = {}) {
// Avoid to throw on empty inputs to allow to simplify claims array
// without having to know if the entity as claims for this property
// Ex: simplifyPropertyClaims(entity.claims.P124211616)
if (propertyClaims == null || propertyClaims.length === 0)
return [];
const { keepNonTruthy, keepNonDeprecated } = parseKeepOptions(options);
const { minTimePrecision } = options;
if (keepNonDeprecated) {
propertyClaims = nonDeprecatedPropertyClaims(propertyClaims);
}
else if (!(keepNonTruthy)) {
propertyClaims = truthyPropertyClaims(propertyClaims);
}
const simplifiedArray = [];
for (const claim of propertyClaims) {
const isDroppedClaim = timeSnakPrecisionIsTooLow(claim.mainsnak, minTimePrecision);
if (!isDroppedClaim) {
const simplifiedClaim = simplifyClaim(claim, options);
// Filter-out novalue and somevalue claims,
// unless a novalueValue or a somevalueValue is passed in options
// Considers null as defined
if (simplifiedClaim !== undefined)
simplifiedArray.push(simplifiedClaim);
}
}
// Deduplicate values unless we return a rich value object
if (simplifiedArray[0] && typeof simplifiedArray[0] !== 'object') {
return uniq(simplifiedArray);
}
else {
return simplifiedArray;
}
}
export function simplifySnaks(snaks = {}, options = {}) {
const { propertyPrefix } = options;
const simplified = {};
for (let [propertyId, propertyArray] of typedEntries(snaks)) {
if (propertyPrefix) {
propertyId = propertyPrefix + ':' + propertyId;
}
simplified[propertyId] = simplifyPropertySnaks(propertyArray, options);
}
return simplified;
}
export function simplifyPropertySnaks(propertySnaks, options = {}) {
if (propertySnaks == null || propertySnaks.length === 0)
return [];
const { minTimePrecision } = options;
const simplifiedArray = [];
for (const snak of propertySnaks) {
const isDroppedSnak = timeSnakPrecisionIsTooLow(snak, minTimePrecision);
if (!isDroppedSnak) {
const simplifiedSnak = simplifySnak(snak, options);
// Filter-out novalue and somevalue snaks,
// unless a novalueValue or a somevalueValue is passed in options
// Considers null as defined
if (simplifiedSnak !== undefined)
simplifiedArray.push(simplifiedSnak);
}
}
// Deduplicate values unless we return a rich value object
if (simplifiedArray[0] && typeof simplifiedArray[0] !== 'object') {
return uniq(simplifiedArray);
}
else {
return simplifiedArray;
}
}
export function simplifyQualifiers(qualifiers, options = {}) {
return simplifySnaks(qualifiers, options);
}
export function simplifyPropertyQualifiers(propertyQualifiers, options = {}) {
return simplifyPropertySnaks(propertyQualifiers, options);
}
export function simplifyQualifier(qualifier, options = {}) {
return simplifySnak(qualifier, options);
}
export function simplifyReferences(references, options = {}) {
return references.map(reference => simplifyReference(reference, options));
}
export function simplifyReference(reference, options = {}) {
const snaks = simplifySnaks(reference.snaks, options);
if (options.keepHashes)
return { snaks, hash: reference.hash };
else
return snaks;
}
/** @deprecated use the new function name simplifyReference instead */
export const simplifyReferenceRecord = simplifyReference;
const keepOptions = ['keepQualifiers', 'keepReferences', 'keepIds', 'keepHashes', 'keepTypes', 'keepSnaktypes', 'keepRanks', 'keepRichValues'];
const parseKeepOptions = (options = {}) => {
if (options.keepAll) {
for (const optionName of keepOptions) {
if (options[optionName] == null)
options[optionName] = true;
}
}
return options;
};
function timeSnakPrecisionIsTooLow(snak, minTimePrecision) {
if (minTimePrecision == null)
return false;
if (snak.datatype !== 'time' || snak.snaktype !== 'value')
return false;
const { value } = snak.datavalue;
return value.precision < minTimePrecision;
}
//# sourceMappingURL=simplify_claims.js.map