teo_runtime/model/relation/
builder.rs

1use std::collections::BTreeMap;
2use std::sync::{Arc, Mutex};
3use std::sync::atomic::{AtomicBool, Ordering};
4use teo_parser::r#type::Type;
5use crate::app::data::AppData;
6use crate::comment::Comment;
7use crate::model::{Field, Relation};
8use crate::model::relation::delete::Delete;
9use crate::model::relation::relation;
10use crate::model::relation::update::Update;
11use crate::optionality::Optionality;
12use crate::traits::named::Named;
13use crate::Value;
14
15#[derive(Clone)]
16pub struct Builder {
17    inner: Arc<Inner>
18}
19
20pub struct Inner {
21    name: String,
22    comment: Option<Comment>,
23    r#type: Type,
24    optionality: Arc<Mutex<Optionality>>,
25    model: Arc<Mutex<Vec<String>>>,
26    through: Arc<Mutex<Option<Vec<String>>>>,
27    local: Arc<Mutex<Option<String>>>,
28    foreign: Arc<Mutex<Option<String>>>,
29    is_vec: AtomicBool,
30    fields: Arc<Mutex<Vec<String>>>,
31    references: Arc<Mutex<Vec<String>>>,
32    delete: Arc<Mutex<Delete>>,
33    update: Arc<Mutex<Update>>,
34    delete_specified: AtomicBool,
35    update_specified: AtomicBool,
36    data: Arc<Mutex<BTreeMap<String, Value>>>,
37    app_data: AppData,
38}
39
40impl Builder {
41    pub fn new(name: String, comment: Option<Comment>, r#type: Type, app_data: AppData) -> Self {
42        Self {
43            inner: Arc::new(Inner {
44                name,
45                comment,
46                r#type,
47                optionality: Arc::new(Mutex::new(Optionality::Optional)),
48                model: Arc::new(Mutex::new(vec![])),
49                through: Arc::new(Mutex::new(None)),
50                local: Arc::new(Mutex::new(None)),
51                foreign: Arc::new(Mutex::new(None)),
52                is_vec: AtomicBool::new(false),
53                fields: Arc::new(Mutex::new(vec![])),
54                references: Arc::new(Mutex::new(vec![])),
55                delete: Arc::new(Mutex::new(Delete::Nullify)),
56                update: Arc::new(Mutex::new(Update::Nullify)),
57                delete_specified: AtomicBool::new(false),
58                update_specified: AtomicBool::new(false),
59                data: Arc::new(Mutex::new(BTreeMap::new())),
60                app_data,
61            })
62        }
63    }
64
65    pub fn name(&self) -> &str {
66        self.inner.name.as_str()
67    }
68
69    pub fn comment(&self) -> Option<&Comment> {
70        self.inner.comment.as_ref()
71    }
72
73    pub fn r#type(&self) -> &Type {
74        &self.inner.r#type
75    }
76
77    pub fn optionality(&self) -> Optionality {
78        self.inner.optionality.lock().unwrap().clone()
79    }
80
81    pub fn set_optionality(&self, optionality: Optionality) {
82        *self.inner.optionality.lock().unwrap() = optionality;
83    }
84
85    pub fn model(&self) -> Vec<String> {
86        self.inner.model.lock().unwrap().clone()
87    }
88
89    pub fn set_model(&self, model: Vec<String>) {
90        *self.inner.model.lock().unwrap() = model;
91    }
92
93    pub fn through(&self) -> Option<Vec<String>> {
94        self.inner.through.lock().unwrap().clone()
95    }
96
97    pub fn set_through(&self, through: Option<Vec<String>>) {
98        *self.inner.through.lock().unwrap() = through;
99    }
100
101    pub fn local(&self) -> Option<String> {
102        self.inner.local.lock().unwrap().clone()
103    }
104
105    pub fn set_local(&self, local: Option<String>) {
106        *self.inner.local.lock().unwrap() = local;
107    }
108
109    pub fn foreign(&self) -> Option<String> {
110        self.inner.foreign.lock().unwrap().clone()
111    }
112
113    pub fn set_foreign(&self, foreign: Option<String>) {
114        *self.inner.foreign.lock().unwrap() = foreign;
115    }
116
117    pub fn is_vec(&self) -> bool {
118        self.inner.is_vec.load(std::sync::atomic::Ordering::Relaxed)
119    }
120
121    pub fn set_is_vec(&self, is_vec: bool) {
122        self.inner.is_vec.store(is_vec, std::sync::atomic::Ordering::Relaxed);
123    }
124
125    pub fn fields(&self) -> Vec<String> {
126        self.inner.fields.lock().unwrap().clone()
127    }
128
129    pub fn set_fields(&self, fields: Vec<String>) {
130        *self.inner.fields.lock().unwrap() = fields;
131    }
132
133    pub fn references(&self) -> Vec<String> {
134        self.inner.references.lock().unwrap().clone()
135    }
136
137    pub fn set_references(&self, references: Vec<String>) {
138        *self.inner.references.lock().unwrap() = references;
139    }
140
141    pub fn delete(&self) -> Delete {
142        *self.inner.delete.lock().unwrap()
143    }
144
145    pub fn set_delete(&self, delete: Delete) {
146        *self.inner.delete.lock().unwrap() = delete;
147        self.inner.delete_specified.store(true, Ordering::Relaxed);
148    }
149
150    pub fn update(&self) -> Update {
151        *self.inner.update.lock().unwrap()
152    }
153
154    pub fn set_update(&self, update: Update) {
155        *self.inner.update.lock().unwrap() = update;
156        self.inner.update_specified.store(true, Ordering::Relaxed);
157    }
158
159    pub fn has_foreign_key(&self, fields: Vec<&Field>) -> bool {
160        if self.through().is_some() {
161            false
162        } else {
163            self.fields().iter().find(|name| fields.iter().find(|f| f.name() == name.as_str() && f.foreign_key()).is_some()).is_some()
164        }
165    }
166
167    pub fn data(&self) -> BTreeMap<String, Value> {
168        self.inner.data.lock().unwrap().clone()
169    }
170
171    pub fn insert_data_entry(&self, key: String, value: Value) {
172        self.inner.data.lock().unwrap().insert(key, value);
173    }
174
175    pub fn remove_data_entry(&self, key: &str) {
176        self.inner.data.lock().unwrap().remove(key);
177    }
178
179    pub fn set_data(&self, data: BTreeMap<String, Value>) {
180        *self.inner.data.lock().unwrap() = data;
181    }
182
183    pub fn data_entry(&self, key: &str) -> Option<Value> {
184        self.inner.data.lock().unwrap().get(key).cloned()
185    }
186
187    pub(crate) fn build(self, fields: Vec<&Field>) -> Relation {
188        let has_foreign_key = self.has_foreign_key(fields);
189        let r#type = self.r#type();
190        let delete_rule = if !self.inner.delete_specified.load(Ordering::Relaxed) {
191            // set default delete rule
192            if r#type.is_optional() {
193                if !has_foreign_key {
194                    Delete::NoAction
195                } else {
196                    Delete::Nullify
197                }
198            } else if r#type.is_array() {
199                Delete::NoAction
200            } else {
201                if !has_foreign_key {
202                    Delete::NoAction
203                } else {
204                    Delete::Cascade
205                }
206            }
207        } else {
208            self.delete()
209        };
210        let update_rule = if !self.inner.update_specified.load(Ordering::Relaxed) {
211            // set default update rule
212            if r#type.is_optional() {
213                if !has_foreign_key {
214                    Update::Nullify
215                } else {
216                    Update::NoAction
217                }
218            } else if r#type.is_array() {
219                Update::NoAction
220            } else {
221                if !has_foreign_key {
222                    Update::NoAction
223                } else {
224                    Update::Update
225                }
226            }
227        } else {
228            self.update()
229        };
230        let relation = Relation {
231            inner: Arc::new(relation::Inner {
232                name: self.inner.name.clone(),
233                comment: self.inner.comment.clone(),
234                r#type: self.inner.r#type.clone(),
235                optionality: self.optionality(),
236                model: self.model(),
237                through: self.through(),
238                local: self.local(),
239                foreign: self.foreign(),
240                is_vec: self.is_vec(),
241                fields: self.fields(),
242                references: self.references(),
243                delete: delete_rule,
244                update: update_rule,
245                has_foreign_key,
246                data: self.data(),
247            })
248        };
249        relation
250    }
251
252    pub fn app_data(&self) -> &AppData {
253        &self.inner.app_data
254    }
255}