bradleymarques/gimme_wikidata

View on GitHub
lib/gimme_wikidata.rb

Summary

Maintainability
A
35 mins
Test Coverage
require 'gimme_wikidata/claim'
require 'gimme_wikidata/entity'
require 'gimme_wikidata/entity_result'
require 'gimme_wikidata/extensions'
require 'gimme_wikidata/enums'
require 'gimme_wikidata/item'
require 'gimme_wikidata/parser'
require 'gimme_wikidata/printer'
require 'gimme_wikidata/property'
require 'gimme_wikidata/search'
require 'gimme_wikidata/version'
require 'gimme_wikidata/wikidata_api'

module GimmeWikidata

  include SymbolizeHelper

  class << self

    ##
    # Search Wikidata for a particular search term, and get the results.
    #
    # Searches the Wikidata API for a particular term and returns some SearchResults (wrapped in a Search object).
    # Constructs the required search query, makes the call to the API and parses the response.
    #
    # * *Parameters*    :
    #   - +search_term+ -> the search term to look for on Wikidata
    #   - +strict_language+ -> Should we force a restriction to the current language?  See WikidataAPI::language
    #   - +type+ -> Either search for 'item' or 'property'.  Defaults to 'item'
    #   - +limit+ -> The maximum number of SearchResults to return.  Defaults to 50.
    #   - +continue+ -> Where to continue the search from.  Defaults to 0.
    # * *Returns* :
    #   - A Search object representing and containing the +SearchResults+ found
    def search(search_term = 'wikidata', strict_language: false, type: 'item', limit: 50, continue: 0)
      search_query = WikidataAPI.search_query(search_term, strict_language: strict_language, type: type, limit: limit, continue: continue)
      response = WikidataAPI.make_call(search_query)
      Parser.parse_search_response(response)
    end

    ##
    # Fetch Entity (or Entities) from Wikidata by id (or ids)
    #
    # Calls either +fetch_entity+ or +fetch_entities+, so is just for convenience.
    #
    # * *Parameters*    :
    #   - +ids+ -> Either a single Wikidata id or an array of them.  If the former, will call +fetch_entity+; if the latter, will call +fetch_entities+
    #   - +props+ -> The properties to pull from Wikidata (see Props class).  Defaults to +aliases+, +labels+, +descriptions+ and +claims+.
    # * *Returns* :
    #   - An Entity in the case of a single id, and an EntityResult in the case of multiple ids
    # * *Raises* :
    #   - +ArgumentError+ if ids are not valid Wikidata ids
    def fetch(ids, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
      case ids.class.to_s
      when 'Array'
        raise ArgumentError.new 'Invalid Wikidata ids' unless valid_ids? ids
        return fetch_entities(ids, props: props)
      when 'String'
        raise ArgumentError.new 'Invalid Wikidata id' unless valid_id? ids
        return fetch_entity(ids, props: props)
      else
        raise ArgumentError.new 'Invalid Wikidata ids'
      end
    end

    ##
    # Fetch a single Entity from Wikidata by id
    #
    # * *Parameters*    :
    #   - +id+ -> The Wikidata id of the Entity to get
    #   - +props+ -> The properties to pull from Wikidata (see Props class)
    # * *Returns* :
    #   - An Entity if successful, and an EntityResponse (with error message) if unsuccessful
    # * *Raises* :
    #   - +ArgumentError+ if ids are not valid Wikidata ids
    def fetch_entity(id, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
      raise ArgumentError.new 'Invalid Wikidata id' unless valid_id? id
      entity_result = fetch_entities([id], props: props)
      return entity_result unless entity_result.was_successful?
      entity_result.entities.first # Simply return the first element, since there was only 1 Entity to fetch
    end

    ##
    # Fetch multiple Entities from Wikidata by id
    #
    # Makes a call to Wikidata and get the results wrapped in a +EntityResult+ object
    # * *Parameters*    :
    #   - +ids+ -> An array of Wikidata ids, such as ['Q1', 'Q2', 'P206', 'P16']
    #   - +props+ -> The properties to pull from Wikidata (see Props class)
    # * *Returns* :
    #   - An EntityResult object containing Entities
    # * *Raises* :
    #   - +ArgumentError+ if ids are not valid Wikidata ids
    def fetch_entities(ids, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
      raise ArgumentError.new 'Invalid Wikidata ids' unless valid_ids? ids
      get_query = WikidataAPI.get_entities_query(ids, props: props)
      response = WikidataAPI.make_call(get_query)
      entity_result = Parser.parse_entity_response(response)
      entity_result.resolve_all_properties
      entity_result.resolve_all_claims if props.include? Props::CLAIMS
      entity_result
    end

    ##
    # Valdiates an array of ids against Wikidata format
    #
    # Wikidata has ids in the form 'QN' or 'PN' where Q means 'Item', P means 'Property', and N is any number.
    # * *Parameters*:
    #   - +ids+ -> An array of (possible) Wikidata ids to be validated, in string form
    #   - +type+ -> array of symbols representing entity types to check. Defaults to +[:item, :property]+
    # * *Returns*:
    #   - boolean
    def valid_ids?(ids, type = [:item, :property])
      return false unless ids.is_a? Array
      ids.all? { |i| valid_id?(i, type) }
    end

    ##
    # Valdiates a single id against Wikidata format
    #
    # Wikidata has ids in the form 'QN' or 'PN' where Q means 'Item', P means 'Property', and N is any number.
    # * *Parameters*    :
    #   - +id+ -> A (possible) Wikidata id to be validated, as a String
    #   - +type+ -> array of symbols representing entity types to check. Defaults to +[:item, :property]+
    # * *Returns*:
    #   - boolean
    def valid_id?(id, type = [:item, :property])

      return false unless id.is_a? String

      prefix =
      case type
      when [:item, :property] then 'QP'
      when [:item] then 'Q'
      when [:property] then 'P'
      else raise ArgumentError.new "type must be a subset of [:item, :property]"
      end

      !(/\A[#{prefix}][0-9]+\z/.match(id).nil?)
    end

  end

end