Modul:SimpleDataAccess
Vorlagenprogrammierung | Diskussionen | Lua | Unterseiten | |||
Modul | Deutsch | English
|
Modul: | Dokumentation |
Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus
--[=[ SimpleDataAccess 2022-07-03
Data Management Module for simplified Access from Within Other Modules:
All functions return first values only.
Author: Vollbracht
* qualifyingValue(statement, propQual) wikiData first qualifier value
* statementQualOrMainSnak(qualifier, property, propQual) first value
* MainSnakValue(qualifier, property) wikiData first main snack value
* indirectMSValue(qualifier, properties) wikiData first main snack value
* qualifiersLineup(qualifier, property) sequence of wikiData qualifiers
*
]=]
--Module globals
local _, GeneralTime = pcall(require, "Modul:Wikidata/Time")
local Time = GeneralTime.service
local service = {}
--------------------------- local functions -----------------------------
--[[
statements(object, property, all)
Have calling functions work with all of:
params to call an mw.wikibase statement fetch function,
wikibase entity and param to call its statement fetch method
allready fetched statement table.
single statement and property to access qualifiers
Functions that are known to have one properties set type only should use the
applying statement fetch function or method directly instead!
]]
local statements = function(object, property, all)
if type(object) == 'string' then
if not property then return nil end
if all then return mw.wikibase.getAllStatements(object, property) end
return mw.wikibase.getBestStatements(object, property)
end
if not object then return nil end
if object.getBestStatements then
if not property then return nil end
if all then return object:getAllStatements(property) end
return object:getBestStatements(property)
end
if object[property] then object = object[property] end
if object[1] then return object end
return nil
end
--[[
unwrap(<source>)
object value of a given source: this function simplifies by ignoring a lot
like language e.g.
this function drops all object values if table and not
* time
* text
* id
enhance this function at will:
process additional table object values as follows:
return <return object>, 'f'
have <return object>:format(fmtString)
or
return <return object>, <new type>
enhance service.SnakValue(...) and getList(...) then as well
parameters:
source mainsnak, mainsnak.datavalue, mainsnak.datavalue.value or
qualifier item
returns: (value text, value time, value id, simple type value or nil) and
type of value:
f if formatable
id if Q123... - string
result of format(value) in all other cases
]]
local unwrap = function(source)
if not source then return nil end
if source.mainsnak then
if source.mainsnak.datavalue then
source = source.mainsnak.datavalue.value
else mw.logObject(source) end
elseif source.datavalue then source = source.datavalue.value
elseif source.value then source = source.value end
if type(source) == 'table' then
if source.text then return source.text, 'string' end
if source.time then return Time:new(source), 'f' end
if source.id then return source.id, 'id' end
return nil
end
return source, type(source)
end
local function get1stNamedAs(statement, fallback)
local q = statement.qualifiers
if not q then return fallback end
local n = q.P1932
if not n then n = q.P1810 end
if not n then return fallback end
return n[1]["datavalue"]["value"]
end
--[[
SnakValue
text value of a given value
parameters:
value as of mainsnak.datavalue.value
t as of value, t = unwrap(value) if already unwrapped
additional (optional, variant) for use with t = 'f' or 'id'
returns: simple data value:
value (if no table), value.text, or label of value.id
]]
service.SnakValue = function(value, t, additional)
if not t then value, t = unwrap(value) end
if not value then return '' end
if t == 'f' then return value:format(additional) end
if t == 'id' then
local label = mw.wikibase.getLabel(value)
if label then return label end
if additional then return get1stNamedAs(additional, value) end
return value
end
return value
end
local get1stStatement = function(qualifier, property, test)
if qualifier == nil or qualifier == "" then
mw.log('no qualifier given for statement retrival')
return nil
end
local statementList = statements(qualifier, property)
if test then
if not statementList or #statementList == 0 then
mw.logObject(statementList, qualifier .. '.' .. property)
local all = nil
if type(qualifier) == "table" then
all = qualifier:getAllStatements(property)
mw.logObject(all, 'all of this')
else
all = mw.wikibase.getAllStatements(qualifier, property)
mw.logObject(all, 'all of ' .. qualifier)
end
if not all or #all == 0 then
all = mw.wikibase.getEntity(qualifier)
mw.logObject(all, 'all of entity: ' .. qualifier)
end
else mw.logObject(statementList) end
end
if statementList and type(statementList) == "table" then
local result = statementList[1]
if type(result) == "table" then
return result
end
end
if test then mw.log('no data: (' .. qualifier .. '.' .. property .. '):') end
return nil
end
-- deprecated; use Modul:Wikidata/Time or Modul:Time instead -->
service.time = { MATCHING = Time.MATCHING, PRECISIONLEVEL = Time.PRECISIONLEVEL,
DEFAULTFORMAT = Time.DEFAULTFORMAT, lessthan = Time.lessthan,
format = Time.format, timify = Time.timify
}
function service.time:new(source)
mw.log('indirect (avoid!)')
return Time:new(source)
end
-- <--deprecated--
--[[
getSnaks(object, <P...>, <all>)
snak values table:
either all main snaks of a wikidata object defined by property
or all snaks of a statement qualifying its mainsnak by property
parameters:
object: wikidata source:
qualifier string <Q...> of a wikidata object or
statement table as of mw.wikibase.getBestStatements or
single statement beeing source for qualifying snaks
property: defining source statement qualifier string <P...> for
getBestStatements or
filtering qualifying snaks
ignored if source object is table {[1]=..., [2]= ..., ...}
all: use getAllStatements instead of getBestStatements
ignored if source object is table
]]
service.getSnaks = function(object, property, all)
object = statements(object, property, all)
if not object then return nil end
if not object[1] then return nil end
local result = {}
for _, v in ipairs(object) do
local r = unwrap(v)
if r then table.insert(result, r) end
end
return result
end
--[[
SnakList(<object>, <property>, <all>, <value type>, <separator string>)
statement mainsnak values comma or separator string separated
parameters:
object: wikidata source:
qualifier string <Q...> of a wikidata object or
statement table as of mw.wikibase.getBestStatements or
single statement beeing source for qualifying snaks
property: defining source statement qualifier string <P...> for
getBestStatements or
filtering qualifying snaks
ignored if source object is table {[1]=..., [2]= ..., ...}
all: use getAllStatements instead of getBestStatements
ignored if source object is table
optional; default: false
vType: additional process information
mandantory for objects without toString() method
optional otherwise; defaults to 'string'
recomended 'id' for IDs ('Q123...') to process as labels
sep: separator string
optional; default: ', '
returns: string
]]
service.SnakList = function(object, property, all, vType, fmtString, sep)
if not sep then sep = ', ' end
if not vType then
local snaks = service.getSnaks(object, property, all)
if snaks then return table.concat(snaks, sep) end
return ''
end
local result = {}
local source = statements(object, property, all)
if not source then return '' end
if vType == 'id' then
for _, v in ipairs(source) do
local label = service.SnakValue(v, nil, v)
if label then table.insert(result,label) end
end
elseif vType == 'f' then
for _, v in ipairs(source) do
local text = service.SnakValue(v, nil, fmtString)
if text then table.insert(result,text) end
end
else
for _, v in ipairs(source) do
local text, t = unwrap(v)
if text then table.insert(result,text) end
end
end
return table.concat(result, sep)
end
--[[
namedAsList(<object>, <property>, <all>, <separator string>)
Variant to SnakList handling IDs only:
here "named as" is preferred and "label" (or ID) are fallback
parameters:
object: wikidata source:
qualifier string <Q...> of a wikidata object or
statement table as of mw.wikibase.getBestStatements or
single statement beeing source for qualifying snaks
property: defining source statement qualifier string <P...> for
getBestStatements or
filtering qualifying snaks
ignored if source object is table {[1]=..., [2]= ..., ...}
all: use getAllStatements instead of getBestStatements
ignored if source object is table
optional; default: false
vType optional; return result as (comma) separated list instead of
table
sep: separator string
optional; default: ', '
returns: string
]]
service.namedAsList = function(object, property, all, vType, fmtString, sep)
local result = {}
local source = statements(object, property, all)
if not source then if sep then return '' else return {} end end
if not vType then
for _, v in ipairs(source) do
local value = get1stNamedAs(v)
if not value then value = service.SnakValue(v) end
if value then table.insert(result, value) end
end
elseif vType == 'id' then
for _, v in ipairs(source) do
local id, t = unwrap(v)
local link = mw.wikibase.getSitelink(id)
local name = get1stNamedAs(v)
if not name then name = service.SnakValue(id, t) end
if name then
if link then
if link == name then
table.insert(result, '[[' .. name .. ']]')
else
table.insert(result, '[[' .. link .. '|' .. name .. ']]')
end
else
table.insert(result, name)
end
else
if link then table.insert(result, '[[' .. link .. ']]') end
end
end
else
mw.log('no namedAsList handling defined for ' .. vType)
end
if sep then return table.concat(result, sep) end
return result
end
--[[
WD:qualifiedSnaks(Object, property, {{}})
limit a list of statements
parameters:
target either a table containing a list of statements
or an object name (Q1234, e.g.)
claim name of a property to get a statement list if target is name
qualificators struct of elements by which list of statements may be
qualified
currently knowing qualificators.time only:
if given only those statements are returned that share
the same time (not before start = P580 e.g.)
]]
service.qualifiedSnaks = function(this, target, claim, qualificators)
condInclude = function(statement)
if not statement then return nil, false end
if not statement.qualifiers then
return statement.datavalue.value, false
end
end
target = statements(target, claim)
if type(target) ~= 'table' then return nil end
if qualificators then
if qualificators.time then
return Time.filtered(target, qualificators.time)
end
end
return target
end
--[[
qualifyingValue(statement, propQual)
simplified view on data
Parameters:
statement: statement given for an entity
propQual: qualifier for a statement value, defaults to MainSnack
returns: a string value of MainSnack or property qualifier if available
]]
service.qualifyingValue = function( statement, propQual, firstOnly, vType,
fmtString, sep)
if not statement then return "" end
if not propQual then return "" end
if not statement.qualifiers then return "" end
local snaks = statement.qualifiers[propQual]
if firstOnly then return service.SnakValue(snaks[1]) end
return service.SnakList(snaks, nil, nil, vType, fmtString, sep)
end
--[[
statementQualOrMainSnak
simple value of a statement with priority on qualifying value and fall back
to main snak value
parameters:
qualifier: string of Q[0-9]+ type for an entity with statements
property: string of P[0-9]+ type for usage of first statement
propQual: string of P[0-9]+ type for qualifying this statement
returns: simple value (no table)
]]
service.statementQualOrMainSnak = function(qualifier, property, propQual, test)
mw.log('Avoid deprecated statementQualOrMainSnak')
local statement = get1stStatement(qualifier, property, test)
if not statement then return "" end
local result = ''
local q = statement["qualifiers"]
if q and type(q[propQual]) == "table" then
result = service.SnakValue(q[propQual][1]["datavalue"]["value"])
end
if result == '' then
return service.SnakValue(statement["mainsnak"]["datavalue"]["value"])
end
return result
end
service.statementQualOrMainSnack = service.statementQualOrMainSnak
--[[
MainSnakValue(qualifier, property)
simplified view on data
Parameters:
qualifier: case 1: wikiData qualifier of an element with a property
case 2: wikiData element with a property
property: Property of the element having result as value
returns: a wikiData qualifier or a string value of MainSnack if available
limited: no regard of anything but first statement
limited: only label if id
limited: no regard of text language if text
]]
service.MainSnakValue = function(qualifier, property, fmtString)
local s = get1stStatement(qualifier, property)
if not s then return "" end
local ms = s.mainsnak
if not ms then return '' end
local sdv, t = unwrap(ms)
if t == 'f' then
if not fmtString then return sdv
else return service.SnakValue(sdv, 'f', fmtString) end
elseif t == 'id' then return service.SnakValue(sdv, 'id', s) end
return service.SnakValue(sdv, t)
end
service.MainSnackValue = service.MainSnakValue
--[[
indirectMSValue(qualifier, properties)
Parameters:
qualifier: case 1: wikiData qualifier of an element with a property
case 2: wikiData element with a property
properties: sequence of properties in a string, optionally separated
returns:
first MainSnackValue of last property of element given in seccond last
property ... of element given in first property of given element
]]
service.indirectMSValue = function(qualifier, properties, fmtString)
if not properties then return '' end
if qualifier == nil or qualifier == "" then return "" end
local props = {}
for prop in properties:gmatch('[pP]%d+') do
table.insert(props, prop)
end
if #props == 0 then return "" end
local statementList = statements(qualifier, props[1])
local t = ''
local qual = qualifier
local result = ""
local i = 1
-- process all but last properties
while i < #props do
if not statementList then return '' end
if not statementList[1] then return '' end
result, t = unwrap(statementList[1].mainsnak)
if t ~= 'id' then return '' end
qual = result
-- mw.log('next for ' .. mw.wikibase.getLabel(qual))
i = i + 1
statementList = mw.wikibase.getBestStatements(qual, props[i])
end
-- process last property
if not statementList then return '' end
if not statementList[1] then return "" end
local ms = statementList[1].mainsnak
local sdv, t = unwrap(ms)
if t == 'f' then return sdv:format(fmtString) end
if t == 'id' then
local label = mw.wikibase.getLabel(sdv)
if label then return label end
return get1stNamedAs(statementList[1], sdv)
end
return sdv
end
--[[
qualifiersLineup(qualifier, property)
sequence of wikiData qualifiers
Parameters:
qualifier: case 1: wikiData qualifier of an element with a property
case 2: wikiData element with a property
property: Property of the element having result qualifiers as values
returns:
best statement's values as long as they are wikiData qualifiers lined up
in a table with respect on series ordinals if available
constraint:
It's in the responsibility of wikiData to provide correct data. In case
of corruption this function might return an empty table or one that
apears empty by starting with index ~= 1.
]]
service.qualifiersLineup = function(qualifier, property)
local statementList = statements(qualifier, property)
if not statementList then return {} end
local result = {}
for i, elm in ipairs(statementList) do
local eQual, t = unwrap(elm.mainsnak)
if t ~= 'id' then return result end
local iQual = elm.qualifiers
if not iQual then
mw.log('kein qualifier in ' .. eQual)
table.insert(result, eQual)
else
iQual = iQual.P1545
if not iQual then
mw.log('keine Ornungsnummer in ' .. eQual)
table.insert(result, eQual)
else
local eNum = iQual[1]["datavalue"]["value"]
table.insert(result, eNum, eQual)
end
end
end
return result
end
service.test = function(frame)
return service.MainSnackValue('Q115122668', 'P577', 2)
end
return service