1use crate::read_ebml::Process;
16
17use std::{
18 fs::{OpenOptions, File},
19 io::{self, BufRead, BufReader, Write},
20 path::Path,
21};
22
23pub fn 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
122 process_rows.push(needed_proc);
124 }
125
126 }
127
128 process_rows
130
131}
132
133#[cfg(test)]
146mod tests {
147 use super::*;
149 use std::fs;
150 use std::fs::OpenOptions;
151 use std::io::Write;
152
153 fn create_test_file(filename:&str, lines:Vec<String>) {
154 let mut new_file = OpenOptions::new()
155 .read(true)
156 .write(true)
157 .create(true)
158 .open(filename)
159 .expect("Could not open the file!");
160 for line in lines {
161 new_file.write({line+"\n"}.as_bytes()).expect("Could not write line to test-only file!");
162 }
163 }
164
165 fn destroy_test_file(filename:&str) {
166 let _ = fs::remove_file(filename);
167 }
168
169 fn generate_minimum_csv_file() -> Vec<String> {
170 vec!["Document Number,Title,Subject,Product,Author,Reviewer".to_string()]
171 }
172
173 fn generate_csv_with_1000_templates() -> Vec<String> {
174 let mut new_vec_of_strings = generate_minimum_csv_file();
175 new_vec_of_strings.push(new_vec_of_strings[0].clone());
176 for ii in 0..1000 {
178 new_vec_of_strings[0].push_str(",Template");
179 new_vec_of_strings[0].push_str(&ii.to_string());
180 new_vec_of_strings[1].push_str(",x");
181 }
182 new_vec_of_strings
184 }
185
186 fn generate_csv_with_1000_processes() -> Vec<String> {
187 let mut new_vec_of_strings = generate_minimum_csv_file();
188 for _ii in 0..1000 {
190 new_vec_of_strings.push(new_vec_of_strings[0].clone());
191 }
192 new_vec_of_strings
194 }
195
196 fn generate_csv_with_25_templates_250_processes() -> Vec<String> {
197 let mut new_vec_of_strings = generate_minimum_csv_file();
198 new_vec_of_strings.push(new_vec_of_strings[0].clone());
199 for ii in 0..25 {
201 new_vec_of_strings[0].push_str(",Template");
202 new_vec_of_strings[0].push_str(&ii.to_string());
203 new_vec_of_strings[1].push_str(",x");
204 }
205 for _ii in 1..250 {
206 new_vec_of_strings.push(new_vec_of_strings[1].clone());
207 }
208 new_vec_of_strings
210 }
211
212 fn generate_csv_with_allcaps_headers() -> Vec<String> {
213 let mut new_vec_of_strings = generate_minimum_csv_file();
214 new_vec_of_strings[0] = new_vec_of_strings[0].to_uppercase();
215 new_vec_of_strings
216 }
217
218 fn generate_csv_with_lowercase_headers() -> Vec<String> {
219 let mut new_vec_of_strings = generate_minimum_csv_file();
220 new_vec_of_strings[0] = new_vec_of_strings[0].to_lowercase();
221 new_vec_of_strings
222 }
223
224 fn generate_csv_with_1000_templates_uppercase_x() -> Vec<String> {
225 let mut new_vec_of_strings = generate_minimum_csv_file();
226 new_vec_of_strings.push(new_vec_of_strings[0].clone());
227 for ii in 0..1000 {
229 new_vec_of_strings[0].push_str(",Template");
230 new_vec_of_strings[0].push_str(&ii.to_string());
231 new_vec_of_strings[1].push_str(",X");
232 }
233 new_vec_of_strings
235 }
236
237 #[test]
240 fn test_minimum() {
241 let file_name = "test_minimum.csv".to_string();
242 create_test_file(&file_name,generate_minimum_csv_file());
243
244 let list_of_processes = read_csv(&file_name,true);
245 assert_eq!(list_of_processes.len(),0);
246
247 destroy_test_file(&file_name);
248 }
249
250 #[test]
251 fn test_1000_templates_quiet() {
252 let file_name = "test_1000_templates.csv".to_string();
253 create_test_file(&file_name,generate_csv_with_1000_templates());
254
255 let list_of_processes = read_csv(&file_name,false);
256 assert_eq!(list_of_processes.len(),1);
257 assert_eq!(list_of_processes[0].get_all_templates().len(),1000);
258
259 destroy_test_file(&file_name);
260 }
261
262 #[test]
263 fn test_1000_processes_quiet() {
264 let file_name = "test_1000_processes.csv".to_string();
265 create_test_file(&file_name,generate_csv_with_1000_processes());
266
267 let list_of_processes = read_csv(&file_name,false);
268 assert_eq!(list_of_processes.len(),1000);
269 assert_eq!(list_of_processes[0].get_all_templates().len(),0);
270
271 destroy_test_file(&file_name);
272 }
273
274 #[test]
275 fn test_25_templates_250_processes_quiet() {
276 let file_name = "test_25_templates_250_processes.csv".to_string();
277 create_test_file(&file_name,generate_csv_with_25_templates_250_processes());
278
279 let list_of_processes = read_csv(&file_name,false);
280 assert_eq!(list_of_processes.len(),250);
281 for ii in 0..250 {
282 assert_eq!(list_of_processes[ii].get_all_templates().len(),25);
283 }
284 destroy_test_file(&file_name);
285 }
286
287 #[test]
288 fn test_allcaps_csv() {
289 let file_name = "test_allcaps.csv".to_string();
290 create_test_file(&file_name,generate_csv_with_allcaps_headers());
291
292 let list_of_processes = read_csv(&file_name,true);
293 assert_eq!(list_of_processes.len(),0);
294
295 destroy_test_file(&file_name);
296 }
297
298 #[test]
299 fn test_lowercase_csv() {
300 let file_name = "test_lowercase.csv".to_string();
301 create_test_file(&file_name,generate_csv_with_lowercase_headers());
302
303 let list_of_processes = read_csv(&file_name,true);
304 assert_eq!(list_of_processes.len(),0);
305
306 destroy_test_file(&file_name);
307 }
308
309 #[test]
310 fn test_uppercase_x_quiet() {
311 let file_name = "test_1000_templates_uppercase_x.csv".to_string();
312 create_test_file(&file_name,generate_csv_with_1000_templates_uppercase_x());
313
314 let list_of_processes = read_csv(&file_name,false);
315 assert_eq!(list_of_processes.len(),1);
316 assert_eq!(list_of_processes[0].get_all_templates().len(),1000);
317
318 destroy_test_file(&file_name);
319 }
320
321
322}