fastobo_graphs/from_graph/
entity.rs1use std::str::FromStr;
2use std::string::ToString;
3
4use fastobo::ast::ClassIdent;
5use fastobo::ast::CreationDate;
6use fastobo::ast::Definition;
7use fastobo::ast::EntityFrame;
8use fastobo::ast::Ident;
9use fastobo::ast::InstanceClause;
10use fastobo::ast::InstanceFrame;
11use fastobo::ast::InstanceIdent;
12use fastobo::ast::Line;
13use fastobo::ast::LiteralPropertyValue;
14use fastobo::ast::PrefixedIdent;
15use fastobo::ast::PropertyValue;
16use fastobo::ast::QuotedString;
17use fastobo::ast::RelationIdent;
18use fastobo::ast::ResourcePropertyValue;
19use fastobo::ast::SubsetIdent;
20use fastobo::ast::Synonym;
21use fastobo::ast::TermClause;
22use fastobo::ast::TermFrame;
23use fastobo::ast::TypedefClause;
24use fastobo::ast::TypedefFrame;
25use fastobo::ast::UnquotedString;
26use fastobo::ast::Xref;
27use fastobo::ast::XrefList;
28
29use crate::constants::property::dc;
30use crate::constants::property::iao;
31use crate::constants::property::obo_in_owl;
32use crate::constants::property::rdfs;
33use crate::error::Error;
34use crate::error::Result;
35
36use crate::model::BasicPropertyValue;
37use crate::model::DefinitionPropertyValue;
38use crate::model::Meta;
39use crate::model::Node;
40use crate::model::NodeType;
41
42use super::FromGraph;
43
44macro_rules! impl_frame_inner {
47 ($node:expr, $id: expr, $ident: ident, $variant: ident) => {{
48 mashup! {
49 m[Variant] = $variant;
50 m[Frame] = $variant Frame;
51 m[Clause] = $variant Clause;
52 }
53 m! {
54 let mut frame = Frame::new(Line::from($ident::from($id)));
55 if let Some(label) = $node.label {
56 let name = Clause::Name(Box::new(UnquotedString::new(label)));
57 frame.push(Line::from(name));
58 }
59 if let Some(meta) = $node.meta {
60 let clauses: Vec<Clause> = FromGraph::from_graph(*meta)?;
61 frame.extend(clauses.into_iter().map(Line::from));
62 }
63 Ok(Some(EntityFrame::Variant(Box::new(frame))))
64 }
65 }};
66}
67
68impl FromGraph<Node> for Option<EntityFrame> {
69 fn from_graph(node: Node) -> Result<Self> {
70 let id = Ident::from_str(&node.id)?;
71 match node.ty {
72 None => Ok(None),
73 Some(NodeType::Class) => impl_frame_inner!(node, id, ClassIdent, Term),
74 Some(NodeType::Individual) => impl_frame_inner!(node, id, InstanceIdent, Instance),
75 Some(NodeType::Property) => {
76 match impl_frame_inner!(node, id, RelationIdent, Typedef) {
78 Ok(Some(EntityFrame::Typedef(mut frame))) => {
79 if let Some((idx, _)) = frame.iter().enumerate().find(|(_, c)| {
80 if let TypedefClause::PropertyValue(pv) = c.as_inner() {
81 if let PropertyValue::Literal(lpv) = pv.as_ref() {
82 match lpv.property().as_ref() {
83 Ident::Url(url) => url.as_str() == obo_in_owl::SHORTHAND,
84 _ => false,
85 }
86 } else {
87 false
88 }
89 } else {
90 false
91 }
92 }) {
93 let new_id = match frame.remove(idx).into_inner() {
94 TypedefClause::PropertyValue(pv) => match *pv {
95 PropertyValue::Resource(rpv) => {
96 RelationIdent::from(rpv.target().clone())
97 }
98 _ => unreachable!(),
99 },
100 _ => unreachable!(),
101 };
102 *frame.id_mut() = new_id.into();
103 }
104 Ok(Some(EntityFrame::Typedef(frame)))
105 }
106 other => other,
107 }
108 }
109 }
110 }
111}
112
113macro_rules! impl_meta {
116 ($clause:ident) => {
117 impl FromGraph<Meta> for Vec<$clause> {
118 fn from_graph(meta: Meta) -> Result<Self> {
119 let mut clauses = Vec::new();
120 if let Some(desc) = meta.definition {
121 clauses.push($clause::from_graph(*desc)?)
122 }
123 for comment in meta.comments {
124 clauses.push($clause::Comment(Box::new(UnquotedString::new(comment))));
125 }
126 for subset in meta.subsets {
127 let id = SubsetIdent::from_str(&subset)?;
128 clauses.push($clause::Subset(Box::new(id)));
129 }
130 for xref in meta.xrefs {
131 clauses.push($clause::Xref(Box::new(Xref::from_graph(xref)?)));
132 }
133 for synonym in meta.synonyms {
134 clauses.push($clause::Synonym(Box::new(Synonym::from_graph(synonym)?)));
135 }
136 for pv in meta.basic_property_values {
137 clauses.push($clause::from_graph(pv)?);
138 }
139 if meta.deprecated {
140 clauses.push($clause::IsObsolete(true));
141 }
142 Ok(clauses)
143 }
144 }
145 };
146}
147
148impl_meta!(TermClause);
149impl_meta!(TypedefClause);
150impl_meta!(InstanceClause);
151
152macro_rules! impl_definition_pv {
155 ($clause:ident) => {
156 impl FromGraph<DefinitionPropertyValue> for $clause {
157 fn from_graph(pv: DefinitionPropertyValue) -> Result<Self> {
158 let value = QuotedString::new(pv.val);
159 let xrefs = pv
160 .xrefs
161 .into_iter()
162 .map(|id: String| Ident::from_str(&id).map(Xref::new).map_err(Error::from))
163 .collect::<Result<XrefList>>()?;
164 Ok($clause::Def(Box::new(Definition::with_xrefs(value, xrefs))))
165 }
166 }
167 };
168}
169
170impl_definition_pv!(TermClause);
171impl_definition_pv!(TypedefClause);
172impl_definition_pv!(InstanceClause);
173
174macro_rules! impl_basic_pv_common {
177 ($pv:ident, $clause:ident, $x:ident $(, $l:pat => $r:expr )* ) => {{
178 match $x {
179 rdfs::COMMENT => {
180 Ok($clause::Comment(Box::new(UnquotedString::new($pv.val))))
181 },
182 obo_in_owl::HAS_ALTERNATIVE_ID => {
183 let id = Ident::from_str(&$pv.val)?;
184 Ok($clause::AltId(Box::new(id.into())))
185 },
186 obo_in_owl::HAS_OBO_NAMESPACE => {
187 let id = Ident::from_str(&$pv.val)?;
188 Ok($clause::Namespace(Box::new(id.into())))
189 },
190 obo_in_owl::CREATED_BY | dc::CREATOR => {
191 Ok($clause::CreatedBy(Box::new(UnquotedString::new($pv.val))))
192 }
193 obo_in_owl::CREATION_DATE | dc::DATE => {
194 let date = CreationDate::from_str(&$pv.val)?;
195 Ok($clause::CreationDate(Box::new(date)))
196 }
197 iao::REPLACED_BY => {
198 let id = Ident::from_str(&$pv.val)?;
199 Ok($clause::ReplacedBy(Box::new(id.into())))
200 }
201 $( $l => $r ),*
202 other => {
203 let rel = RelationIdent::from_str(&other)?;
204 let pv = match Ident::from_str(&$pv.val) {
205 Ok(id) => PropertyValue::from(ResourcePropertyValue::new(rel, id)),
206 Err(_) => PropertyValue::from(LiteralPropertyValue::new(
207 rel,
208 QuotedString::new($pv.val),
209 Ident::from(PrefixedIdent::new("xsd", "string"))
210 ))
211 };
212 Ok($clause::PropertyValue(Box::new(pv)))
213 },
214 }
215 }};
216}
217
218impl FromGraph<BasicPropertyValue> for TermClause {
219 fn from_graph(pv: BasicPropertyValue) -> Result<Self> {
220 let s = pv.pred.as_str();
221 impl_basic_pv_common!(pv, TermClause, s)
222 }
223}
224
225impl FromGraph<BasicPropertyValue> for TypedefClause {
226 fn from_graph(pv: BasicPropertyValue) -> Result<Self> {
227 let s = pv.pred.as_str();
228 impl_basic_pv_common!(pv, TypedefClause, s,
229 obo_in_owl::IS_CYCLIC => {
230 match bool::from_str(&pv.val) {
231 Ok(b) => Ok(TypedefClause::IsCyclic(b)),
232 Err(e) => Err(Error::InvalidBoolean(e, pv.val.to_string())),
233 }
234 },
235 iao::ANTISYMMETRIC_PROPERTY => {
236 match bool::from_str(&pv.val) {
237 Ok(b) => Ok(TypedefClause::IsAntiSymmetric(b)),
238 Err(e) => Err(Error::InvalidBoolean(e, pv.val.to_string())),
239 }
240 },
241 obo_in_owl::IS_CLASS_LEVEL => {
242 match bool::from_str(&pv.val) {
243 Ok(b) => Ok(TypedefClause::IsClassLevel(b)),
244 Err(e) => Err(Error::InvalidBoolean(e, pv.val.to_string())),
245 }
246 },
247 obo_in_owl::IS_METADATA_TAG => {
248 match bool::from_str(&pv.val) {
249 Ok(b) => Ok(TypedefClause::IsMetadataTag(b)),
250 Err(e) => Err(Error::InvalidBoolean(e, pv.val.to_string())),
251 }
252 }
253 )
254 }
255}
256
257impl FromGraph<BasicPropertyValue> for InstanceClause {
258 fn from_graph(pv: BasicPropertyValue) -> Result<Self> {
259 let s = pv.pred.as_str();
260 impl_basic_pv_common!(pv, InstanceClause, s)
261 }
262}