1use super::{
2 ebi_command::{EBI_COMMANDS, EbiCommand},
3 ebi_input::{EbiInput, EbiObjectImporter, EbiTraitImporter},
4 ebi_output::{EbiObjectExporter, EbiOutputType},
5 ebi_trait::FromEbiTraitObject,
6};
7use crate::{
8 ebi_commands::ebi_command_validate::EBI_VALIDATE,
9 ebi_file_handlers::{
10 business_process_model_and_notation::EBI_BUSINESS_PROCESS_MODEL_AND_NOTATION,
11 compressed_event_log::EBI_COMPRESSED_EVENT_LOG,
12 deterministic_finite_automaton::EBI_DETERMINISTIC_FINITE_AUTOMATON,
13 directly_follows_graph::EBI_DIRECTLY_FOLLOWS_GRAPH,
14 directly_follows_model::EBI_DIRECTLY_FOLLOWS_MODEL, event_log_csv::EBI_EVENT_LOG_CSV,
15 event_log_ocel::EBI_EVENT_LOG_OCEL, event_log_python::EBI_EVENT_LOG_PYTHON,
16 event_log_xes::EBI_EVENT_LOG_XES, executions::EBI_EXECUTIONS,
17 finite_language::EBI_FINITE_LANGUAGE,
18 finite_stochastic_language::EBI_FINITE_STOCHASTIC_LANGUAGE,
19 labelled_petri_net::EBI_LABELLED_PETRI_NET,
20 language_of_alignments::EBI_LANGUAGE_OF_ALIGNMENTS, lola_net::EBI_LOLA_NET,
21 petri_net_markup_language::EBI_PETRI_NET_MARKUP_LANGUAGE,
22 portable_document_format::EBI_PORTABLE_DOCUMENT_FORMAT,
23 portable_network_graphics::EBI_PORTABLE_NETWORK_GRAPHCIS, process_tree::EBI_PROCESS_TREE,
24 process_tree_markup_language::EBI_PROCESS_TREE_MARKUP_LANGUAGE,
25 scalable_vector_graphics::EBI_SCALABLE_VECTOR_GRAPHICS,
26 stochastic_business_process_model_and_notation::EBI_STOCHASTIC_BUSINESS_PROCESS_MODEL_AND_NOTATION,
27 stochastic_deterministic_finite_automaton::EBI_STOCHASTIC_DETERMINISTIC_FINITE_AUTOMATON,
28 stochastic_directly_follows_model::EBI_STOCHASTIC_DIRECTLY_FOLLOWS_MODEL,
29 stochastic_labelled_petri_net::EBI_STOCHASTIC_LABELLED_PETRI_NET,
30 stochastic_language_of_alignments::EBI_STOCHASTIC_LANGUAGE_OF_ALIGNMENTS,
31 stochastic_nondeterministic_finite_automaton::EBI_STOCHASTIC_NONDETERMINISTIC_FINITE_AUTOMATON,
32 stochastic_process_tree::EBI_STOCHASTIC_PROCESS_TREE,
33 },
34 ebi_framework::{
35 ebi_command::get_applicable_commands, ebi_input::EbiObjectImporterFallible,
36 ebi_trait::EbiTrait,
37 },
38 prom::java_object_handler::JavaObjectHandler,
39};
40use ebi_objects::{
41 EbiObjectType,
42 anyhow::{Error, Result, anyhow},
43};
44use std::{collections::BTreeSet, fmt::Display, hash::Hash, io::BufRead, str::FromStr};
45
46pub const EBI_FILE_HANDLERS: &'static [EbiFileHandler] = &[
51 EBI_COMPRESSED_EVENT_LOG,
52 EBI_DIRECTLY_FOLLOWS_GRAPH,
53 EBI_DETERMINISTIC_FINITE_AUTOMATON,
54 EBI_DIRECTLY_FOLLOWS_MODEL,
55 EBI_STOCHASTIC_DIRECTLY_FOLLOWS_MODEL,
56 EBI_EXECUTIONS,
57 EBI_STOCHASTIC_BUSINESS_PROCESS_MODEL_AND_NOTATION,
58 EBI_BUSINESS_PROCESS_MODEL_AND_NOTATION,
59 EBI_EVENT_LOG_XES,
61 EBI_FINITE_LANGUAGE,
62 EBI_FINITE_STOCHASTIC_LANGUAGE,
63 EBI_LABELLED_PETRI_NET,
64 EBI_LANGUAGE_OF_ALIGNMENTS,
65 EBI_LOLA_NET,
66 EBI_PETRI_NET_MARKUP_LANGUAGE,
67 EBI_STOCHASTIC_DETERMINISTIC_FINITE_AUTOMATON,
68 EBI_STOCHASTIC_LABELLED_PETRI_NET,
69 EBI_PROCESS_TREE,
70 EBI_STOCHASTIC_LANGUAGE_OF_ALIGNMENTS,
71 EBI_STOCHASTIC_PROCESS_TREE,
72 EBI_PROCESS_TREE_MARKUP_LANGUAGE,
73 EBI_EVENT_LOG_CSV,
74 EBI_PORTABLE_DOCUMENT_FORMAT,
75 EBI_SCALABLE_VECTOR_GRAPHICS,
76 EBI_PORTABLE_DOCUMENT_FORMAT,
77 EBI_PORTABLE_NETWORK_GRAPHCIS,
78 EBI_STOCHASTIC_NONDETERMINISTIC_FINITE_AUTOMATON,
79 EBI_EVENT_LOG_PYTHON,
80];
81
82#[derive(Clone, Debug)]
83pub struct EbiFileHandler {
84 pub name: &'static str,
85 pub article: &'static str, pub file_extension: &'static str,
87 pub is_binary: bool,
88 pub format_specification: &'static str,
89 pub validator: Option<fn(&mut dyn BufRead) -> Result<()>>,
90
91 pub trait_importers: &'static [EbiTraitImporter],
94
95 pub object_importers: &'static [EbiObjectImporter],
99
100 pub object_importers_fallible: &'static [EbiObjectImporterFallible],
104
105 pub object_exporters: &'static [EbiObjectExporter],
108
109 pub object_exporters_fallible: &'static [EbiObjectExporter],
112 pub java_object_handlers: &'static [JavaObjectHandler],
113}
114
115impl EbiFileHandler {
116 pub fn get_applicable_commands(&self) -> BTreeSet<Vec<&'static EbiCommand>> {
117 let mut result = BTreeSet::new();
118
119 for importer in self.trait_importers {
120 result.extend(importer.get_trait().get_applicable_commands());
121 }
122 for importer in self.object_importers {
123 result.extend(get_applicable_commands(&importer.get_type()));
124 }
125 if self.validator.is_some() {
126 result.insert(vec![&EBI_COMMANDS, &EBI_VALIDATE]);
127 }
128
129 result
130 }
131
132 pub fn get_producing_commands(&self) -> BTreeSet<Vec<&'static EbiCommand>> {
133 let mut objects = vec![];
135 for exporter in self.object_exporters {
136 objects.push(exporter.get_type());
137 }
138 for exporter in self.object_exporters_fallible {
139 objects.push(exporter.get_type());
140 }
141
142 let mut result = BTreeSet::new();
144 for command_path in EBI_COMMANDS.get_command_paths() {
145 if let Some(EbiCommand::Command { output_type, .. }) = command_path.last() {
146 if let EbiOutputType::ObjectType(x) = output_type {
147 if objects.contains(x) {
148 result.insert(command_path);
149 }
150 }
151 }
152 }
153
154 result
155 }
156
157 pub fn can_import_as_object(&self, object_type: &EbiObjectType) -> Tri {
158 for importer in self.object_importers {
159 if importer.get_type() == *object_type {
160 return Tri::Yes;
161 }
162 }
163 for importer in self.object_importers_fallible {
164 if importer.get_type() == *object_type {
165 return Tri::Fallible;
166 }
167 }
168 return Tri::No;
169 }
170
171 pub fn can_import_as_trait(&self, trait_type: &EbiTrait) -> bool {
172 for importer in self.trait_importers {
173 if importer.get_trait() == *trait_type {
174 return true;
175 }
176 }
177 return false;
178 }
179
180 pub fn can_export_as_object(&self, object_type: &EbiObjectType) -> Tri {
181 for exporter in self.object_exporters {
182 if exporter.get_type() == *object_type {
183 return Tri::Yes;
184 }
185 }
186 for exporter in self.object_exporters_fallible {
187 if exporter.get_type() == *object_type {
188 return Tri::Fallible;
189 }
190 }
191 return Tri::No;
192 }
193}
194
195impl FromStr for EbiFileHandler {
196 type Err = Error;
197
198 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
199 for file_handler in EBI_FILE_HANDLERS {
200 if file_handler.validator.is_some()
201 && (file_handler.name == s || file_handler.file_extension == s)
202 {
203 return Ok(file_handler.clone());
204 }
205 }
206 return Err(anyhow!("{} is not an Ebi file handler.", s));
207 }
208}
209
210impl FromEbiTraitObject for EbiFileHandler {
211 fn from_trait_object(object: EbiInput) -> Result<Box<Self>> {
212 match object {
213 EbiInput::FileHandler(e) => Ok(Box::new(e)),
214 _ => Err(anyhow!(
215 "cannot read {} {} as an file handler",
216 object.get_type().get_article(),
217 object.get_type()
218 )),
219 }
220 }
221}
222
223impl Eq for EbiFileHandler {}
224
225impl PartialEq for EbiFileHandler {
226 fn eq(&self, other: &Self) -> bool {
227 self.name == other.name
228 }
229}
230
231impl PartialOrd for EbiFileHandler {
232 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
233 self.name
234 .to_lowercase()
235 .partial_cmp(&other.name.to_lowercase())
236 }
237}
238
239impl Ord for EbiFileHandler {
240 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
241 self.name.to_lowercase().cmp(&other.name.to_lowercase())
242 }
243}
244
245impl Hash for EbiFileHandler {
246 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
247 self.name.hash(state);
248 }
249}
250
251impl Display for EbiFileHandler {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 write!(f, "{} (.{})", self.name, self.file_extension)
254 }
255}
256
257pub fn get_file_handlers(object_type: &EbiObjectType) -> Vec<&'static EbiFileHandler> {
258 let mut result = vec![];
259 for file_handler in EBI_FILE_HANDLERS.iter() {
260 for importer in file_handler.object_importers {
261 if &importer.get_type() == object_type {
262 result.push(file_handler);
263 break;
264 }
265 }
266 }
267 result
268}
269
270pub fn get_file_handlers_fallible(object_type: &EbiObjectType) -> Vec<&'static EbiFileHandler> {
271 let mut result = vec![];
272 for file_handler in EBI_FILE_HANDLERS.iter() {
273 for importer in file_handler.object_importers_fallible {
274 if &importer.get_type() == object_type {
275 result.push(file_handler);
276 break;
277 }
278 }
279 }
280 result
281}
282
283pub enum Tri {
284 Yes,
285 No,
286 Fallible,
287}
288
289impl Tri {
290 pub fn to_latex_circle(&self) -> &str {
291 match self {
292 Tri::Yes => "\\CIRCLE",
293 Tri::Fallible => "\\LEFTcircle",
294 Tri::No => "\\Circle",
295 }
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use std::str::FromStr;
302
303 use crate::{
304 ebi_file_handlers::{
305 executions::EBI_EXECUTIONS, finite_stochastic_language::EBI_FINITE_STOCHASTIC_LANGUAGE,
306 process_tree::EBI_PROCESS_TREE,
307 stochastic_labelled_petri_net::EBI_STOCHASTIC_LABELLED_PETRI_NET,
308 },
309 ebi_framework::{
310 ebi_file_handler::EbiFileHandler, ebi_input::EbiInput, ebi_trait::FromEbiTraitObject,
311 },
312 };
313
314 #[test]
315 fn file_handlers() {
316 assert_eq!(
317 EbiFileHandler::from_str("slang").unwrap(),
318 EBI_FINITE_STOCHASTIC_LANGUAGE
319 );
320 assert!(EbiFileHandler::from_str("blablabla44252435").is_err());
321
322 EbiFileHandler::get_producing_commands(&EBI_PROCESS_TREE);
323 EbiFileHandler::get_producing_commands(&EBI_STOCHASTIC_LABELLED_PETRI_NET);
324
325 assert!(
326 EBI_PROCESS_TREE
327 .cmp(&EBI_STOCHASTIC_LABELLED_PETRI_NET)
328 .is_lt()
329 );
330
331 EbiFileHandler::from_trait_object(EbiInput::FileHandler(EBI_EXECUTIONS)).unwrap();
332 }
333}