use super::{
ebi_command::{EBI_COMMANDS, EbiCommand},
ebi_input::{EbiInput, EbiObjectImporter, EbiTraitImporter},
ebi_output::{EbiObjectExporter, EbiOutputType},
ebi_trait::FromEbiTraitObject,
};
use crate::{
ebi_commands::ebi_command_validate::EBI_VALIDATE,
ebi_file_handlers::{
business_process_model_and_notation::EBI_BUSINESS_PROCESS_MODEL_AND_NOTATION,
compressed_event_log::EBI_COMPRESSED_EVENT_LOG,
deterministic_finite_automaton::EBI_DETERMINISTIC_FINITE_AUTOMATON,
directly_follows_graph::EBI_DIRECTLY_FOLLOWS_GRAPH,
directly_follows_model::EBI_DIRECTLY_FOLLOWS_MODEL, event_log_csv::EBI_EVENT_LOG_CSV,
event_log_ocel::EBI_EVENT_LOG_OCEL, event_log_python::EBI_EVENT_LOG_PYTHON,
event_log_xes::EBI_EVENT_LOG_XES, executions::EBI_EXECUTIONS,
finite_language::EBI_FINITE_LANGUAGE,
finite_stochastic_language::EBI_FINITE_STOCHASTIC_LANGUAGE,
finite_stochastic_partially_ordered_language::EBI_FINITE_STOCHASTIC_PARTIALLY_ORDERED_LANGUAGE,
labelled_petri_net::EBI_LABELLED_PETRI_NET,
language_of_alignments::EBI_LANGUAGE_OF_ALIGNMENTS, lola_net::EBI_LOLA_NET,
partially_ordered_workflow_language::EBI_PARTIALLY_ORDERED_WORKFLOW_LANGUAGE,
petri_net_markup_language::EBI_PETRI_NET_MARKUP_LANGUAGE,
portable_document_format::EBI_PORTABLE_DOCUMENT_FORMAT,
portable_network_graphics::EBI_PORTABLE_NETWORK_GRAPHCIS, process_tree::EBI_PROCESS_TREE,
process_tree_markup_language::EBI_PROCESS_TREE_MARKUP_LANGUAGE,
scalable_vector_graphics::EBI_SCALABLE_VECTOR_GRAPHICS,
stochastic_business_process_model_and_notation::EBI_STOCHASTIC_BUSINESS_PROCESS_MODEL_AND_NOTATION,
stochastic_deterministic_finite_automaton::EBI_STOCHASTIC_DETERMINISTIC_FINITE_AUTOMATON,
stochastic_directly_follows_model::EBI_STOCHASTIC_DIRECTLY_FOLLOWS_MODEL,
stochastic_labelled_petri_net::EBI_STOCHASTIC_LABELLED_PETRI_NET,
stochastic_language_of_alignments::EBI_STOCHASTIC_LANGUAGE_OF_ALIGNMENTS,
stochastic_nondeterministic_finite_automaton::EBI_STOCHASTIC_NONDETERMINISTIC_FINITE_AUTOMATON,
stochastic_process_tree::EBI_STOCHASTIC_PROCESS_TREE,
},
ebi_framework::{
ebi_command::get_applicable_commands, ebi_input::EbiObjectImporterFallible,
ebi_trait::EbiTrait,
},
prom::java_object_handler::JavaObjectHandler,
};
use ebi_objects::{
EbiObjectType,
anyhow::{Error, Result, anyhow},
};
use std::{collections::BTreeSet, fmt::Display, hash::Hash, io::BufRead, str::FromStr};
pub const EBI_FILE_HANDLERS: &'static [EbiFileHandler] = &[
EBI_COMPRESSED_EVENT_LOG,
EBI_DIRECTLY_FOLLOWS_GRAPH,
EBI_DETERMINISTIC_FINITE_AUTOMATON,
EBI_DIRECTLY_FOLLOWS_MODEL,
EBI_STOCHASTIC_DIRECTLY_FOLLOWS_MODEL,
EBI_EXECUTIONS,
EBI_STOCHASTIC_BUSINESS_PROCESS_MODEL_AND_NOTATION,
EBI_BUSINESS_PROCESS_MODEL_AND_NOTATION,
EBI_EVENT_LOG_OCEL,
EBI_EVENT_LOG_XES,
EBI_FINITE_LANGUAGE,
EBI_FINITE_STOCHASTIC_LANGUAGE,
EBI_FINITE_STOCHASTIC_PARTIALLY_ORDERED_LANGUAGE,
EBI_LABELLED_PETRI_NET,
EBI_LANGUAGE_OF_ALIGNMENTS,
EBI_LOLA_NET,
EBI_PETRI_NET_MARKUP_LANGUAGE,
EBI_STOCHASTIC_DETERMINISTIC_FINITE_AUTOMATON,
EBI_STOCHASTIC_LABELLED_PETRI_NET,
EBI_PROCESS_TREE,
EBI_STOCHASTIC_LANGUAGE_OF_ALIGNMENTS,
EBI_STOCHASTIC_PROCESS_TREE,
EBI_PROCESS_TREE_MARKUP_LANGUAGE,
EBI_EVENT_LOG_CSV,
EBI_PORTABLE_DOCUMENT_FORMAT,
EBI_SCALABLE_VECTOR_GRAPHICS,
EBI_PORTABLE_DOCUMENT_FORMAT,
EBI_PORTABLE_NETWORK_GRAPHCIS,
EBI_STOCHASTIC_NONDETERMINISTIC_FINITE_AUTOMATON,
EBI_PARTIALLY_ORDERED_WORKFLOW_LANGUAGE,
EBI_EVENT_LOG_PYTHON,
];
#[derive(Clone, Debug)]
pub struct EbiFileHandler {
pub name: &'static str,
pub article: &'static str, pub file_extension: &'static str,
pub is_binary: bool,
pub format_specification: &'static str,
pub validator: Option<fn(&mut dyn BufRead) -> Result<()>>,
pub trait_importers: &'static [EbiTraitImporter],
pub object_importers: &'static [EbiObjectImporter],
pub object_importers_fallible: &'static [EbiObjectImporterFallible],
pub object_exporters: &'static [EbiObjectExporter],
pub object_exporters_fallible: &'static [EbiObjectExporter],
pub java_object_handlers: &'static [JavaObjectHandler],
}
impl EbiFileHandler {
pub fn get_applicable_commands(&self) -> BTreeSet<Vec<&'static EbiCommand>> {
let mut result = BTreeSet::new();
for importer in self.trait_importers {
result.extend(importer.get_trait().get_applicable_commands());
}
for importer in self.object_importers {
result.extend(get_applicable_commands(&importer.get_type()));
}
if self.validator.is_some() {
result.insert(vec![&EBI_COMMANDS, &EBI_VALIDATE]);
}
result
}
pub fn get_producing_commands(&self) -> BTreeSet<Vec<&'static EbiCommand>> {
let mut objects = vec![];
for exporter in self.object_exporters {
objects.push(exporter.get_type());
}
for exporter in self.object_exporters_fallible {
objects.push(exporter.get_type());
}
let mut result = BTreeSet::new();
for command_path in EBI_COMMANDS.get_command_paths() {
if let Some(EbiCommand::Command { output_type, .. }) = command_path.last() {
if let EbiOutputType::ObjectType(x) = output_type {
if objects.contains(x) {
result.insert(command_path);
}
}
}
}
result
}
pub fn can_import_as_object(&self, object_type: &EbiObjectType) -> Tri {
for importer in self.object_importers {
if importer.get_type() == *object_type {
return Tri::Yes;
}
}
for importer in self.object_importers_fallible {
if importer.get_type() == *object_type {
return Tri::Fallible;
}
}
return Tri::No;
}
pub fn can_import_as_trait(&self, trait_type: &EbiTrait) -> bool {
for importer in self.trait_importers {
if importer.get_trait() == *trait_type {
return true;
}
}
return false;
}
pub fn can_export_as_object(&self, object_type: &EbiObjectType) -> Tri {
for exporter in self.object_exporters {
if exporter.get_type() == *object_type {
return Tri::Yes;
}
}
for exporter in self.object_exporters_fallible {
if exporter.get_type() == *object_type {
return Tri::Fallible;
}
}
return Tri::No;
}
}
impl FromStr for EbiFileHandler {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
for file_handler in EBI_FILE_HANDLERS {
if file_handler.validator.is_some()
&& (file_handler.name == s || file_handler.file_extension == s)
{
return Ok(file_handler.clone());
}
}
return Err(anyhow!("{} is not an Ebi file handler.", s));
}
}
impl FromStr for &'static EbiFileHandler {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
for file_handler in EBI_FILE_HANDLERS {
if file_handler.validator.is_some()
&& (file_handler.name == s || file_handler.file_extension == s)
{
return Ok(file_handler);
}
}
return Err(anyhow!("{} is not an Ebi file handler.", s));
}
}
impl FromEbiTraitObject for EbiFileHandler {
fn from_trait_object(object: EbiInput) -> Result<Box<Self>> {
match object {
EbiInput::FileHandler(e) => Ok(Box::new(e)),
_ => Err(anyhow!(
"cannot read {} {} as an file handler",
object.get_type().get_article(),
object.get_type()
)),
}
}
}
impl Eq for EbiFileHandler {}
impl PartialEq for EbiFileHandler {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl PartialOrd for EbiFileHandler {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.name
.to_lowercase()
.partial_cmp(&other.name.to_lowercase())
}
}
impl Ord for EbiFileHandler {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.to_lowercase().cmp(&other.name.to_lowercase())
}
}
impl Hash for EbiFileHandler {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl Display for EbiFileHandler {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} (.{})", self.name, self.file_extension)
}
}
pub fn get_file_handlers(object_type: &EbiObjectType) -> Vec<&'static EbiFileHandler> {
let mut result = vec![];
for file_handler in EBI_FILE_HANDLERS.iter() {
for importer in file_handler.object_importers {
if &importer.get_type() == object_type {
result.push(file_handler);
break;
}
}
}
result
}
pub fn get_file_handlers_fallible(object_type: &EbiObjectType) -> Vec<&'static EbiFileHandler> {
let mut result = vec![];
for file_handler in EBI_FILE_HANDLERS.iter() {
for importer in file_handler.object_importers_fallible {
if &importer.get_type() == object_type {
result.push(file_handler);
break;
}
}
}
result
}
pub enum Tri {
Yes,
No,
Fallible,
}
impl Tri {
pub fn to_latex_circle(&self) -> &str {
match self {
Tri::Yes => "\\CIRCLE",
Tri::Fallible => "\\LEFTcircle",
Tri::No => "\\Circle",
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::{
ebi_file_handlers::{
executions::EBI_EXECUTIONS, finite_stochastic_language::EBI_FINITE_STOCHASTIC_LANGUAGE,
process_tree::EBI_PROCESS_TREE,
stochastic_labelled_petri_net::EBI_STOCHASTIC_LABELLED_PETRI_NET,
},
ebi_framework::{
ebi_file_handler::EbiFileHandler, ebi_input::EbiInput, ebi_trait::FromEbiTraitObject,
},
};
#[test]
fn file_handlers() {
assert_eq!(
EbiFileHandler::from_str("slang").unwrap(),
EBI_FINITE_STOCHASTIC_LANGUAGE
);
assert!(EbiFileHandler::from_str("blablabla44252435").is_err());
EbiFileHandler::get_producing_commands(&EBI_PROCESS_TREE);
EbiFileHandler::get_producing_commands(&EBI_STOCHASTIC_LABELLED_PETRI_NET);
assert!(
EBI_PROCESS_TREE
.cmp(&EBI_STOCHASTIC_LABELLED_PETRI_NET)
.is_lt()
);
EbiFileHandler::from_trait_object(EbiInput::FileHandler(EBI_EXECUTIONS)).unwrap();
}
}