local sparql = require "Module:SPARQL"
local ppath = require "Module:PropertyPath"
local tool = require "Module:Tools"
local func = require "Module:Luafun"
-- Module that generate queries for classes items.
-- especially queries to find instances of those classes
-- lua tuple (pair) implementation, see http://lua-users.org/wiki/FunctionalTuples
local function Def(_class, _stmts)
return function(fn) return fn(_class, _stmts) end
end
local function class(_class, _stmts) return _class end
local function stmts(_class, _stmts) return _stmts end
-- generates a truthy statement pattern for a property value pair
local function truthy_pair_gp(prop, val)
return " wdt:" .. prop .. " wd:" .. val
end
local walk = ppath.iterate
-- buildding a graph pattern for truthy staetements
local function truthy_stmt_gp_atom(item, prop, val)
return item .. truthy_pair_gp(prop, val)
end
-- buildding a graph pattern for qualifier snaks
local function qualifier_snak_gp(prop, val)
return "pq:" .. prop .. " wd:" .. val
end
local function truthy_stmt_gp(item, propval_pairs)
return item .. table.concat(
propval_pairs,
", ")
end
local p = {}
-- generates a partial query to find any instance item of one class or its subclasses
-- that are explicitely linked to a class
p.query_explicit_instances = function (class_id, var)
local init = var or ""
return init .. " wdt:P31/wdt:P279* " .. "wd:".. class_id
end
p.query_implicit_instances = function(class, var_name)
if not var_name or var_name == "" then
var_name = "item"
end
var_name = sparql.create_var(var_name)
local stmts = {}
if not class then error("the class_id provided to generate the query in query implicit instances is nil") end
for has_quality_stmt in walk(class,"wdt:P279*/p:P1552") do
if has_quality_stmt:item_value() == "Q47524457" then -- only statements with "instances statements as qualifiers" special value
for qualifier_snak in walk(has_quality_stmt, (">!()")) do
if qualifier_snak:has_an_item() then -- TODO: manage other datatypes restrictions
stmts[#stmts + 1] = truthy_stmt_gp_atom(var_name, qualifier_snak.property, qualifier_snak:item_value())
end
end
end
end
local vars = {}
vars[1] = var_name
return sparql.pi(vars, sparql.intersect(stmts))
end
-- testing with « Q38043002 »
-- function to find explicit instances of a class, as well as « implicit instances » ( see documentation, eg. [[Template:query all instances]] )
p.query_any_instances = function(class_id, var_name)
if not var_name or var_name == "" then
var_name = "item"
end
local class_stmts_pairs = {}
var_name = sparql.create_var(var_name)
for has_quality_stmt in walk(class_id, "wdt:P279*/p:P1552") do
if has_quality_stmt:item_value() == "Q47524457" then -- only statements with "instances statements as qualifiers" special value
local instances_snak_gp = {}
for qualifier_snak in walk(has_quality_stmt, ">!()") do
if qualifier_snak:has_an_item() then -- TODO: manage other datatypes restrictions
instances_snak_gp[#instances_snak_gp + 1] = truthy_pair_gp(qualifier_snak.property, qualifier_snak:item_value())
end
end
class_stmts_pairs[#class_stmts_pairs + 1] = Def(
has_quality_stmt.parent:item_value(),
instances_snak_gp
)
end
end
local last = class_stmts_pairs[#class_stmts_pairs]
return func.iter(class_stmts_pairs):take_n(#class_stmts_pairs - 1):reduce(
function(acc, nextcp)
return sparql.union({
p.query_explicit_instances(nextcp(class), var_name),
sparql.intersect({
truthy_stmt_gp(var_name, nextcp(stmts)),
acc
}),
})
end,
sparql.union({
p.query_explicit_instances(last(class), var_name),
truthy_stmt_gp(var_name, last(stmts))
})
)
end
--[[
functions to generate a query that finds items with statements with a certain main snak,
either because they actually have a statement with that main snak
or because they are explicit instances of a class that bears it in « has quality »
WIP
--]]
p.item_by_statement = function(var_name, property, value)
if not var_name or var_name == "" then
var_name = "item"
end
var_name = sparql.create_var(var_name)
return sparql.union{
var_name .. truthy_pair_gp(property, value),
var_name .. " wdt:P31/wdt:P279*/p:P1552 " .. "[ps:P1552 wd:Q47524457 ;" .. qualifier_snak_gp(property, value) .. "]"
}
end
p.query_implicit_instance_template = function(frame)
return p.query_implicit_instances(frame.args[1], frame.args[2])
end
p.query_any_instance_template = function(frame)
return p.query_any_instances(frame.args[1], frame.args[2])
end
p.query_any_statement_template = function(frame)
return p.item_by_statement(frame.args[1], frame.args[2], frame.args[3])
end
return p