Module:Work license

--[=[ A module that can be used to get licensing information about an entity

WORK IN PROGRESS ]=]

local p = {} --p stands for package

-- library util provided by MW local util = require 'libraryUtil'

local wikibaseUtils = require( 'Module:Wikibase utils' )

-- common constants local DATA = mw.loadData( 'Module:Work data/properties' )

-- local constants useful mainly for this module local LDATA = { props = { jurisdiction = 'P1001', determinationMethod = 'P459', relevantCopyrightDate = 'P9905' },	items = { usa = 'Q30', publicDomain = 'Q19652', pma50Countries = 'Q59621182', pma70Countries = 'Q73560261', pma25orLessCountries = 'Q68543134', pma60orLessCountries = 'Q105480667', pma70orLessCountries = 'Q59542795', pma80orLessCountries = 'Q61830521', pma100orLessCountries = 'Q60332278', pma50orMoreCountries = 'Q87048619', pma70orMoreCountries = 'Q60845045', countriesWithPDArt = 'Q108574927', countriesWithoutPDArt = 'Q108574944', pubOver95YearsAgo = 'Q47246828', byUsFederalGov = 'Q60671452', noUsRenweal = 'Q29941035', noUsNotice = 'Q47012574', badUsNotice = 'Q61062601', pma100Determination = 'Q29940705', } }

-- "extra" jurisdications that countries belong to and can't be worked out -- by maths local JURISDICTIONS = { [ LDATA.items.usa ] = { LDATA.items.countriesWithPDArt, } } local PMAS = { }

local function getJurisdictionsForCountry( countryQid ) -- always contains the country itself local jurisdictions = { countryQid }	-- add "specials" for _, j in pairs( JURISDICTIONS[ countryQid ] or {} ) do		table.insert( jurisdictions, j ) end local pma = PMAS[ countryQid ] if pma ~= nil then -- work out the membership of the PMA items -- these are incomplete at WD, so this looks wierd, but it does what it		-- needs to for us		-- XX or less groupins if pma <= 25 then table.insert( jurisdictions, LDATA.items.pma25orLessCountries ) end if pma <= 60 then table.insert( jurisdictions, LDATA.items.pma60orLessCountries ) end if pma <= 70 then table.insert( jurisdictions, LDATA.items.pma70orLessCountries ) end if pma <= 80 then table.insert( jurisdictions, LDATA.items.pma80orLessCountries ) end if pma <= 100 then table.insert( jurisdictions, LDATA.items.pma100orLessCountries ) end -- exact PMA groupings if pma == 50 then table.insert( jurisdictions, LDATA.items.pma50Countries ) elseif pma == 70 then table.insert( jurisdictions, LDATA.items.pma70Countries ) end -- or more groupings if pma >= 70 then table.insert( jurisdictions, LDATA.items.pma70orMoreCountries ) end if pma >= 50 then table.insert( jurisdictions, LDATA.items.pma50orMoreCountries ) end else -- error('Do not know the PMA for the requested country: ' .. countryQid ) end return jurisdictions end

--[=[ Get any qualifiers of the given statement with a QID in the given list Returns a table of snaks, or an empty table ]=] local function getStatementQualifiersWithValueQids( statement, pid, qids ) if type( qids ) ~= 'table' then qids = { qids } end local matchingQualifiers = {}

-- look in every suitable qualifier of this statement local qualifiersOfProperty = wikibaseUtils.getQualifiersOfStatementWithPid( statement, pid ) -- for every qualifier, see if it has one of the desired values for _, qualifierSnak in pairs( qualifiersOfProperty ) do		local snakValue = wikibaseUtils.getSnakValueQid( qualifierSnak ) for _, qid in pairs( qids ) do			if snakValue == qid then table.insert( matchingQualifiers, qualifierSnak ) end end end return matchingQualifiers end

--[=[ Get the list of the copyright claims that apply to the given country ]=] local function getApplicableCopyrightStatusClaims( entity, countryQid ) local copyrightStatusClaims = entity:getAllStatements( DATA.props.copyrightStatus ) -- the list of jurisdictions that this country belongs to	local allowedJurisdictions = getJurisdictionsForCountry( countryQid ) local applicableClaims = {} for _, statement in pairs( copyrightStatusClaims ) do		local applicableClaimsForStatement = getStatementQualifiersWithValueQids(			statement, LDATA.props.jurisdiction, allowedJurisdictions )

if #applicableClaimsForStatement > 0 then table.insert( applicableClaims, statement ) end end -- did not find any statement indicating PD	return applicableClaims end

--[=[ Determine if a work is public domain in the given country ]=] local function isEntityPdInCountry( entity, countryQid ) local applicableClaims = getApplicableCopyrightStatusClaims( entity, countryQid ) for _, claim in pairs( applicableClaims ) do		if wikibaseUtils.getSnakValueQid( claim.mainsnak ) == LDATA.items.publicDomain then return true end end -- no claim indicates PD in the given country return false end

local function getBestRelevantDate( claim ) local dates = wikibaseUtils.getQualifiersOfStatementWithPid(		claim, LDATA.props.relevantCopyrightDate ) local relevantDate for _, dateQual in pairs( dates ) do		relevantDate = wikibaseUtils.getSnakValueYear( dateQual ) end return relevantDate end

local function getUsLicenceFromClaim( claim ) local status = wikibaseUtils.getSnakValueQid( claim.mainsnak ) -- list of determination qualifers on the claim local determinations = wikibaseUtils.getQualifiersOfStatementWithPid(		claim, LDATA.props.determinationMethod ) local relevantDate = getBestRelevantDate( claim ) -- convert suitable determination qualifers to a simple representation for _, det in pairs( determinations ) do		-- the Qid of the determination method local detQid = wikibaseUtils.getSnakValueQid( det )

if status == LDATA.items.publicDomain then if detQid == LDATA.items.pubOver95YearsAgo then lic = { nature = 'pub-date', date = relevantDate }			elseif detQid == LDATA.items.byUsFederalGov then lic = { nature = 'us-gov', date = nil -- date doesn't matter }			elseif detQid == LDATA.items.noUsRenweal then lic = { nature = 'not-renewed', date = relevantDate }			elseif detQid == LDATA.items.noUsNotice then lic = { nature = 'no-notice', date = relevantDate }			elseif detQid == LDATA.items.badUsNotices then lic = { nature = 'no-notice', date = relevantDate }			end end

if lic ~= nil then return lic end end return nil end

--[=[ Get the US and non-US license data ]=] local function getEntityLicenseData( entity ) local usLicenses local otherLicenses

-- get all the US-applicable copyright statements local usClaims = getApplicableCopyrightStatusClaims( entity, LDATA.items.usa ) for _, claim in pairs( usClaims ) do		local usLic = getUsLicenceFromClaim( claim) -- probably just need one(?) if usLic ~= nil then usLicenses = usLic break end end return { us = usLicenses, other = otherLicenses }	end

--[=[ This is the main entry point to get a new workLicense object

This function is public, and is designed to be called by other modules ]=] function p.newWorkLicense( titleOrQid ) -- the object we will eventually return local obj = {} -- the function that checks if a call to a method is using. instead of : local checkSelfFunc = util.makeCheckSelfFunction( 'Module:Work license',		'aWorkLicense', obj, 'work license object' ); local entity = wikibaseUtils.getEntity( titleOrQid ) -- bail out if we don't find a WB entity if entity == nil then return nil end -- data object of this object -- this is private, and access is granted though the returned meta-table local data = { entity = entity, }

return setmetatable( obj, {		__eq = entity.id.equals,		__lt = entity.id.__lt,		__tostring = function ( t )			return t.entity		end,		-- return specific fields		__index = function ( t, key )			-- figure out if a work is PD at Wikisource (i.e. in the US specifically)			-- returns true, false or nil (meaning cannot be determined)			if key == 'isPublicDomain' then				if data.isPublicDomain == nil then					data.isPublicDomain = isEntityPdInCountry( entity, LDATA.items.usa )				end				return data.isPublicDomain			end			if key == 'licenseData' then				if data.licenseData == nil then					data.licenseData = getEntityLicenseData( entity )				end				return data.licenseData			end			-- otherwise, just return the member of data			return data[ key ]		end,		-- workLicense objects are always read-only		__newindex = function ( t, k, v )			error( "index '" .. k .. "' is read only", 2 )		end	} ) end

return p