use crate::client::accessors::impl_sbol_identified;
use crate::client::builder::IdentifiedExtensionBuilder;
use crate::client::{IdentifiedData, ToRdf, TopLevelData, TryFromObject};
use crate::error::BuildError;
use crate::identity::DisplayId;
use crate::vocab::*;
use crate::{Iri, Literal, Object, Resource, Term, Triple};
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct IdentifiedExtension {
pub identity: Resource,
pub identified: IdentifiedData,
pub top_level: Option<TopLevelData>,
pub rdf_types: Vec<Iri>,
}
impl IdentifiedExtension {
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<IdentifiedExtensionBuilder, BuildError> {
IdentifiedExtensionBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for IdentifiedExtension {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = Vec::new();
for rdf_type in &self.rdf_types {
triples.push(Triple {
subject: self.identity.clone(),
predicate: Iri::from_static(RDF_TYPE),
object: Term::Resource(Resource::Iri(rdf_type.clone())),
});
}
if !self
.rdf_types
.iter()
.any(|iri| iri.as_str() == SBOL_IDENTIFIED_CLASS)
{
triples.push(Triple {
subject: self.identity.clone(),
predicate: Iri::from_static(RDF_TYPE),
object: Term::Resource(Resource::Iri(Iri::from_static(SBOL_IDENTIFIED_CLASS))),
});
}
push_string(
&mut triples,
&self.identity,
SBOL_DISPLAY_ID,
self.identified.display_id.as_deref(),
);
push_string(
&mut triples,
&self.identity,
SBOL_NAME,
self.identified.name.as_deref(),
);
push_string(
&mut triples,
&self.identity,
SBOL_DESCRIPTION,
self.identified.description.as_deref(),
);
for value in &self.identified.derived_from {
push_resource(
&mut triples,
&self.identity,
PROV_WAS_DERIVED_FROM,
value.clone(),
);
}
for value in &self.identified.generated_by {
push_resource(
&mut triples,
&self.identity,
PROV_WAS_GENERATED_BY,
value.clone(),
);
}
for value in &self.identified.measures {
push_resource(
&mut triples,
&self.identity,
SBOL_HAS_MEASURE,
value.clone(),
);
}
for extension in &self.identified.extensions {
triples.push(Triple {
subject: self.identity.clone(),
predicate: extension.predicate.clone(),
object: extension.object.clone(),
});
}
if let Some(top_level) = &self.top_level {
if let Some(namespace) = &top_level.namespace {
push_resource(
&mut triples,
&self.identity,
SBOL_HAS_NAMESPACE,
Resource::Iri(namespace.clone()),
);
}
for attachment in &top_level.attachments {
push_resource(
&mut triples,
&self.identity,
SBOL_HAS_ATTACHMENT,
attachment.clone(),
);
}
}
Ok(triples)
}
}
impl TryFromObject for IdentifiedExtension {
fn try_from_object(object: &Object) -> Option<Self> {
let rdf_types: Vec<Iri> = object.rdf_types().iter().cloned().collect();
let top_level = object
.is_top_level()
.then(|| TopLevelData::from_object(object));
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
top_level,
rdf_types,
})
}
}
fn push_string(
triples: &mut Vec<Triple>,
identity: &Resource,
predicate: &'static str,
value: Option<&str>,
) {
if let Some(value) = value {
triples.push(Triple {
subject: identity.clone(),
predicate: Iri::from_static(predicate),
object: Term::Literal(Literal::simple(value)),
});
}
}
fn push_resource(
triples: &mut Vec<Triple>,
identity: &Resource,
predicate: &'static str,
value: Resource,
) {
triples.push(Triple {
subject: identity.clone(),
predicate: Iri::from_static(predicate),
object: Term::Resource(value),
});
}
impl_sbol_identified!(IdentifiedExtension);