use crate::client::IdentifiedData;
use crate::client::accessors::impl_sbol_identified;
use crate::client::builder::{
ConstraintBuilder, InteractionBuilder, InterfaceBuilder, ParticipationBuilder,
VariableFeatureBuilder,
};
use crate::client::shared::{iris, resources};
use crate::client::to_rdf::{Emitter, emit_identified, seed_triples};
use crate::client::{ToRdf, TryFromObject};
use crate::document::Document;
use crate::error::BuildError;
use crate::identity::DisplayId;
use crate::vocab::*;
use crate::{Iri, Object, Resource, SbolClass, Triple};
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct Constraint {
pub identity: Resource,
pub identified: IdentifiedData,
pub subject: Option<Resource>,
pub constrained_object: Option<Resource>,
pub restriction: Option<Iri>,
}
impl Constraint {
pub fn new(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
subject: Resource,
constrained_object: Resource,
restriction: Iri,
) -> Result<Self, BuildError> {
Self::builder(parent, display_id)?
.subject(subject)
.constrained_object(constrained_object)
.restriction(restriction)
.build()
}
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<ConstraintBuilder, BuildError> {
ConstraintBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for Constraint {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = seed_triples(&self.identity, SbolClass::Constraint);
let mut e = Emitter::new(&mut triples, &self.identity, SbolClass::Constraint);
emit_identified(&mut e, &self.identified)?;
e.resource(SBOL_SUBJECT, self.subject.as_ref())?;
e.resource(SBOL_OBJECT, self.constrained_object.as_ref())?;
e.iri(SBOL_RESTRICTION, self.restriction.as_ref())?;
drop(e);
Ok(triples)
}
}
impl TryFromObject for Constraint {
fn try_from_object(object: &Object) -> Option<Self> {
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
subject: object.first_resource(SBOL_SUBJECT).cloned(),
constrained_object: object.first_resource(SBOL_OBJECT).cloned(),
restriction: object.first_iri(SBOL_RESTRICTION).cloned(),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct Interaction {
pub identity: Resource,
pub identified: IdentifiedData,
pub types: Vec<Iri>,
pub participations: Vec<Resource>,
}
impl Interaction {
pub fn new(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
types: impl IntoIterator<Item = Iri>,
) -> Result<Self, BuildError> {
Self::builder(parent, display_id)?.types(types).build()
}
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<InteractionBuilder, BuildError> {
InteractionBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for Interaction {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = seed_triples(&self.identity, SbolClass::Interaction);
let mut e = Emitter::new(&mut triples, &self.identity, SbolClass::Interaction);
emit_identified(&mut e, &self.identified)?;
e.iris(SBOL_TYPE, &self.types)?;
e.resources(SBOL_HAS_PARTICIPATION, &self.participations)?;
drop(e);
Ok(triples)
}
}
impl TryFromObject for Interaction {
fn try_from_object(object: &Object) -> Option<Self> {
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
types: iris(object, SBOL_TYPE),
participations: resources(object, SBOL_HAS_PARTICIPATION),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct Interface {
pub identity: Resource,
pub identified: IdentifiedData,
pub inputs: Vec<Resource>,
pub outputs: Vec<Resource>,
pub nondirectional: Vec<Resource>,
}
impl Interface {
pub fn new(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<Self, BuildError> {
Self::builder(parent, display_id)?.build()
}
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<InterfaceBuilder, BuildError> {
InterfaceBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for Interface {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = seed_triples(&self.identity, SbolClass::Interface);
let mut e = Emitter::new(&mut triples, &self.identity, SbolClass::Interface);
emit_identified(&mut e, &self.identified)?;
e.resources(SBOL_INPUT, &self.inputs)?;
e.resources(SBOL_OUTPUT, &self.outputs)?;
e.resources(SBOL_NONDIRECTIONAL, &self.nondirectional)?;
drop(e);
Ok(triples)
}
}
impl TryFromObject for Interface {
fn try_from_object(object: &Object) -> Option<Self> {
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
inputs: resources(object, SBOL_INPUT),
outputs: resources(object, SBOL_OUTPUT),
nondirectional: resources(object, SBOL_NONDIRECTIONAL),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct Participation {
pub identity: Resource,
pub identified: IdentifiedData,
pub roles: Vec<Iri>,
pub participant: Option<Resource>,
pub higher_order_participant: Option<Resource>,
}
impl Participation {
pub fn new(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
roles: impl IntoIterator<Item = Iri>,
) -> Result<Self, BuildError> {
Self::builder(parent, display_id)?.roles(roles).build()
}
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<ParticipationBuilder, BuildError> {
ParticipationBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for Participation {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = seed_triples(&self.identity, SbolClass::Participation);
let mut e = Emitter::new(&mut triples, &self.identity, SbolClass::Participation);
emit_identified(&mut e, &self.identified)?;
e.iris(SBOL_ROLE, &self.roles)?;
e.resource(SBOL_PARTICIPANT, self.participant.as_ref())?;
e.resource(
SBOL_HIGHER_ORDER_PARTICIPANT,
self.higher_order_participant.as_ref(),
)?;
drop(e);
Ok(triples)
}
}
impl TryFromObject for Participation {
fn try_from_object(object: &Object) -> Option<Self> {
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
roles: iris(object, SBOL_ROLE),
participant: object.first_resource(SBOL_PARTICIPANT).cloned(),
higher_order_participant: object
.first_resource(SBOL_HIGHER_ORDER_PARTICIPANT)
.cloned(),
})
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct VariableFeature {
pub identity: Resource,
pub identified: IdentifiedData,
pub cardinality: Option<Iri>,
pub variable: Option<Resource>,
pub variants: Vec<Resource>,
pub variant_collections: Vec<Resource>,
pub variant_derivations: Vec<Resource>,
pub variant_measures: Vec<Resource>,
}
impl VariableFeature {
pub fn new(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
cardinality: Iri,
variable: Resource,
) -> Result<Self, BuildError> {
Self::builder(parent, display_id)?
.cardinality(cardinality)
.variable(variable)
.build()
}
pub fn builder(
parent: &Resource,
display_id: impl TryInto<DisplayId, Error = BuildError>,
) -> Result<VariableFeatureBuilder, BuildError> {
VariableFeatureBuilder::seed(parent, display_id.try_into()?)
}
}
impl ToRdf for VariableFeature {
fn to_rdf_triples(&self) -> Result<Vec<Triple>, BuildError> {
let mut triples = seed_triples(&self.identity, SbolClass::VariableFeature);
let mut e = Emitter::new(&mut triples, &self.identity, SbolClass::VariableFeature);
emit_identified(&mut e, &self.identified)?;
e.iri(SBOL_CARDINALITY, self.cardinality.as_ref())?;
e.resource(SBOL_VARIABLE, self.variable.as_ref())?;
e.resources(SBOL_VARIANT, &self.variants)?;
e.resources(SBOL_VARIANT_COLLECTION, &self.variant_collections)?;
e.resources(SBOL_VARIANT_DERIVATION, &self.variant_derivations)?;
e.resources(SBOL_VARIANT_MEASURE, &self.variant_measures)?;
drop(e);
Ok(triples)
}
}
impl TryFromObject for VariableFeature {
fn try_from_object(object: &Object) -> Option<Self> {
Some(Self {
identity: object.identity().clone(),
identified: IdentifiedData::from_object(object),
cardinality: object.first_iri(SBOL_CARDINALITY).cloned(),
variable: object.first_resource(SBOL_VARIABLE).cloned(),
variants: resources(object, SBOL_VARIANT),
variant_collections: resources(object, SBOL_VARIANT_COLLECTION),
variant_derivations: resources(object, SBOL_VARIANT_DERIVATION),
variant_measures: resources(object, SBOL_VARIANT_MEASURE),
})
}
}
impl_sbol_identified!(
Constraint,
Interaction,
Interface,
Participation,
VariableFeature
);
impl Participation {
pub fn parent_interaction<'a>(&self, doc: &'a Document) -> Option<&'a Interaction> {
doc.interactions().find(|interaction| {
interaction
.participations
.iter()
.any(|p| p == &self.identity)
})
}
}