use std::collections::HashSet;
use json::JsonValue;
use crate::{
Error,
ErrorCode,
Direction,
LangString,
Id,
Indexed,
object::*,
Context,
syntax::Type
};
use super::{
expand_iri,
node_id_of_term
};
fn clone_default_language<T: Id, C: Context<T>>(active_context: &C) -> Option<String> {
match active_context.default_language() {
Some(lang) => Some(lang.to_string()),
None => None
}
}
fn clone_default_base_direction<T: Id, C: Context<T>>(active_context: &C) -> Option<Direction> {
match active_context.default_base_direction() {
Some(dir) => Some(dir),
None => None
}
}
pub fn expand_literal<T: Id, C: Context<T>>(active_context: &C, active_property: Option<&str>, value: &JsonValue) -> Result<Indexed<Object<T>>, Error> {
let active_property_definition = active_context.get_opt(active_property);
let active_property_type = if let Some(active_property_definition) = active_property_definition {
active_property_definition.typ.clone()
} else {
None
};
match active_property_type {
Some(Type::Id) if value.is_string() => {
let mut node = Node::new();
node.id = node_id_of_term(expand_iri(active_context, value.as_str().unwrap(), true, false));
Ok(Object::Node(node).into())
},
Some(Type::Vocab) if value.is_string() => {
let mut node = Node::new();
node.id = node_id_of_term(expand_iri(active_context, value.as_str().unwrap(), true, true));
Ok(Object::Node(node).into())
},
_ => {
let result = match value {
JsonValue::Null => Literal::Null,
JsonValue::Boolean(b) => Literal::Boolean(*b),
JsonValue::Number(n) => Literal::Number(*n),
JsonValue::Short(_) | JsonValue::String(_) => Literal::String(value.as_str().unwrap().to_string()),
_ => panic!("expand_literal must be called with a literal JSON value")
};
let mut tys = HashSet::new();
match active_property_type {
None | Some(Type::Id) | Some(Type::Vocab) | Some(Type::None) => {
if let Literal::String(str) = result {
let language = if let Some(active_property_definition) = active_property_definition {
if let Some(language) = &active_property_definition.language {
language.clone()
} else {
clone_default_language(active_context)
}
} else {
clone_default_language(active_context)
};
let direction = if let Some(active_property_definition) = active_property_definition {
if let Some(direction) = &active_property_definition.direction {
direction.clone()
} else {
clone_default_base_direction(active_context)
}
} else {
clone_default_base_direction(active_context)
};
return Ok(Object::Value(Value::LangString(LangString::new(str, language, direction))).into())
}
},
Some(typ) => {
if let Ok(typ) = typ.into_ref() {
tys.insert(typ);
} else {
return Err(ErrorCode::InvalidTypeValue.into())
}
}
}
Ok(Object::Value(Value::Literal(result, tys)).into())
}
}
}