1use crate::read_ebml::Process;
16
17use std::{
18 fs::{OpenOptions, File},
19 io::{self, BufRead, BufReader, Write},
20 path::Path,
21};
22
23fn new_css_file_if_none_exists(tflag:&str) {
25 let assets_folder = "./assets";
26 let new_css_file = assets_folder.to_owned()+"/"+tflag;
27 if Path::new(&assets_folder).exists() {
29 match Path::new(&new_css_file).exists() {
30 true => (),
31 false => { let mut f = OpenOptions::new()
32 .read(true)
33 .write(true)
34 .create(true)
35 .open(&new_css_file)
36 .expect("Could not open the file!");
37 let mut new_line = "/* *******************************".to_string();
38 new_line.push_str(&("\n ".to_owned()+tflag));
39 new_line.push_str("\n ******************************* */");
40 f.write(new_line.as_bytes()).expect("Could not write template line into new file!");
41 },
42 };
43 }
44}
45
46pub fn read_csv(file_name:&String,verbose:bool) -> Vec<Process> {
48
49 let read_file = if file_name==&String::from("") { "./DocumentList.csv" } else { file_name };
51
52 fn lines_from_file(filename: impl AsRef<Path>) -> io::Result<Vec<String>> {
54 BufReader::new(File::open(filename)?).lines().collect()
55 }
56
57 let lines = lines_from_file(read_file).expect("Could not load lines");
59
60 let mut process_rows:Vec<Process> = vec![];
62 let mut header_row:Vec<&str> = vec![];
63
64 for (ii,line) in lines.iter().enumerate() {
66
67 let all_parts: Vec<&str> = line.split(',').collect();
69
70 if ii==0 {
72
73 assert!(all_parts[0].to_string().to_uppercase()=="Document Number".to_string().to_uppercase());
76 assert!(all_parts[1].to_string().to_uppercase()=="Title".to_string().to_uppercase());
77 assert!(all_parts[2].to_string().to_uppercase()=="Subject".to_string().to_uppercase());
78 assert!(all_parts[3].to_string().to_uppercase()=="Product".to_string().to_uppercase());
79 assert!(all_parts[4].to_string().to_uppercase()=="Author".to_string().to_uppercase());
80 assert!(all_parts[5].to_string().to_uppercase()=="Reviewer".to_string().to_uppercase());
81
82 header_row = all_parts;
84
85 } else if !(all_parts[0]=="") {
87
88 let mut needed_proc = Process::new();
90
91 needed_proc.set_number(all_parts[0]);
93 needed_proc.set_title(all_parts[1]);
94 needed_proc.set_subject(all_parts[2]);
95 needed_proc.set_product(all_parts[3]);
96 needed_proc.set_author(all_parts[4]);
97 needed_proc.set_reviewer(all_parts[5]);
98
99 if all_parts.len() > 6 {
101
102 for jj in 6..all_parts.len() {
104
105 match all_parts[jj] {
107 "x"|"X" => {
108 let template_name = header_row[jj].to_string() + ".css";
110 if verbose { println!("Template identified: {}",&template_name); }
111 needed_proc.add_template(&template_name);
113 new_css_file_if_none_exists(&template_name);
114 },
115 _ => (),
117 }
118
119 }
120 }
121 if verbose { needed_proc.display_process_to_stdout(); };
122
123 process_rows.push(needed_proc);
125 }
126
127 }
128
129 process_rows
131
132}
133
134#[cfg(test)]
147mod tests {
148 use super::*;
150 use std::fs;
151 use std::fs::OpenOptions;
152 use std::io::Write;
153
154 fn create_test_file(filename:&str, lines:Vec<String>) {
155 let mut new_file = OpenOptions::new()
156 .read(true)
157 .write(true)
158 .create(true)
159 .open(filename)
160 .expect("Could not open the file!");
161 for line in lines {
162 new_file.write({line+"\n"}.as_bytes()).expect("Could not write line to test-only file!");
163 }
164 }
165
166 fn destroy_test_file(filename:&str) {
167 let _ = fs::remove_file(filename);
168 }
169
170 fn generate_minimum_csv_file() -> Vec<String> {
171 vec!["Document Number,Title,Subject,Product,Author,Reviewer".to_string()]
172 }
173
174 fn generate_csv_with_1000_templates() -> Vec<String> {
175 let mut new_vec_of_strings = generate_minimum_csv_file();
176 new_vec_of_strings.push(new_vec_of_strings[0].clone());
177 for ii in 0..1000 {
179 new_vec_of_strings[0].push_str(",Template");
180 new_vec_of_strings[0].push_str(&ii.to_string());
181 new_vec_of_strings[1].push_str(",x");
182 }
183 new_vec_of_strings
185 }
186
187 fn generate_csv_with_1000_processes() -> Vec<String> {
188 let mut new_vec_of_strings = generate_minimum_csv_file();
189 for _ii in 0..1000 {
191 new_vec_of_strings.push(new_vec_of_strings[0].clone());
192 }
193 new_vec_of_strings
195 }
196
197 fn generate_csv_with_25_templates_250_processes() -> Vec<String> {
198 let mut new_vec_of_strings = generate_minimum_csv_file();
199 new_vec_of_strings.push(new_vec_of_strings[0].clone());
200 for ii in 0..25 {
202 new_vec_of_strings[0].push_str(",Template");
203 new_vec_of_strings[0].push_str(&ii.to_string());
204 new_vec_of_strings[1].push_str(",x");
205 }
206 for _ii in 1..250 {
207 new_vec_of_strings.push(new_vec_of_strings[1].clone());
208 }
209 new_vec_of_strings
211 }
212
213 fn generate_csv_with_allcaps_headers() -> Vec<String> {
214 let mut new_vec_of_strings = generate_minimum_csv_file();
215 new_vec_of_strings[0] = new_vec_of_strings[0].to_uppercase();
216 new_vec_of_strings
217 }
218
219 fn generate_csv_with_lowercase_headers() -> Vec<String> {
220 let mut new_vec_of_strings = generate_minimum_csv_file();
221 new_vec_of_strings[0] = new_vec_of_strings[0].to_lowercase();
222 new_vec_of_strings
223 }
224
225 fn generate_csv_with_1000_templates_uppercase_x() -> Vec<String> {
226 let mut new_vec_of_strings = generate_minimum_csv_file();
227 new_vec_of_strings.push(new_vec_of_strings[0].clone());
228 for ii in 0..1000 {
230 new_vec_of_strings[0].push_str(",Template");
231 new_vec_of_strings[0].push_str(&ii.to_string());
232 new_vec_of_strings[1].push_str(",X");
233 }
234 new_vec_of_strings
236 }
237
238 #[test]
241 fn test_minimum() {
242 let file_name = "test_minimum.csv".to_string();
243 create_test_file(&file_name,generate_minimum_csv_file());
244
245 let list_of_processes = read_csv(&file_name,true);
246 assert_eq!(list_of_processes.len(),0);
247
248 destroy_test_file(&file_name);
249 }
250
251 #[test]
252 fn test_1000_templates_quiet() {
253 let file_name = "test_1000_templates.csv".to_string();
254 create_test_file(&file_name,generate_csv_with_1000_templates());
255
256 let list_of_processes = read_csv(&file_name,false);
257 assert_eq!(list_of_processes.len(),1);
258 assert_eq!(list_of_processes[0].get_all_templates().len(),1000);
259
260 destroy_test_file(&file_name);
261 }
262
263 #[test]
264 fn test_1000_processes_quiet() {
265 let file_name = "test_1000_processes.csv".to_string();
266 create_test_file(&file_name,generate_csv_with_1000_processes());
267
268 let list_of_processes = read_csv(&file_name,false);
269 assert_eq!(list_of_processes.len(),1000);
270 assert_eq!(list_of_processes[0].get_all_templates().len(),0);
271
272 destroy_test_file(&file_name);
273 }
274
275 #[test]
276 fn test_25_templates_250_processes_quiet() {
277 let file_name = "test_25_templates_250_processes.csv".to_string();
278 create_test_file(&file_name,generate_csv_with_25_templates_250_processes());
279
280 let list_of_processes = read_csv(&file_name,false);
281 assert_eq!(list_of_processes.len(),250);
282 for ii in 0..250 {
283 assert_eq!(list_of_processes[ii].get_all_templates().len(),25);
284 }
285 destroy_test_file(&file_name);
286 }
287
288 #[test]
289 fn test_allcaps_csv() {
290 let file_name = "test_allcaps.csv".to_string();
291 create_test_file(&file_name,generate_csv_with_allcaps_headers());
292
293 let list_of_processes = read_csv(&file_name,true);
294 assert_eq!(list_of_processes.len(),0);
295
296 destroy_test_file(&file_name);
297 }
298
299 #[test]
300 fn test_lowercase_csv() {
301 let file_name = "test_lowercase.csv".to_string();
302 create_test_file(&file_name,generate_csv_with_lowercase_headers());
303
304 let list_of_processes = read_csv(&file_name,true);
305 assert_eq!(list_of_processes.len(),0);
306
307 destroy_test_file(&file_name);
308 }
309
310 #[test]
311 fn test_uppercase_x_quiet() {
312 let file_name = "test_1000_templates_uppercase_x.csv".to_string();
313 create_test_file(&file_name,generate_csv_with_1000_templates_uppercase_x());
314
315 let list_of_processes = read_csv(&file_name,false);
316 assert_eq!(list_of_processes.len(),1);
317 assert_eq!(list_of_processes[0].get_all_templates().len(),1000);
318
319 destroy_test_file(&file_name);
320 }
321
322
323}