#![deny(
missing_debug_implementations,
missing_copy_implementations,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_import_braces,
unused_qualifications
)]
use serde::ser::{SerializeStruct, Serializer};
use serde::Serialize;
use Reference;
use Snak;
use SnakDataType;
use WikibaseError;
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum StatementRank {
Deprecated,
Normal,
Preferred,
}
impl StatementRank {
pub fn as_str(&self) -> &str {
match self {
StatementRank::Deprecated => "deprecated",
StatementRank::Normal => "normal",
StatementRank::Preferred => "preferred",
}
}
}
#[derive(Debug, Clone)]
pub struct Statement {
claim_type: String,
rank: StatementRank,
main_snak: Snak,
qualifiers: Vec<Snak>,
references: Vec<Reference>,
id: Option<String>,
}
impl Statement {
pub fn new<S: Into<String>>(
claim_type: S,
rank: StatementRank,
main_snak: Snak,
qualifiers: Vec<Snak>,
references: Vec<Reference>,
) -> Statement {
Self {
claim_type: claim_type.into(),
rank,
main_snak,
qualifiers,
references,
id: None,
}
}
pub fn new_normal(
main_snak: Snak,
qualifiers: Vec<Snak>,
references: Vec<Reference>,
) -> Statement {
Self::new(
"statement",
StatementRank::Normal,
main_snak,
qualifiers,
references,
)
}
pub fn new_from_json(json_claim: &serde_json::Value) -> Result<Statement, WikibaseError> {
let claim_object = match &json_claim.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Statement".to_string())),
};
let claim_type = match claim_object["type"].as_str() {
Some(value) => value,
None => {
return Err(WikibaseError::Serialization(
"Statement type error".to_string(),
));
}
};
let rank_string = match claim_object["rank"].as_str() {
Some(value) => value,
None => {
return Err(WikibaseError::Serialization(
"Statement rank error".to_string(),
));
}
};
let rank = match rank_string {
"deprecated" => StatementRank::Deprecated,
"normal" => StatementRank::Normal,
"preferred" => StatementRank::Preferred,
_ => {
return Err(WikibaseError::Serialization(
"Statement rank error".to_string(),
));
}
};
let main_snak = match &claim_object["mainsnak"].as_object() {
&Some(snak_json) => Snak::new_from_json(snak_json)?,
&None => return Err(WikibaseError::Serialization("Main snak".to_string())),
};
let qualifiers = match &claim_object.get("qualifiers") {
&Some(qualifiers) => Statement::snaks_object_from_json(&qualifiers)?,
&None => vec![],
};
let references = match &claim_object.get("references") {
&Some(references_array_json) => {
Statement::reference_array_from_json(&references_array_json)?
}
&None => vec![],
};
let mut statement = Statement::new(claim_type, rank, main_snak, qualifiers, references);
match claim_object["id"].as_str() {
Some(id) => statement.set_id(id.to_string()),
None => {}
};
Ok(statement)
}
pub fn snaks_object_from_json(
snaks_object_json: &serde_json::Value,
) -> Result<Vec<Snak>, WikibaseError> {
let mut snaks = vec![];
let snaks_object = match &snaks_object_json.as_object() {
&Some(value) => value,
&None => {
return Err(WikibaseError::Serialization(
"Can't deserialize snaks object".to_string(),
));
}
};
for (_, property_snaks) in snaks_object.iter() {
let snak_array = match &property_snaks.as_array() {
&Some(value) => value,
&None => {
return Err(WikibaseError::Serialization(
"Can't deserialize snak array".to_string(),
));
}
};
for snak_json in snak_array.iter() {
let snak_object = match &snak_json.as_object() {
&Some(value) => value,
&None => {
return Err(WikibaseError::Serialization(
"Can't deserialize snak object".to_string(),
));
}
};
snaks.push(Snak::new_from_json(snak_object)?);
}
}
Ok(snaks)
}
pub fn reference_array_from_json(
references_array_json: &serde_json::Value,
) -> Result<Vec<Reference>, WikibaseError> {
let mut references = vec![];
let reference_array = match &references_array_json.as_array() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Reference array".to_string())),
};
for references_object_json in reference_array.iter() {
let reference_object = match &references_object_json.as_object() {
&Some(value) => value,
&None => return Err(WikibaseError::Serialization("Reference object".to_string())),
};
let snaks_array = match &reference_object.get("snaks") {
&Some(value) => value,
&None => {
return Err(WikibaseError::Serialization(
"Reference snak object".to_string(),
));
}
};
references.push(Reference::new(Self::snaks_object_from_json(snaks_array)?));
}
Ok(references)
}
pub fn as_stripped_json(&self) -> serde_json::Value {
let mut ret = json!(self);
if ret.as_object().unwrap().contains_key("id") {
ret.as_object_mut().unwrap().remove("id").unwrap();
}
ret
}
pub fn set_id<S: Into<String>>(&mut self, id: S) {
self.id = Some(id.into());
}
pub fn id(&self) -> Option<String> {
self.id.clone()
}
pub fn set_claim_type(&mut self, claim_type: &str) {
self.claim_type = claim_type.to_string();
}
pub fn set_rank(&mut self, rank: StatementRank) {
self.rank = rank;
}
pub fn set_datatype(&mut self, datatype: SnakDataType) {
self.main_snak.set_datatype(datatype);
}
pub fn property(&self) -> &str {
&self.main_snak.property()
}
pub fn set_property(&mut self, property: &str) {
self.main_snak.set_property(property);
}
pub fn set_main_snak(&mut self, snak: Snak) {
self.main_snak = snak;
}
pub fn add_qualifier_snak(&mut self, snak: Snak) {
self.qualifiers.push(snak);
}
pub fn set_qualifier_snaks(&mut self, snaks: Vec<Snak>) {
self.qualifiers = snaks;
}
pub fn set_references(&mut self, references: Vec<Reference>) {
self.references = references;
}
pub fn references(&self) -> &Vec<Reference> {
&self.references
}
pub fn qualifiers(&self) -> &Vec<Snak> {
&self.qualifiers
}
pub fn main_snak(&self) -> &Snak {
&self.main_snak
}
pub fn claim_type(&self) -> &String {
&self.claim_type
}
pub fn rank(&self) -> &StatementRank {
&self.rank
}
}
impl Serialize for Statement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut num = 3;
if self.id.is_some() {
num += 1;
}
if !self.qualifiers.is_empty() {
num += 1;
}
if !self.references.is_empty() {
num += 1;
}
let mut state = serializer.serialize_struct("Statement", num)?;
state.serialize_field("type", &self.claim_type)?;
state.serialize_field("rank", &self.rank.as_str())?;
state.serialize_field("mainsnak", &self.main_snak)?;
match &self.id {
Some(id) => state.serialize_field("id", &id)?,
None => {}
};
if !self.qualifiers.is_empty() {
let mut qualifiers = json!({});
for snak in &self.qualifiers {
if !qualifiers[snak.property()].is_object() {
qualifiers[snak.property()] = json!([]);
}
qualifiers[snak.property()]
.as_array_mut()
.unwrap()
.push(json!(snak));
}
state.serialize_field("qualifiers", &qualifiers)?;
}
if !self.references.is_empty() {
let mut references = json!([]);
for reference in &self.references {
let mut rj = json!({"snaks":{}});
for snak in reference.snaks() {
if !rj["snaks"][snak.property()].is_array() {
rj["snaks"][snak.property()] = json!([]);
}
rj["snaks"][snak.property()]
.as_array_mut()
.unwrap()
.push(json!(snak));
}
references.as_array_mut().unwrap().push(rj);
}
state.serialize_field("references", &references)?;
}
state.end()
}
}