Alice_DBMS/
instance.rs

1/*                          MIT License
2
3Copyright (c) 2024 Daniil Ermolaev
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE. */
22
23use crate::engines::Engines;
24use uuid::Uuid;
25use std::path::{PathBuf, Path};
26use std::fs::File;
27use std::io::{self, BufRead};
28
29use crate::json_engine::JSONEngine;
30use crate::log_engine::LOGEngine;
31
32use std::collections::HashMap;
33use crate::command_executor::IMPestParser;
34use pest_derive::Parser;
35use pest::Parser;
36use crate::command_executor::Rule;
37
38macro_rules! adbprint {
39    ($($arg:tt)*) => {
40        println!("[ INSTANCE MANAGER ]=: {}", format!($($arg)*));
41    };
42}
43
44#[derive(Debug, Clone)]
45pub struct Instance {
46    pub name: String,
47    pub engine: Engines,
48}
49
50#[derive(Debug, Clone, Default)]
51pub struct InstanceManager {
52    pub name: String,
53    pub instances: Vec<Instance>,
54    pub root_path: PathBuf,
55    pub authenticated_apps: HashMap<String, String>,
56}
57
58impl InstanceManager {
59    pub fn new(root_path: &PathBuf) -> Self {
60        let name = Uuid::new_v4().to_string();
61        Self {
62            name,
63            instances: vec![],
64            root_path: root_path.to_owned(),
65            authenticated_apps: HashMap::new(),
66        }
67    }
68
69    pub fn create_instance(&mut self, engine_type: &str, name: &str) -> Result<String, Box<dyn std::error::Error>> {
70        let new_name = name.to_string();
71        let engine = match engine_type {
72            "json_engine" => Engines::JSONEngine(JSONEngine::new(&self.root_path)),
73            "log_engine" => Engines::LOGEngine(LOGEngine::new(&self.root_path)),
74            _ => {
75                println!("Engine not found.");
76                return Err(Box::new(std::io::Error::new(
77                    std::io::ErrorKind::InvalidInput, "Engine type not found")));
78            }
79        };
80        let instance = Instance { engine, name: new_name.clone() };
81        self.instances.push(instance);
82        Ok(new_name)
83    }
84
85    pub fn get_instance(&self, instance_name: &str) -> Option<&Instance> {
86        self.instances.iter().find(|i| i.name == instance_name)
87    }
88
89    pub fn get_mutable_engine(&mut self, instance_name: &str) -> Option<&mut Engines> {
90        self.instances.iter_mut().find(|instance| instance.name == instance_name)
91            .map(|instance| &mut instance.engine)
92    }
93
94    pub fn sign_up(&mut self, app_name: String) -> String {
95        let key = Uuid::new_v4().to_string();
96        self.authenticated_apps.insert(app_name, key.clone());
97        key
98    }
99
100    pub fn get_all_apps(&self) {
101        adbprint!("{:#?}", self.authenticated_apps);
102    }
103
104    pub fn execute_cmd(&mut self, command: &str) -> Result<(), Box<dyn std::error::Error>> {
105        match IMPestParser::parse(Rule::sql_statements, command) {
106            Ok(pairs) => {
107                for pair in pairs {
108                    for inner_pair in pair.into_inner() {
109                        match inner_pair.as_rule() {
110                            Rule::create_instance => {
111                                let inner = inner_pair.into_inner().as_str().split(" ENGINE ").collect::<Vec<_>>();
112                                let instance_id = self.create_instance(inner[1], inner[0]);
113                                match instance_id {
114                                    Ok(message) => adbprint!("NEW INSTANCE ID: {}", message),
115                                    Err(e) => adbprint!("{:#?}", e),
116                                }
117                            },
118                            Rule::get_instance => {
119                                let inner = inner_pair.into_inner().as_str();
120                                adbprint!("{:#?}", self.get_instance(inner));
121                            },
122                            Rule::get_instances => {
123                                adbprint!("{:#?}", self.instances);
124                            },
125                            Rule::print_addbms => {
126                                adbprint!("{:#?}", self);
127                            },
128                            Rule::supported_engines => {
129                                adbprint!("LOGEngine (log_engine)\nJSONEngine (json_engine)");
130                            },
131                            Rule::create_collection => {
132                                let inner = inner_pair.into_inner().as_str().split(" INSTANCE WITH NAME ").collect::<Vec<_>>();
133                                if let Some(engine) = self.get_mutable_engine(inner[0]) {
134                                    match engine {
135                                        Engines::JSONEngine(json_engine) => {
136                                            json_engine.add_collection(inner[1]); // Call method for JSONEngine
137                                        },
138                                        Engines::LOGEngine(log_engine) => {
139                                            log_engine.add_collection(inner[1]); // Call method for LOGEngine
140                                        },
141                                        // You can add more engine variants here if needed
142                                    }
143                                } else {
144                                    adbprint!("Instance not found: {}", inner[0]);
145                                }
146                            }
147                            
148                            Rule::create_document => {
149                                let inner = inner_pair.into_inner().as_str().split(" INSTANCE IN COLLECTION ").collect::<Vec<_>>();
150                                let inner_two = inner[1].split(" WITH NAME ").collect::<Vec<_>>();
151                            
152                                if let Some(engine) = self.get_mutable_engine(inner[0]) {
153                                    match engine {
154                                        Engines::JSONEngine(json_engine) => {
155                                            if let Some(collection) = json_engine.get_collection_mut(inner_two[0]) {
156                                                collection.add_document(inner_two[1], "");
157                                                adbprint!("DOCUMENT {} CREATED IN {}.{} C.I", inner_two[1], inner_two[0], inner[0]);
158                                            } else {
159                                                adbprint!("Collection not found in JSONEngine: {}", inner_two[0]);
160                                            }
161                                        },
162                                        Engines::LOGEngine(log_engine) => {
163                                            if let Some(collection) = log_engine.get_collection_mut(inner_two[0]) {
164                                                collection.add_document(inner_two[1], "");
165                                                adbprint!("DOCUMENT {} CREATED IN {}.{} C.I", inner_two[1], inner_two[0], inner[0]);
166                                            } else {
167                                                adbprint!("Collection not found in LOGEngine: {}", inner_two[0]);
168                                            }
169                                        },
170                                    }
171                                } else {
172                                    adbprint!("Instance not found: {}", inner[0]);
173                                }
174                            },                            
175                            _ => unreachable!("I don't know this command"),
176                        }
177                    }
178                }
179                Ok(())
180            }
181            Err(e) => {
182                adbprint!("Error parsing command: {}", e);
183                Err(Box::new(e))
184            }
185        }
186    }
187
188    pub fn wrapped_execute_cmd(&mut self, command: &str) -> Result<(), Box<dyn std::error::Error>> {
189        self.execute_cmd(command)
190            .map_err(|e| { adbprint!("Error! {}", e); e })
191    }
192
193    pub fn execute_decl_file<P>(&mut self, filename: P) -> Result<(), io::Error>
194    where
195        P: AsRef<Path>, 
196    {
197        let file = File::open(filename)?;
198        let reader = io::BufReader::new(file);
199
200        for line in reader.lines() {
201            if let Err(e) = self.wrapped_execute_cmd(&line?.replace("\n", "")) {
202                adbprint!("Failed to execute line: {}", e);
203            }
204        }
205        Ok(())
206    }
207}