use macros_process_mining::register_binding;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use crate::analysis::object_centric::path_schemas::{
discover_path_schemas, enumerate_schemas, find_connections_with_sources, get_entities_of_type,
schema_stats, Connection, PathConnectionParams, PathSchemaDiscovery, PathSchemaQuery,
ResolvedPathSchema, SchemaStats, TypeEdge, TypeGraph, TypeRef,
};
use crate::core::event_data::object_centric::linked_ocel::SlimLinkedOCEL;
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct PathSchemaTypeNode {
pub name: String,
pub is_event: bool,
pub count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct PathSchemaTypeGraph {
pub nodes: Vec<PathSchemaTypeNode>,
pub edges: Vec<TypeEdge>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct PathSchemaConnections {
pub schema: String,
pub stats: SchemaStats,
pub connections: Vec<Connection>,
pub limit_reached: bool,
pub selectivity_pruned: bool,
}
#[register_binding]
fn path_schema_type_graph(ocel: &SlimLinkedOCEL) -> PathSchemaTypeGraph {
let type_graph = TypeGraph::from_linked_ocel(ocel);
let mut nodes =
Vec::with_capacity(type_graph.event_types.len() + type_graph.object_types.len());
for name in &type_graph.event_types {
nodes.push(PathSchemaTypeNode {
count: ocel.get_evs_of_type(name).count(),
name: name.clone(),
is_event: true,
});
}
for name in &type_graph.object_types {
nodes.push(PathSchemaTypeNode {
count: ocel.get_obs_of_type(name).count(),
name: name.clone(),
is_event: false,
});
}
PathSchemaTypeGraph {
nodes,
edges: type_graph.edges,
}
}
#[register_binding]
fn path_schema_enumerate(
ocel: &SlimLinkedOCEL,
source: TypeRef,
#[bind(default)] target: Option<TypeRef>,
max_length: usize,
#[bind(default)] allow_cycles: bool,
#[bind(default)] allowed_types: Option<Vec<TypeRef>>,
) -> Vec<ResolvedPathSchema> {
let type_graph = TypeGraph::from_linked_ocel(ocel);
let allowed: Option<HashSet<TypeRef>> = allowed_types.map(|types| types.into_iter().collect());
enumerate_schemas(
&type_graph,
&source,
target.as_ref(),
max_length,
allow_cycles,
allowed.as_ref(),
)
.iter()
.map(|sch| sch.resolve(&type_graph))
.collect()
}
#[register_binding]
fn path_schema_discover(ocel: &SlimLinkedOCEL, query: PathSchemaQuery) -> PathSchemaDiscovery {
discover_path_schemas(ocel, &query)
}
#[register_binding]
fn path_schema_connections(
ocel: &SlimLinkedOCEL,
schema: ResolvedPathSchema,
#[bind(default)] params: PathConnectionParams,
) -> PathSchemaConnections {
let sources = get_entities_of_type(ocel, &schema.source);
let total_sources = sources.len();
let total_targets = get_entities_of_type(ocel, &schema.target).len();
let result = find_connections_with_sources(ocel, &schema, &sources, ¶ms);
let stats = schema_stats(&result.connections, total_sources, total_targets);
PathSchemaConnections {
schema: schema.display(),
stats,
connections: result.connections,
limit_reached: result.limit_reached,
selectivity_pruned: result.selectivity_pruned,
}
}