melodium_engine/designer/
treatment.rs

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                    // This is required to satisfy type/generics comparison for inner instanciantions.
47                    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        // TODO Maybe should we check if no circular
915        // references in connections there
916
917        // Checking all inputs are satisfied.
918        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        // Counting number of outputs connected to self outputs.
957        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        // Check self outputs are connected to exactly one treatment output.
976        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}