1use super::{
2 Connection, GenericInstanciation, ModelInstanciation, Reference, Scope, TreatmentInstanciation,
3 IO,
4};
5use crate::descriptor::Treatment as TreatmentDescriptor;
6use crate::design::{
7 Connection as ConnectionDesign, ModelInstanciation as ModelInstanciationDesign,
8 Parameter as ParameterDesign, Treatment as TreatmentDesign,
9 TreatmentInstanciation as TreatmentInstanciationDesign, IO as IODesign,
10};
11use crate::error::{LogicError, LogicResult};
12use core::fmt::Debug;
13use melodium_common::descriptor::{
14 Attribuable, Attributes, Collection, DescribedType, Entry, Generics, Identified, Identifier,
15 IdentifierRequirement, Parameterized, Treatment as TreatmentTrait,
16};
17use std::collections::HashMap;
18use std::sync::{Arc, RwLock, RwLockReadGuard, Weak};
19
20#[derive(Debug)]
21pub struct Treatment {
22 collection: Arc<Collection>,
23 descriptor: Weak<TreatmentDescriptor>,
24
25 generics: Arc<RwLock<HashMap<String, DescribedType>>>,
26 model_instanciations: HashMap<String, Arc<RwLock<ModelInstanciation>>>,
27 treatments: HashMap<String, Arc<RwLock<TreatmentInstanciation>>>,
28 connections: Vec<Connection>,
29
30 design_reference: Option<Arc<dyn Reference>>,
31
32 auto_reference: Weak<RwLock<Self>>,
33}
34
35impl Treatment {
36 pub fn new(
37 descriptor: &Arc<TreatmentDescriptor>,
38 collection: Arc<Collection>,
39 design_reference: Option<Arc<dyn Reference>>,
40 ) -> Arc<RwLock<Self>> {
41 Arc::<RwLock<Self>>::new_cyclic(|me| {
42 RwLock::new(Self {
43 descriptor: Arc::downgrade(descriptor),
44 collection,
45 generics: Arc::new(RwLock::new(
46 descriptor
48 .generics()
49 .iter()
50 .map(|generic| {
51 (
52 generic.name.clone(),
53 DescribedType::Generic(Box::new(generic.clone())),
54 )
55 })
56 .collect(),
57 )),
58 model_instanciations: HashMap::new(),
59 treatments: HashMap::new(),
60 connections: Vec::new(),
61 design_reference,
62 auto_reference: me.clone(),
63 })
64 })
65 }
66
67 pub fn collection(&self) -> &Arc<Collection> {
68 &self.collection
69 }
70
71 pub fn descriptor(&self) -> Arc<TreatmentDescriptor> {
72 self.descriptor.upgrade().unwrap()
73 }
74
75 pub fn design_reference(&self) -> &Option<Arc<dyn Reference>> {
76 &self.design_reference
77 }
78
79 pub fn import_design(
80 &mut self,
81 design: &TreatmentDesign,
82 replace: &HashMap<Identifier, Identifier>,
83 design_reference: Option<Arc<dyn Reference>>,
84 ) -> LogicResult<()> {
85 let mut result = LogicResult::new_success(());
86
87 for (name, model_instanciation_design) in &design.model_instanciations {
88 let model_identifier = model_instanciation_design
89 .descriptor
90 .upgrade()
91 .unwrap()
92 .identifier()
93 .clone();
94 let model_identifier = replace.get(&model_identifier).unwrap_or(&model_identifier);
95 if let Some(model_instanciation) =
96 result.merge_degrade_failure(self.add_model_instanciation(
97 &model_identifier.into(),
98 name,
99 design_reference.clone(),
100 ))
101 {
102 result.merge_degrade_failure(model_instanciation.write().unwrap().import_design(
103 model_instanciation_design,
104 &self.collection,
105 replace,
106 ));
107 }
108 }
109
110 for (name, treatment_instanciation_design) in &design.treatments {
111 let treatment_identifier = treatment_instanciation_design
112 .descriptor
113 .upgrade()
114 .unwrap()
115 .identifier()
116 .clone();
117 let treatment_identifier = replace
118 .get(&treatment_identifier)
119 .unwrap_or(&treatment_identifier);
120 if let Some(treatment_instanciation) = result.merge_degrade_failure(self.add_treatment(
121 &treatment_identifier.into(),
122 name,
123 design_reference.clone(),
124 )) {
125 result.merge_degrade_failure(
126 treatment_instanciation.write().unwrap().import_design(
127 treatment_instanciation_design,
128 &self.collection,
129 replace,
130 ),
131 );
132 }
133 }
134
135 for connection in &design.connections {
136 match (&connection.output_treatment, &connection.input_treatment) {
137 (IODesign::Sequence(), IODesign::Sequence()) => {
138 result.merge_degrade_failure(self.add_self_connection(
139 &connection.output_name,
140 &connection.input_name,
141 connection.attributes().clone(),
142 design_reference.clone(),
143 ))
144 }
145 (IODesign::Sequence(), IODesign::Treatment(input_treatment)) => result
146 .merge_degrade_failure(self.add_input_connection(
147 &connection.output_name,
148 input_treatment,
149 &connection.input_name,
150 connection.attributes().clone(),
151 design_reference.clone(),
152 )),
153 (IODesign::Treatment(output_treatment), IODesign::Sequence()) => result
154 .merge_degrade_failure(self.add_output_connection(
155 &connection.input_name,
156 output_treatment,
157 &connection.output_name,
158 connection.attributes().clone(),
159 design_reference.clone(),
160 )),
161 (IODesign::Treatment(output_treatment), IODesign::Treatment(input_treatment)) => {
162 result.merge_degrade_failure(self.add_connection(
163 output_treatment,
164 &connection.output_name,
165 input_treatment,
166 &connection.input_name,
167 connection.attributes().clone(),
168 design_reference.clone(),
169 ))
170 }
171 };
172 }
173
174 result
175 }
176
177 pub fn add_model_instanciation(
178 &mut self,
179 model_identifier: &IdentifierRequirement,
180 name: &str,
181 design_reference: Option<Arc<dyn Reference>>,
182 ) -> LogicResult<Arc<RwLock<ModelInstanciation>>> {
183 if self.model_instanciations.contains_key(name) {
184 return Err(LogicError::already_declared_model(
185 209,
186 self.descriptor().identifier().clone(),
187 name.to_string(),
188 design_reference.clone(),
189 ))
190 .into();
191 }
192 if let Some(Entry::Model(model_descriptor)) = self.collection.get(model_identifier) {
193 let model = ModelInstanciation::new(
194 &(self.descriptor() as Arc<dyn TreatmentTrait>),
195 &self.auto_reference.upgrade().unwrap(),
196 self.identifier(),
197 model_descriptor,
198 name,
199 design_reference.clone(),
200 );
201 self.model_instanciations
202 .insert(name.to_string(), Arc::clone(&model));
203 Ok(model).into()
204 } else {
205 Err(LogicError::unexisting_model(
206 41,
207 self.descriptor().identifier().clone(),
208 model_identifier.clone(),
209 design_reference.clone(),
210 ))
211 .into()
212 }
213 }
214
215 pub fn rename_model_instanciation(
216 &mut self,
217 actual_name: &str,
218 new_name: &str,
219 design_reference: Option<Arc<dyn Reference>>,
220 ) -> LogicResult<()> {
221 let mut result = LogicResult::new_success(());
222 if self.model_instanciations.contains_key(new_name) {
223 result = result.and_degrade_failure(LogicResult::new_failure(
224 LogicError::already_declared_model(
225 211,
226 self.descriptor().identifier().clone(),
227 new_name.to_string(),
228 design_reference.clone(),
229 ),
230 ));
231 }
232 if let Some(model_instanciation) = self.model_instanciations.remove(actual_name) {
233 model_instanciation
234 .write()
235 .unwrap()
236 .set_name(new_name.to_string());
237 self.model_instanciations
238 .insert(new_name.to_string(), model_instanciation);
239
240 for (_, treatment) in &self.treatments {
241 let mut treatment = treatment.write().unwrap();
242 let to_replace = treatment
243 .models()
244 .iter()
245 .filter_map(|(parametric_name, local_name)| {
246 if local_name == actual_name {
247 Some(parametric_name.clone())
248 } else {
249 None
250 }
251 })
252 .collect::<Vec<_>>();
253 for name in to_replace {
254 let _ = treatment.add_model(&name, new_name);
255 }
256 }
257 result
258 } else {
259 result.and_degrade_failure(LogicResult::new_failure(LogicError::undeclared_model(
260 212,
261 self.descriptor().identifier().clone(),
262 actual_name.to_string(),
263 design_reference.clone(),
264 )))
265 }
266 }
267
268 pub fn remove_model_instanciation(&mut self, name: &str) -> LogicResult<bool> {
269 Ok(if let Some(_) = self.model_instanciations.remove(name) {
270 for (_, treatment) in &self.treatments {
271 let mut treatment = treatment.write().unwrap();
272 let to_remove = treatment
273 .models()
274 .iter()
275 .filter_map(|(parametric_name, local_name)| {
276 if local_name == name {
277 Some(parametric_name.clone())
278 } else {
279 None
280 }
281 })
282 .collect::<Vec<_>>();
283 for name in to_remove {
284 let _ = treatment.remove_model(&name);
285 }
286 }
287
288 true
289 } else {
290 false
291 })
292 .into()
293 }
294
295 pub fn add_treatment(
296 &mut self,
297 treatment_identifier: &IdentifierRequirement,
298 name: &str,
299 design_reference: Option<Arc<dyn Reference>>,
300 ) -> LogicResult<Arc<RwLock<TreatmentInstanciation>>> {
301 if self.treatments.contains_key(name) {
302 return Err(LogicError::already_declared_treatment(
303 210,
304 self.descriptor().identifier().clone(),
305 name.to_string(),
306 design_reference.clone(),
307 ))
308 .into();
309 }
310 if let Some(Entry::Treatment(treatment_descriptor)) =
311 self.collection.get(treatment_identifier)
312 {
313 let rc_treatment = TreatmentInstanciation::new(
314 &(self.descriptor() as Arc<dyn TreatmentTrait>),
315 &self.auto_reference.upgrade().unwrap(),
316 &self.generics,
317 self.identifier(),
318 &treatment_descriptor,
319 name,
320 design_reference.clone(),
321 );
322 self.treatments
323 .insert(name.to_string(), Arc::clone(&rc_treatment));
324 Ok(rc_treatment).into()
325 } else {
326 Err(LogicError::unexisting_treatment(
327 40,
328 self.descriptor().identifier().clone(),
329 treatment_identifier.clone(),
330 design_reference.clone(),
331 ))
332 .into()
333 }
334 }
335
336 pub fn rename_treatment(
337 &mut self,
338 actual_name: &str,
339 new_name: &str,
340 design_reference: Option<Arc<dyn Reference>>,
341 ) -> LogicResult<()> {
342 let mut result = LogicResult::new_success(());
343 if self.treatments.contains_key(new_name) {
344 result = result.and_degrade_failure(LogicResult::new_failure(
345 LogicError::already_declared_treatment(
346 212,
347 self.descriptor().identifier().clone(),
348 new_name.to_string(),
349 design_reference.clone(),
350 ),
351 ));
352 }
353 if let Some(treatment) = self.treatments.remove(actual_name) {
354 treatment.write().unwrap().set_name(new_name.to_string());
355 self.treatments.insert(new_name.to_string(), treatment);
356
357 result
358 } else {
359 result.and_degrade_failure(LogicResult::new_failure(LogicError::undeclared_treatment(
360 213,
361 self.descriptor().identifier().clone(),
362 actual_name.to_string(),
363 design_reference.clone(),
364 )))
365 }
366 }
367
368 pub fn remove_treatment(&mut self, name: &str) -> LogicResult<bool> {
369 Ok(if let Some(ref treatment) = self.treatments.remove(name) {
370 self.connections.retain(|conn| {
371 let mut result = true;
372 if let IO::Treatment(input_treatment) = &conn.input_treatment {
373 result &= !input_treatment.ptr_eq(&Arc::downgrade(treatment));
374 }
375 if let IO::Treatment(output_treatment) = &conn.output_treatment {
376 result &= !output_treatment.ptr_eq(&Arc::downgrade(treatment));
377 }
378
379 result
380 });
381
382 true
383 } else {
384 false
385 })
386 .into()
387 }
388
389 pub fn add_connection(
390 &mut self,
391 output_treatment: &str,
392 output_name: &str,
393 input_treatment: &str,
394 input_name: &str,
395 attributes: Attributes,
396 design_reference: Option<Arc<dyn Reference>>,
397 ) -> LogicResult<()> {
398 let mut result = LogicResult::new_success(());
399
400 let mut rc_output_treatment = None;
401 let mut output = None;
402 let mut output_treatment_generics = None;
403 if let Some(pos_rc_output_treatment) = self.treatments.get(output_treatment) {
404 rc_output_treatment = Some(pos_rc_output_treatment);
405
406 let output_treatment = pos_rc_output_treatment.read().unwrap();
407 let output_treatment_descriptor = output_treatment.descriptor();
408 output_treatment_generics = Some(Arc::clone(output_treatment.access_generics()));
409
410 if let Some(pos_output) = output_treatment_descriptor.outputs().get(output_name) {
411 output = Some(pos_output.clone());
412 } else {
413 result = result.and_degrade_failure(LogicResult::new_failure(
414 LogicError::connection_output_not_found(
415 36,
416 self.descriptor().identifier().clone(),
417 output_treatment_descriptor.identifier().clone(),
418 output_name.to_string(),
419 design_reference.clone(),
420 ),
421 ));
422 }
423 } else {
424 result = result.and_degrade_failure(LogicResult::new_failure(
425 LogicError::undeclared_treatment(
426 43,
427 self.descriptor().identifier().clone(),
428 output_treatment.to_string(),
429 design_reference.clone(),
430 ),
431 ));
432 }
433
434 let mut rc_input_treatment = None;
435 let mut input = None;
436 let mut input_treatment_generics = None;
437 if let Some(pos_rc_input_treatment) = self.treatments.get(input_treatment) {
438 rc_input_treatment = Some(pos_rc_input_treatment);
439
440 let input_treatment = pos_rc_input_treatment.read().unwrap();
441 let input_treatment_descriptor = input_treatment.descriptor();
442 input_treatment_generics = Some(Arc::clone(input_treatment.access_generics()));
443
444 if let Some(pos_input) = input_treatment_descriptor.inputs().get(input_name) {
445 input = Some(pos_input.clone());
446 } else {
447 result = result.and_degrade_failure(LogicResult::new_failure(
448 LogicError::connection_input_not_found(
449 32,
450 self.descriptor().identifier().clone(),
451 input_treatment_descriptor.identifier().clone(),
452 input_name.to_string(),
453 design_reference.clone(),
454 ),
455 ));
456 }
457 } else {
458 result = result.and_degrade_failure(LogicResult::new_failure(
459 LogicError::undeclared_treatment(
460 44,
461 self.descriptor().identifier().clone(),
462 input_treatment.to_string(),
463 design_reference.clone(),
464 ),
465 ));
466 }
467
468 if let (Some(rc_output_treatment), Some(output), Some(rc_input_treatment), Some(input)) =
469 (rc_output_treatment, output, rc_input_treatment, input)
470 {
471 if input.matches_output(
472 &input_treatment_generics.unwrap().read().unwrap(),
473 &output,
474 &output_treatment_generics.unwrap().read().unwrap(),
475 ) {
476 self.connections.push(Connection::new_internal(
477 output_name,
478 rc_output_treatment,
479 input_name,
480 rc_input_treatment,
481 attributes,
482 design_reference.clone(),
483 ));
484 } else {
485 result = result.and_degrade_failure(LogicResult::new_failure(
486 LogicError::unexisting_connexion_type(
487 47,
488 self.descriptor().identifier().clone(),
489 output_treatment.to_string(),
490 output_name.to_string(),
491 input_treatment.to_string(),
492 input_name.to_string(),
493 *output.flow(),
494 output.described_type().clone(),
495 *input.flow(),
496 input.described_type().clone(),
497 design_reference,
498 ),
499 ));
500 }
501 }
502
503 result
504 }
505
506 pub fn remove_connection(
507 &mut self,
508 output_treatment: &str,
509 output_name: &str,
510 input_treatment: &str,
511 input_name: &str,
512 ) -> LogicResult<bool> {
513 let mut found = false;
514 self.connections.retain(|connection| {
515 if connection.output_name == output_name
516 && connection.input_name == input_name
517 && match &connection.output_treatment {
518 IO::Treatment(t) => {
519 t.upgrade().unwrap().read().unwrap().name() == output_treatment
520 }
521 _ => false,
522 }
523 && match &connection.input_treatment {
524 IO::Treatment(t) => {
525 t.upgrade().unwrap().read().unwrap().name() == input_treatment
526 }
527 _ => false,
528 }
529 {
530 found = true;
531 false
532 } else {
533 true
534 }
535 });
536
537 Ok(found).into()
538 }
539
540 pub fn add_self_connection(
541 &mut self,
542 self_input_name: &str,
543 self_output_name: &str,
544 attributes: Attributes,
545 design_reference: Option<Arc<dyn Reference>>,
546 ) -> LogicResult<()> {
547 let mut result = LogicResult::new_success(());
548
549 let mut input_self = None;
550 if let Some(pos_input) = self.descriptor().inputs().get(self_input_name) {
551 input_self = Some(pos_input.clone());
552 } else {
553 result = result.and_degrade_failure(LogicResult::new_failure(
554 LogicError::connection_self_input_not_found(
555 34,
556 self.descriptor().identifier().clone(),
557 self_input_name.to_string(),
558 design_reference.clone(),
559 ),
560 ));
561 }
562
563 let mut output_self = None;
564 if let Some(pos_output) = self.descriptor().outputs().get(self_output_name) {
565 output_self = Some(pos_output.clone());
566 } else {
567 result = result.and_degrade_failure(LogicResult::new_failure(
568 LogicError::connection_self_output_not_found(
569 38,
570 self.descriptor().identifier().clone(),
571 self_output_name.to_string(),
572 design_reference.clone(),
573 ),
574 ));
575 }
576
577 if let (Some(input_self), Some(output_self)) = (input_self, output_self) {
578 if input_self.matches_output(&self.generics(), &output_self, &self.generics()) {
579 self.connections.push(Connection::new_self(
580 input_self.name(),
581 output_self.name(),
582 attributes,
583 design_reference.clone(),
584 ));
585 } else {
586 result = result.and_degrade_failure(LogicResult::new_failure(
587 LogicError::unexisting_connexion_type(
588 48,
589 self.descriptor().identifier().clone(),
590 "Self".to_string(),
591 self_input_name.to_string(),
592 "Self".to_string(),
593 self_output_name.to_string(),
594 *input_self.flow(),
595 input_self.described_type().clone(),
596 *output_self.flow(),
597 output_self.described_type().clone(),
598 design_reference,
599 ),
600 ));
601 }
602 }
603
604 result
605 }
606
607 pub fn remove_self_connection(
608 &mut self,
609 self_input_name: &str,
610 self_output_name: &str,
611 ) -> LogicResult<bool> {
612 let mut found = false;
613 self.connections.retain(|connection| {
614 if connection.output_name == self_input_name
615 && connection.input_name == self_output_name
616 && match connection.output_treatment {
617 IO::Sequence() => true,
618 _ => false,
619 }
620 && match connection.input_treatment {
621 IO::Sequence() => true,
622 _ => false,
623 }
624 {
625 found = true;
626 false
627 } else {
628 true
629 }
630 });
631
632 Ok(found).into()
633 }
634
635 pub fn add_input_connection(
636 &mut self,
637 self_input_name: &str,
638 input_treatment: &str,
639 input_name: &str,
640 attributes: Attributes,
641 design_reference: Option<Arc<dyn Reference>>,
642 ) -> LogicResult<()> {
643 let mut result = LogicResult::new_success(());
644
645 let mut input_self = None;
646 if let Some(pos_input) = self.descriptor().inputs().get(self_input_name) {
647 input_self = Some(pos_input.clone());
648 } else {
649 result = result.and_degrade_failure(LogicResult::new_failure(
650 LogicError::connection_self_input_not_found(
651 35,
652 self.descriptor().identifier().clone(),
653 self_input_name.to_string(),
654 design_reference.clone(),
655 ),
656 ));
657 }
658
659 let mut rc_input_treatment = None;
660 let mut input = None;
661 let mut input_treatment_generics = None;
662 if let Some(pos_rc_input_treatment) = self.treatments.get(input_treatment) {
663 rc_input_treatment = Some(pos_rc_input_treatment);
664
665 let input_treatment = pos_rc_input_treatment.read().unwrap();
666 let input_treatment_descriptor = input_treatment.descriptor();
667 input_treatment_generics = Some(Arc::clone(input_treatment.access_generics()));
668
669 if let Some(pos_input) = input_treatment_descriptor.inputs().get(input_name) {
670 input = Some(pos_input.clone());
671 } else {
672 result = result.and_degrade_failure(LogicResult::new_failure(
673 LogicError::connection_input_not_found(
674 33,
675 self.descriptor().identifier().clone(),
676 input_treatment_descriptor.identifier().clone(),
677 input_name.to_string(),
678 design_reference.clone(),
679 ),
680 ));
681 }
682 } else {
683 result = result.and_degrade_failure(LogicResult::new_failure(
684 LogicError::undeclared_treatment(
685 45,
686 self.descriptor().identifier().clone(),
687 input_treatment.to_string(),
688 design_reference.clone(),
689 ),
690 ));
691 }
692
693 if let (Some(input_self), Some(rc_input_treatment), Some(input)) =
694 (input_self, rc_input_treatment, input)
695 {
696 if input_self.matches_input(
697 &self.generics(),
698 &input,
699 &input_treatment_generics.unwrap().read().unwrap(),
700 ) {
701 self.connections.push(Connection::new_self_to_internal(
702 input_self.name(),
703 input.name(),
704 rc_input_treatment,
705 attributes,
706 design_reference.clone(),
707 ));
708 } else {
709 result = result.and_degrade_failure(LogicResult::new_failure(
710 LogicError::unexisting_connexion_type(
711 49,
712 self.descriptor().identifier().clone(),
713 "Self".to_string(),
714 self_input_name.to_string(),
715 input_treatment.to_string(),
716 input_name.to_string(),
717 *input_self.flow(),
718 input_self.described_type().clone(),
719 *input.flow(),
720 input.described_type().clone(),
721 design_reference,
722 ),
723 ));
724 }
725 }
726 result
727 }
728
729 pub fn remove_input_connection(
730 &mut self,
731 self_input_name: &str,
732 input_treatment: &str,
733 input_name: &str,
734 ) -> LogicResult<bool> {
735 let mut found = false;
736 self.connections.retain(|connection| {
737 if connection.output_name == self_input_name
738 && connection.input_name == input_name
739 && match connection.output_treatment {
740 IO::Sequence() => true,
741 _ => false,
742 }
743 && match &connection.input_treatment {
744 IO::Treatment(t) => {
745 t.upgrade().unwrap().read().unwrap().name() == input_treatment
746 }
747 _ => false,
748 }
749 {
750 found = true;
751 false
752 } else {
753 true
754 }
755 });
756
757 Ok(found).into()
758 }
759
760 pub fn add_output_connection(
761 &mut self,
762 self_output_name: &str,
763 output_treatment: &str,
764 output_name: &str,
765 attributes: Attributes,
766 design_reference: Option<Arc<dyn Reference>>,
767 ) -> LogicResult<()> {
768 let mut result = LogicResult::new_success(());
769
770 let mut output_self = None;
771 if let Some(pos_output) = self.descriptor().outputs().get(self_output_name) {
772 output_self = Some(pos_output.clone());
773 } else {
774 result = result.and_degrade_failure(LogicResult::new_failure(
775 LogicError::connection_self_output_not_found(
776 39,
777 self.descriptor().identifier().clone(),
778 self_output_name.to_string(),
779 design_reference.clone(),
780 ),
781 ));
782 }
783
784 let mut rc_output_treatment = None;
785 let mut output = None;
786 let mut output_treatment_generics = None;
787 if let Some(pos_rc_output_treatment) = self.treatments.get(output_treatment) {
788 rc_output_treatment = Some(pos_rc_output_treatment);
789
790 let output_treatment = pos_rc_output_treatment.read().unwrap();
791 let output_treatment_descriptor = output_treatment.descriptor();
792 output_treatment_generics = Some(Arc::clone(output_treatment.access_generics()));
793
794 if let Some(pos_output) = output_treatment_descriptor.outputs().get(output_name) {
795 output = Some(pos_output.clone());
796 } else {
797 result = result.and_degrade_failure(LogicResult::new_failure(
798 LogicError::connection_output_not_found(
799 37,
800 self.descriptor().identifier().clone(),
801 output_treatment_descriptor.identifier().clone(),
802 output_name.to_string(),
803 design_reference.clone(),
804 ),
805 ));
806 }
807 } else {
808 result = result.and_degrade_failure(LogicResult::new_failure(
809 LogicError::undeclared_treatment(
810 46,
811 self.descriptor().identifier().clone(),
812 output_treatment.to_string(),
813 design_reference.clone(),
814 ),
815 ));
816 }
817
818 if let (Some(output_self), Some(rc_output_treatment), Some(output)) =
819 (output_self, rc_output_treatment, output)
820 {
821 if output_self.matches_output(
822 &self.generics(),
823 &output,
824 &output_treatment_generics.unwrap().read().unwrap(),
825 ) {
826 self.connections.push(Connection::new_internal_to_self(
827 output.name(),
828 rc_output_treatment,
829 output_self.name(),
830 attributes,
831 design_reference.clone(),
832 ));
833 } else {
834 result = result.and_degrade_failure(LogicResult::new_failure(
835 LogicError::unexisting_connexion_type(
836 50,
837 self.descriptor().identifier().clone(),
838 output_treatment.to_string(),
839 output_name.to_string(),
840 "Self".to_string(),
841 self_output_name.to_string(),
842 *output.flow(),
843 output.described_type().clone(),
844 *output_self.flow(),
845 output_self.described_type().clone(),
846 design_reference,
847 ),
848 ));
849 }
850 }
851
852 result
853 }
854
855 pub fn remove_output_connection(
856 &mut self,
857 self_output_name: &str,
858 output_treatment: &str,
859 output_name: &str,
860 ) -> LogicResult<bool> {
861 let mut found = false;
862 self.connections.retain(|connection| {
863 if connection.output_name == output_name
864 && connection.input_name == self_output_name
865 && match &connection.output_treatment {
866 IO::Treatment(t) => {
867 t.upgrade().unwrap().read().unwrap().name() == output_treatment
868 }
869 _ => false,
870 }
871 && match connection.input_treatment {
872 IO::Sequence() => true,
873 _ => false,
874 }
875 {
876 found = true;
877 false
878 } else {
879 true
880 }
881 });
882
883 Ok(found).into()
884 }
885
886 pub fn model_instanciations(&self) -> &HashMap<String, Arc<RwLock<ModelInstanciation>>> {
887 &self.model_instanciations
888 }
889
890 pub fn treatments(&self) -> &HashMap<String, Arc<RwLock<TreatmentInstanciation>>> {
891 &self.treatments
892 }
893
894 pub fn connections(&self) -> &Vec<Connection> {
895 &self.connections
896 }
897
898 pub fn validate(&self) -> LogicResult<()> {
899 let mut result = LogicResult::new_success(());
900
901 result = self
902 .model_instanciations
903 .iter()
904 .fold(result, |result, (_, model)| {
905 result.and_degrade_failure(model.read().unwrap().validate())
906 });
907 result = self
908 .treatments
909 .iter()
910 .fold(result, |result, (_, treatment)| {
911 result.and_degrade_failure(treatment.read().unwrap().validate())
912 });
913
914 for (treatment_name, arc_treatment) in &self.treatments {
919 let treatment = arc_treatment.read().unwrap();
920 for (input_name, _) in treatment.descriptor().inputs() {
921 let mut satisfaction = 0;
922 for connection in &self.connections {
923 if let IO::Treatment(treatment_ref) = &connection.input_treatment {
924 if Arc::<_>::downgrade(&arc_treatment).ptr_eq(treatment_ref)
925 && input_name == &connection.input_name
926 {
927 satisfaction += 1;
928 }
929 }
930 }
931
932 if satisfaction == 0 {
933 result = result.and_degrade_failure(LogicResult::new_failure(
934 LogicError::unsatisfied_input(
935 243,
936 Some(self.descriptor().identifier().clone()),
937 treatment_name.clone(),
938 input_name.clone(),
939 self.design_reference.clone(),
940 ),
941 ));
942 } else if satisfaction > 1 {
943 result = result.and_degrade_failure(LogicResult::new_failure(
944 LogicError::overloaded_input(
945 244,
946 self.descriptor().identifier().clone(),
947 treatment_name.clone(),
948 input_name.clone(),
949 self.design_reference.clone(),
950 ),
951 ));
952 }
953 }
954 }
955
956 let mut outputs_satisfaction = self
958 .descriptor()
959 .outputs()
960 .iter()
961 .map(|(name, _output)| -> (String, usize) { (name.to_string(), 0) })
962 .collect::<HashMap<String, usize>>();
963
964 for connection in &self.connections {
965 match connection.input_treatment {
966 IO::Sequence() => {
967 *(outputs_satisfaction
968 .get_mut(&connection.input_name)
969 .unwrap()) += 1;
970 }
971 _ => {}
972 }
973 }
974
975 for (output, count) in outputs_satisfaction {
977 if count < 1 {
978 result.errors_mut().push(LogicError::unsatisfied_output(
979 51,
980 self.descriptor().identifier().clone(),
981 output,
982 self.design_reference.clone(),
983 ));
984 } else if count > 1 {
985 result.errors_mut().push(LogicError::overloaded_output(
986 52,
987 self.descriptor().identifier().clone(),
988 output,
989 self.design_reference.clone(),
990 ));
991 }
992 }
993
994 result
995 }
996
997 pub fn make_use(&self, identifier: &Identifier) -> bool {
998 self.unvalidated_design()
999 .success()
1000 .map(|design| design.make_use(identifier))
1001 .unwrap_or(false)
1002 }
1003
1004 pub fn uses(&self) -> Vec<Identifier> {
1005 self.unvalidated_design()
1006 .success()
1007 .map(|design| design.uses())
1008 .unwrap_or_default()
1009 }
1010
1011 pub fn unvalidated_design(&self) -> LogicResult<TreatmentDesign> {
1012 let result = LogicResult::new_success(());
1013
1014 result.and_then(|_| {
1015 LogicResult::new_success(TreatmentDesign {
1016 descriptor: self.descriptor.clone(),
1017 model_instanciations: self
1018 .model_instanciations
1019 .iter()
1020 .map(|(name, model_instanciation)| {
1021 let model_instanciation = model_instanciation.read().unwrap();
1022 (
1023 name.clone(),
1024 ModelInstanciationDesign {
1025 name: name.clone(),
1026 attributes: model_instanciation.attributes().clone(),
1027 descriptor: Arc::downgrade(&model_instanciation.descriptor()),
1028 parameters: model_instanciation
1029 .parameters()
1030 .iter()
1031 .filter_map(|(name, param)| {
1032 if let Some(value) = param.read().unwrap().value().as_ref()
1033 {
1034 Some((
1035 name.clone(),
1036 ParameterDesign {
1037 name: name.clone(),
1038 value: value.clone(),
1039 },
1040 ))
1041 } else {
1042 None
1043 }
1044 })
1045 .collect(),
1046 },
1047 )
1048 })
1049 .collect(),
1050 treatments: self
1051 .treatments
1052 .iter()
1053 .map(|(name, treatment_instanciation)| {
1054 let treatment_instanciation = treatment_instanciation.read().unwrap();
1055 (
1056 name.clone(),
1057 TreatmentInstanciationDesign {
1058 name: name.clone(),
1059 attributes: treatment_instanciation.attributes().clone(),
1060 descriptor: Arc::downgrade(&treatment_instanciation.descriptor()),
1061 generics: {
1062 let clone = treatment_instanciation.generics().clone();
1063 clone
1064 },
1065 models: treatment_instanciation.models().clone(),
1066 parameters: treatment_instanciation
1067 .parameters()
1068 .iter()
1069 .filter_map(|(name, param)| {
1070 if let Some(value) = param.read().unwrap().value().as_ref()
1071 {
1072 Some((
1073 name.clone(),
1074 ParameterDesign {
1075 name: name.clone(),
1076 value: value.clone(),
1077 },
1078 ))
1079 } else {
1080 None
1081 }
1082 })
1083 .collect(),
1084 },
1085 )
1086 })
1087 .collect(),
1088 connections: self
1089 .connections
1090 .iter()
1091 .filter_map(|connection| {
1092 Some(ConnectionDesign {
1093 attributes: connection.attributes().clone(),
1094 output_treatment: match &connection.output_treatment {
1095 IO::Sequence() => IODesign::Sequence(),
1096 IO::Treatment(t) => IODesign::Treatment(
1097 t.upgrade()?.read().unwrap().name().to_string(),
1098 ),
1099 },
1100 output_name: connection.output_name.clone(),
1101 input_treatment: match &connection.input_treatment {
1102 IO::Sequence() => IODesign::Sequence(),
1103 IO::Treatment(t) => IODesign::Treatment(
1104 t.upgrade()?.read().unwrap().name().to_string(),
1105 ),
1106 },
1107 input_name: connection.input_name.clone(),
1108 })
1109 })
1110 .collect(),
1111 })
1112 })
1113 }
1114
1115 pub fn design(&self) -> LogicResult<TreatmentDesign> {
1116 self.validate().and_then(|_| self.unvalidated_design())
1117 }
1118}
1119
1120impl Scope for Treatment {
1121 fn descriptor(&self) -> Arc<dyn Parameterized> {
1122 Arc::clone(&self.descriptor()) as Arc<dyn Parameterized>
1123 }
1124
1125 fn collection(&self) -> Arc<Collection> {
1126 Arc::clone(&self.collection)
1127 }
1128
1129 fn identifier(&self) -> Identifier {
1130 self.descriptor().identifier().clone()
1131 }
1132}
1133
1134impl GenericInstanciation for Treatment {
1135 fn generics(&'_ self) -> RwLockReadGuard<'_, HashMap<String, DescribedType>> {
1136 self.generics.read().unwrap()
1137 }
1138
1139 fn set_generic(&mut self, _generic_name: String, _type: DescribedType) -> LogicResult<()> {
1140 LogicResult::new_success(())
1141 }
1142}