wikibase 0.7.6

A library to access Wikibase
Documentation
// query.rs
//
// Copyright © 2018
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

use crate::entity_type::EntityType;
use crate::Configuration;
use std::collections::HashMap;

/// Query for entities items and properties by ID (`wbgetentities`).
///
/// This structure holds all the parameters to query for one or many
/// Wikibase entities (items and properties).
///
/// # API Documentation
///
/// https://www.wikidata.org/w/api.php?action=help&modules=wbgetentities
///
/// # Example
///
/// ```
/// let query = wikibase::query::EntityQuery::new(vec!["Q19660".to_string(), "P190".to_string()], "es");
/// ```
#[derive(Debug)]
pub struct EntityQuery {
    ids: Vec<String>,
    lang: String,
}

/// Maps to the wbgetentities Mediawiki API
///
/// # API Documentation
///
/// https://www.wikidata.org/w/api.php?action=help&modules=wbsearchentities
///
/// # Example
///
/// ```
/// let query = wikibase::query::SearchQuery::new("Minsk", "be", "be", 10, wikibase::EntityType::Property);
/// ```
#[derive(Debug)]
pub struct SearchQuery {
    query: String,
    lang: String,
    search_lang: String,
    limit: u64,
    entity_type: EntityType,
}

impl EntityQuery {
    pub fn new<S: Into<String>>(ids: Vec<String>, lang: S) -> EntityQuery {
        Self {
            ids,
            lang: lang.into(),
        }
    }

    pub fn ids(&self) -> &[String] {
        &self.ids
    }

    pub fn lang(&self) -> &str {
        &self.lang
    }

    pub fn url(&self, configuration: &Configuration) -> String {
        let mut params: Vec<String> = self
            .params()
            .iter()
            .map(|(k, v)| k.to_owned() + "=" + v)
            .collect();
        params.sort(); // For tests
        format!(
            "{}?{}&format=json",
            configuration.api_url(),
            encode_url(&params.join("&"))
        )
    }

    pub fn params(&self) -> HashMap<String, String> {
        vec![
            ("action", "wbgetentities"),
            ("ids", &self.ids_piped()),
            ("languages", &self.lang),
            ("uselang", &self.lang),
        ]
        .into_iter()
        .map(|s| (s.0.to_string(), s.1.to_string()))
        .collect()
    }

    fn ids_piped(&self) -> String {
        self.ids().join("|")
    }
}

impl SearchQuery {
    pub fn new<S: Into<String>>(
        query: S,
        lang: S,
        search_lang: S,
        limit: u64,
        entity_type: EntityType,
    ) -> SearchQuery {
        Self {
            query: query.into(),
            lang: lang.into(),
            search_lang: search_lang.into(),
            limit,
            entity_type,
        }
    }

    pub fn entity_type(&self) -> &EntityType {
        &self.entity_type
    }

    pub fn lang(&self) -> &str {
        &self.lang
    }

    pub fn limit(&self) -> &u64 {
        &self.limit
    }

    pub fn query(&self) -> &str {
        &self.query
    }

    pub fn search_lang(&self) -> &str {
        &self.search_lang
    }

    pub fn url(&self, configuration: &Configuration) -> String {
        let mut params: Vec<String> = self
            .params()
            .iter()
            .map(|(k, v)| k.to_owned() + "=" + v)
            .collect();
        params.sort(); // For tests
        format!(
            "{}?{}&format=json",
            configuration.api_url(),
            encode_url(&params.join("&"))
        )
    }

    pub fn params(&self) -> HashMap<String, String> {
        vec![
            ("action", "wbsearchentities"),
            ("search", &self.query),
            ("language", &self.search_lang),
            ("limit", &self.limit.to_string()),
            ("type", &self.entity_type.string_value()),
            ("uselang", &self.lang),
        ]
        .into_iter()
        .map(|s| (s.0.to_string(), s.1.to_string()))
        .collect()
    }
}

/// Encodes the URL for a request
///
/// Only replaces various special characters to make the request work.
/// Replaces:
/// " " (space) -> "%20"
fn encode_url(url: &str) -> String {
    str::replace(url, " ", "%20")
}