phenopacket_builder/v2/core/
individual.rs1use crate::{Build, Buildable, Set, Unset};
2use phenopackets::schema::v2::core::time_element::Element;
3use phenopackets::schema::v2::core::vital_status::Status;
4use phenopackets::schema::v2::core::{
5 Age, GestationalAge, Individual, KaryotypicSex, OntologyClass, Sex, TimeElement, VitalStatus,
6};
7use std::marker::PhantomData;
8
9#[derive(Debug, Default, Clone, PartialEq)]
10pub struct IndividualBuilder<T = Unset> {
11 id: Option<String>,
12 alternate_ids: Vec<String>,
13 date_of_birth: Option<prost_types::Timestamp>,
14 time_at_last_encounter: Option<TimeElement>,
15 vital_status: Option<VitalStatus>,
16 sex: Sex,
17 karyotypic_sex: KaryotypicSex,
18 gender: Option<OntologyClass>,
19 taxonomy: Option<OntologyClass>,
20 data: PhantomData<T>,
21}
22
23impl<T> IndividualBuilder<T> {
24 pub fn add_alternate_id(mut self, id: impl Into<String>) -> Self {
25 self.alternate_ids.push(id.into());
26 self
27 }
28
29 pub fn extend_alternate_ids(
30 mut self,
31 ids: impl IntoIterator<Item = impl Into<String>>,
32 ) -> Self {
33 self.alternate_ids.extend(ids.into_iter().map(Into::into));
34 self
35 }
36
37 pub fn clear_alternate_ids(mut self) -> Self {
38 self.alternate_ids.clear();
39 self
40 }
41
42 pub fn date_of_birth(mut self, date: impl Build<prost_types::Timestamp>) -> Self {
43 self.date_of_birth = Some(date.build());
44 self
45 }
46
47 pub fn time_at_last_encounter(
48 mut self,
49 time_at_last_encounter: impl Build<TimeElement>,
50 ) -> Self {
51 self.time_at_last_encounter = Some(time_at_last_encounter.build());
52 self
53 }
54
55 pub fn vital_status(mut self, vital_status: impl Build<VitalStatus>) -> Self {
56 self.vital_status = Some(vital_status.build());
57 self
58 }
59
60 pub fn deceased(mut self) -> Self {
61 self.vital_status = Some(VitalStatus::builder().deceased().build());
62 self
63 }
64
65 pub fn deceased_at(mut self, time_of_death: impl Into<TimeElement>) -> Self {
66 self.vital_status = Some(
67 VitalStatus::builder()
68 .deceased()
69 .time_of_death(time_of_death)
70 .build(),
71 );
72 self
73 }
74
75 pub fn alive(mut self) -> Self {
76 self.vital_status = Some(VitalStatus::builder().alive().build());
77 self
78 }
79
80 pub fn sex(mut self, sex: impl Into<Sex>) -> Self {
81 self.sex = sex.into();
82 self
83 }
84
85 pub fn male(self) -> Self {
86 self.sex(Sex::Male)
87 }
88
89 pub fn female(self) -> Self {
90 self.sex(Sex::Female)
91 }
92
93 pub fn other_sex(self) -> Self {
94 self.sex(Sex::OtherSex)
95 }
96
97 pub fn karyotypic_sex(mut self, karyotypic_sex: impl Into<KaryotypicSex>) -> Self {
98 self.karyotypic_sex = karyotypic_sex.into();
99 self
100 }
101
102 pub fn karyotypic_sex_xx(self) -> Self {
103 self.karyotypic_sex(KaryotypicSex::Xx)
104 }
105
106 pub fn karyotypic_sex_xy(self) -> Self {
107 self.karyotypic_sex(KaryotypicSex::Xy)
108 }
109
110 pub fn karyotypic_sex_xo(self) -> Self {
111 self.karyotypic_sex(KaryotypicSex::Xo)
112 }
113
114 pub fn karyotypic_sex_xxy(self) -> Self {
115 self.karyotypic_sex(KaryotypicSex::Xxy)
116 }
117
118 pub fn karyotypic_sex_xxyy(self) -> Self {
119 self.karyotypic_sex(KaryotypicSex::Xxyy)
120 }
121
122 pub fn karyotypic_sex_xxxy(self) -> Self {
123 self.karyotypic_sex(KaryotypicSex::Xxxy)
124 }
125
126 pub fn karyotypic_sex_xxxx(self) -> Self {
127 self.karyotypic_sex(KaryotypicSex::Xxxx)
128 }
129
130 pub fn karyotypic_sex_xyy(self) -> Self {
131 self.karyotypic_sex(KaryotypicSex::Xyy)
132 }
133
134 pub fn karyotypic_sex_other(self) -> Self {
135 self.karyotypic_sex(KaryotypicSex::OtherKaryotype)
136 }
137
138 pub fn gender(mut self, gender: impl Build<OntologyClass>) -> Self {
139 self.gender = Some(gender.build());
140 self
141 }
142
143 pub fn taxonomy(mut self, taxonomy: impl Build<OntologyClass>) -> Self {
144 self.taxonomy = Some(taxonomy.build());
145 self
146 }
147
148 pub fn homo_sapiens(self) -> Self {
149 self.taxonomy(OntologyClass::builder().id_label("NCBITaxon:9606", "homo sapiens"))
150 }
151}
152
153impl IndividualBuilder<Unset> {
154 pub fn id(self, id: impl Into<String>) -> IndividualBuilder<Set> {
155 IndividualBuilder {
156 id: Some(id.into()),
157 alternate_ids: self.alternate_ids,
158 date_of_birth: self.date_of_birth,
159 time_at_last_encounter: self.time_at_last_encounter,
160 vital_status: self.vital_status,
161 sex: self.sex,
162 karyotypic_sex: self.karyotypic_sex,
163 gender: self.gender,
164 taxonomy: self.taxonomy,
165 data: PhantomData,
166 }
167 }
168}
169impl Buildable for Individual {
170 type Builder = IndividualBuilder;
171}
172
173impl Build<Individual> for IndividualBuilder<Set> {
174 fn build(self) -> Individual {
175 Individual {
176 id: self.id.expect("id must have been set"),
177 alternate_ids: self.alternate_ids,
178 date_of_birth: self.date_of_birth,
179 time_at_last_encounter: self.time_at_last_encounter,
180 vital_status: self.vital_status,
181 sex: self.sex.into(),
182 karyotypic_sex: self.karyotypic_sex.into(),
183 gender: self.gender,
184 taxonomy: self.taxonomy,
185 }
186 }
187}
188
189#[derive(Debug, Default, Clone, PartialEq)]
190pub struct VitalStatusBuilder<T = Unset> {
191 status: Option<Status>,
192 time_of_death: Option<TimeElement>,
193 cause_of_death: Option<OntologyClass>,
194 survival_time_in_days: Option<u32>,
195 data: PhantomData<T>,
196}
197
198impl<T> VitalStatusBuilder<T> {
199 pub fn status(self, status: impl Into<Status>) -> VitalStatusBuilder<Set> {
200 VitalStatusBuilder {
201 status: Some(status.into()),
202 time_of_death: self.time_of_death,
203 cause_of_death: self.cause_of_death,
204 survival_time_in_days: self.survival_time_in_days,
205 data: PhantomData,
206 }
207 }
208
209 pub fn alive(self) -> VitalStatusBuilder<Set> {
210 self.status(Status::Alive)
211 }
212
213 pub fn deceased(self) -> VitalStatusBuilder<Set> {
214 self.status(Status::Deceased)
215 }
216
217 pub fn time_of_death(mut self, time_of_death: impl Into<TimeElement>) -> VitalStatusBuilder<T> {
218 self.time_of_death = Some(time_of_death.into());
219 self
220 }
221
222 pub fn time_of_death_at_age(mut self, age: impl Into<Age>) -> VitalStatusBuilder<T> {
223 self.time_of_death = Some(TimeElement {
224 element: Some(Element::Age(age.into())),
225 });
226 self
227 }
228
229 pub fn time_of_death_at_gestational_age(
230 mut self,
231 gestational_age: impl Into<GestationalAge>,
232 ) -> VitalStatusBuilder<T> {
233 self.time_of_death = Some(TimeElement {
234 element: Some(Element::GestationalAge(gestational_age.into())),
235 });
236 self
237 }
238
239 pub fn cause_of_death(
240 mut self,
241 cause_of_death: impl Into<OntologyClass>,
242 ) -> VitalStatusBuilder<T> {
243 self.cause_of_death = Some(cause_of_death.into());
244 self
245 }
246
247 pub fn survival_time_in_days(
248 mut self,
249 survival_time_in_days: impl Into<u32>,
250 ) -> VitalStatusBuilder<T> {
251 self.survival_time_in_days = Some(survival_time_in_days.into());
252 self
253 }
254}
255
256impl Buildable for VitalStatus {
257 type Builder = VitalStatusBuilder;
258}
259
260impl Build<VitalStatus> for VitalStatusBuilder<Set> {
261 fn build(self) -> VitalStatus {
262 VitalStatus {
263 status: self.status.expect("status must have been set").into(),
264 time_of_death: self.time_of_death,
265 cause_of_death: self.cause_of_death,
266 survival_time_in_days: self.survival_time_in_days.unwrap_or_default(),
267 }
268 }
269}