Belgekirina modulê[biafirîne]
local path = {}
local propt = require "Module:Propriétés"

path.Node = {}

function path.Node:new (o)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  return o
end

path.AlternativeNode = path.Node:new()

function path.AlternativeNode:create(nodes)
	local newinst = {["nodes"] = nodes}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

function path.AlternativeNode:type()
	return "alternativenode"
end

path.SequenceNode = path.Node:new()

function path.SequenceNode:create(nodes)
	local newinst = {["nodes"] = nodes}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

function path.SequenceNode:type()
	return "sequencenode"
end

path.StarNode = path.Node:new()
function path.StarNode:create(node)
	assert(node, "(Some) Node : no node provided on creation")
	local newinst = {["node"] = node}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

path.PlusNode = path.Node:new()
function path.PlusNode:create(node)
	assert(node, "(Some) Node : no node provided on creation")

	local newinst = {["node"] = node}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

path.MaybeNode = path.Node:new()
function path.MaybeNode:create(node)
	assert(node, "(Some) Node : no node provided on creation")
	local newinst = {["node"] = node}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

path.BetweenNode = path.Node:new()
function path.BetweenNode:create(node, min, max)
	assert(node, "(Some) Node : no node provided on creation")

	local newinst = {
		["node"] = node, 
		["min"] = min,
		["max"] = max,
	}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end


path.InverseNode = path.Node:new()
function path.InverseNode:create(node)
	assert(node, "(Some) Node : no node provided on creation")
	local newinst = {["node"] = node}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

path.QualifiedStatementNode = path.Node:new()
function path.QualifiedStatementNode:create(main_prop_node, qual_node)
	assert(main_prop_node, "(Some) Node : no node provided on creation")
	assert(qual_node, "(Some) Node : no node provided on creation")
	
	local newinst = {
		["property"] = main_prop_node,
		["qualifier"] = qual_node
	}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end


path.PseudoPropertyNode = path.Node:new()

path.PropertyNode = path.PseudoPropertyNode:new()

function path.PropertyNode:create(property)
	assert(property, "(Prop Node : a property must be provided on creation")
	local newinst = {
		["property"] = propt.normalize(property)
	}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

function path.PropertyNode:matches(property_str)
	return propt.normalize(property_str) == self.property
end

-- see https://www.w3.org/2009/sparql/docs/property-paths/Overview.xml

path.NegatedPropertySetNode = path.PseudoPropertyNode:new()
function path.NegatedPropertySetNode:create(negated_nodes)
	assert(negated_nodes, "NegPSet Node : no nodeset provided on creation")
	local newinst = {
		["negated_nodes"] = negated_nodes
	}
	setmetatable(newinst, self)
	self.__index = self
	self.props = {}
	
	for _, val in pairs(negated_nodes) do
		self.props[val.node.property] = true
	end
	
	return newinst
end

function path.NegatedPropertySetNode:inset(pid)
	return self.props[pid] ~= nil
end

function path.NegatedPropertySetNode:matches(property_str)
	return not self:inset(propt.normalize(property_str))
end

path.PropertySetNode = path.PseudoPropertyNode:new()
function path.PropertySetNode:create(nodes)
	
	assert(nodes, "PseudoProp Node : no nodes provided on creation")
	local newinst = {
		["nodes"] = nodes
	}
	setmetatable(newinst, self)
	self.__index = self
	self.props = {}
	
	for _, val in pairs(nodes) do
		self.props[val.node.property] = true
	end
	
	return newinst
end

function path.PropertySetNode:inset(pid)
	return self.props[pid] ~= nil
end

function path.PropertySetNode:matches(property_str)
	return self:inset(propt.normalize(property_str))
end


path.QualifierSnakNode = path.Node:new()

function path.QualifierSnakNode:create(pseudopnode)
	local newinst = {["pseudopnode"] = pseudopnode}
	setmetatable(newinst, self)
	self.__index = self
	return newinst
end

function path.QualifierSnakNode:type()
	return "qualifiersnaknode"
end

function path.QualifierSnakNode:matches(property_str)
	return self.pseudopnode:matches(property_str)
end

return path