Skip to main content

oxirs_stream/
event.rs

1//! # Stream Events
2//!
3//! Event types for RDF streaming with comprehensive metadata and provenance tracking.
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::time::Duration;
9use uuid;
10
11// Event metadata is defined as a struct below
12
13/// Enhanced RDF streaming events with metadata and provenance
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub enum StreamEvent {
16    TripleAdded {
17        subject: String,
18        predicate: String,
19        object: String,
20        graph: Option<String>,
21        metadata: EventMetadata,
22    },
23    TripleRemoved {
24        subject: String,
25        predicate: String,
26        object: String,
27        graph: Option<String>,
28        metadata: EventMetadata,
29    },
30    QuadAdded {
31        subject: String,
32        predicate: String,
33        object: String,
34        graph: String,
35        metadata: EventMetadata,
36    },
37    QuadRemoved {
38        subject: String,
39        predicate: String,
40        object: String,
41        graph: String,
42        metadata: EventMetadata,
43    },
44    GraphCreated {
45        graph: String,
46        metadata: EventMetadata,
47    },
48    GraphCleared {
49        graph: Option<String>,
50        metadata: EventMetadata,
51    },
52    GraphDeleted {
53        graph: String,
54        metadata: EventMetadata,
55    },
56    SparqlUpdate {
57        query: String,
58        operation_type: SparqlOperationType,
59        metadata: EventMetadata,
60    },
61    TransactionBegin {
62        transaction_id: String,
63        isolation_level: Option<IsolationLevel>,
64        metadata: EventMetadata,
65    },
66    TransactionCommit {
67        transaction_id: String,
68        metadata: EventMetadata,
69    },
70    TransactionAbort {
71        transaction_id: String,
72        metadata: EventMetadata,
73    },
74    SchemaChanged {
75        schema_type: SchemaType,
76        change_type: SchemaChangeType,
77        details: String,
78        metadata: EventMetadata,
79    },
80    Heartbeat {
81        timestamp: DateTime<Utc>,
82        source: String,
83        metadata: EventMetadata,
84    },
85    QueryResultAdded {
86        query_id: String,
87        result: QueryResult,
88        metadata: EventMetadata,
89    },
90    QueryResultRemoved {
91        query_id: String,
92        result: QueryResult,
93        metadata: EventMetadata,
94    },
95    QueryCompleted {
96        query_id: String,
97        execution_time: Duration,
98        metadata: EventMetadata,
99    },
100
101    // Named Graph Events
102    GraphMetadataUpdated {
103        graph: String,
104        metadata_type: String,
105        old_value: Option<String>,
106        new_value: String,
107        metadata: EventMetadata,
108    },
109    GraphPermissionsChanged {
110        graph: String,
111        permission_type: String, // "read", "write", "admin"
112        principal: String,       // user or role
113        granted: bool,
114        metadata: EventMetadata,
115    },
116    GraphStatisticsUpdated {
117        graph: String,
118        triple_count: u64,
119        size_bytes: u64,
120        last_modified: u64,
121        metadata: EventMetadata,
122    },
123    GraphRenamed {
124        old_name: String,
125        new_name: String,
126        metadata: EventMetadata,
127    },
128    GraphMerged {
129        source_graphs: Vec<String>,
130        target_graph: String,
131        metadata: EventMetadata,
132    },
133    GraphSplit {
134        source_graph: String,
135        target_graphs: Vec<String>,
136        split_criteria: String,
137        metadata: EventMetadata,
138    },
139
140    // Schema Change Events
141    SchemaDefinitionAdded {
142        schema_type: String, // "class", "property", "datatype"
143        schema_uri: String,
144        definition: String,
145        metadata: EventMetadata,
146    },
147    SchemaDefinitionRemoved {
148        schema_type: String,
149        schema_uri: String,
150        metadata: EventMetadata,
151    },
152    SchemaDefinitionModified {
153        schema_type: String,
154        schema_uri: String,
155        old_definition: String,
156        new_definition: String,
157        metadata: EventMetadata,
158    },
159    OntologyImported {
160        ontology_uri: String,
161        version: Option<String>,
162        import_method: String, // "owl:imports", "explicit", "inference"
163        metadata: EventMetadata,
164    },
165    OntologyRemoved {
166        ontology_uri: String,
167        version: Option<String>,
168        metadata: EventMetadata,
169    },
170    ConstraintAdded {
171        constraint_type: String, // "cardinality", "range", "domain", "functional"
172        target: String,          // property or class URI
173        constraint_definition: String,
174        metadata: EventMetadata,
175    },
176    ConstraintRemoved {
177        constraint_type: String,
178        target: String,
179        constraint_definition: String,
180        metadata: EventMetadata,
181    },
182    ConstraintViolated {
183        constraint_type: String,
184        target: String,
185        violating_data: String,
186        severity: String, // "error", "warning", "info"
187        metadata: EventMetadata,
188    },
189    IndexCreated {
190        index_name: String,
191        index_type: String, // "btree", "hash", "fulltext", "spatial"
192        target_properties: Vec<String>,
193        graph: Option<String>,
194        metadata: EventMetadata,
195    },
196    IndexDropped {
197        index_name: String,
198        index_type: String,
199        metadata: EventMetadata,
200    },
201    IndexRebuilt {
202        index_name: String,
203        reason: String,
204        duration_ms: u64,
205        metadata: EventMetadata,
206    },
207
208    // Schema Update Events
209    SchemaUpdated {
210        schema_uri: String,
211        update_type: String,
212        old_definition: Option<String>,
213        new_definition: String,
214        metadata: EventMetadata,
215    },
216
217    // SHACL Shape Events
218    ShapeAdded {
219        shape_uri: String,
220        shape_definition: String,
221        target_class: Option<String>,
222        metadata: EventMetadata,
223    },
224    ShapeUpdated {
225        shape_uri: String,
226        old_definition: String,
227        new_definition: String,
228        target_class: Option<String>,
229        metadata: EventMetadata,
230    },
231    ShapeRemoved {
232        shape_uri: String,
233        metadata: EventMetadata,
234    },
235    ShapeModified {
236        shape_uri: String,
237        old_definition: String,
238        new_definition: String,
239        metadata: EventMetadata,
240    },
241    ShapeValidationStarted {
242        shape_uri: String,
243        target_graph: Option<String>,
244        validation_id: String,
245        metadata: EventMetadata,
246    },
247    ShapeValidationCompleted {
248        shape_uri: String,
249        validation_id: String,
250        success: bool,
251        violation_count: u32,
252        duration_ms: u64,
253        metadata: EventMetadata,
254    },
255    ShapeViolationDetected {
256        shape_uri: String,
257        violation_path: String,
258        violating_node: String,
259        severity: String,
260        message: String,
261        metadata: EventMetadata,
262    },
263
264    // Error Events
265    ErrorOccurred {
266        error_type: String,
267        error_message: String,
268        error_context: Option<String>,
269        metadata: EventMetadata,
270    },
271}
272
273impl StreamEvent {
274    /// Extract timestamp from any StreamEvent variant
275    pub fn timestamp(&self) -> DateTime<Utc> {
276        match self {
277            StreamEvent::TripleAdded { metadata, .. } => metadata.timestamp,
278            StreamEvent::TripleRemoved { metadata, .. } => metadata.timestamp,
279            StreamEvent::QuadAdded { metadata, .. } => metadata.timestamp,
280            StreamEvent::QuadRemoved { metadata, .. } => metadata.timestamp,
281            StreamEvent::GraphCreated { metadata, .. } => metadata.timestamp,
282            StreamEvent::GraphCleared { metadata, .. } => metadata.timestamp,
283            StreamEvent::GraphDeleted { metadata, .. } => metadata.timestamp,
284            StreamEvent::SparqlUpdate { metadata, .. } => metadata.timestamp,
285            StreamEvent::TransactionBegin { metadata, .. } => metadata.timestamp,
286            StreamEvent::TransactionCommit { metadata, .. } => metadata.timestamp,
287            StreamEvent::TransactionAbort { metadata, .. } => metadata.timestamp,
288            StreamEvent::SchemaChanged { metadata, .. } => metadata.timestamp,
289            StreamEvent::Heartbeat { timestamp, .. } => *timestamp,
290            StreamEvent::QueryResultAdded { metadata, .. } => metadata.timestamp,
291            StreamEvent::QueryResultRemoved { metadata, .. } => metadata.timestamp,
292            StreamEvent::QueryCompleted { metadata, .. } => metadata.timestamp,
293            StreamEvent::GraphMetadataUpdated { metadata, .. } => metadata.timestamp,
294            StreamEvent::GraphPermissionsChanged { metadata, .. } => metadata.timestamp,
295            StreamEvent::GraphStatisticsUpdated { metadata, .. } => metadata.timestamp,
296            StreamEvent::GraphRenamed { metadata, .. } => metadata.timestamp,
297            StreamEvent::GraphMerged { metadata, .. } => metadata.timestamp,
298            StreamEvent::GraphSplit { metadata, .. } => metadata.timestamp,
299            StreamEvent::SchemaDefinitionAdded { metadata, .. } => metadata.timestamp,
300            StreamEvent::SchemaDefinitionRemoved { metadata, .. } => metadata.timestamp,
301            StreamEvent::SchemaDefinitionModified { metadata, .. } => metadata.timestamp,
302            StreamEvent::OntologyImported { metadata, .. } => metadata.timestamp,
303            StreamEvent::OntologyRemoved { metadata, .. } => metadata.timestamp,
304            StreamEvent::ConstraintAdded { metadata, .. } => metadata.timestamp,
305            StreamEvent::ConstraintRemoved { metadata, .. } => metadata.timestamp,
306            StreamEvent::ConstraintViolated { metadata, .. } => metadata.timestamp,
307            StreamEvent::IndexCreated { metadata, .. } => metadata.timestamp,
308            StreamEvent::IndexDropped { metadata, .. } => metadata.timestamp,
309            StreamEvent::IndexRebuilt { metadata, .. } => metadata.timestamp,
310            StreamEvent::SchemaUpdated { metadata, .. } => metadata.timestamp,
311            StreamEvent::ShapeAdded { metadata, .. } => metadata.timestamp,
312            StreamEvent::ShapeUpdated { metadata, .. } => metadata.timestamp,
313            StreamEvent::ShapeRemoved { metadata, .. } => metadata.timestamp,
314            StreamEvent::ShapeModified { metadata, .. } => metadata.timestamp,
315            StreamEvent::ShapeValidationStarted { metadata, .. } => metadata.timestamp,
316            StreamEvent::ShapeValidationCompleted { metadata, .. } => metadata.timestamp,
317            StreamEvent::ShapeViolationDetected { metadata, .. } => metadata.timestamp,
318            StreamEvent::ErrorOccurred { metadata, .. } => metadata.timestamp,
319        }
320    }
321
322    /// Extract event ID from any StreamEvent variant
323    pub fn event_id(&self) -> &str {
324        match self {
325            StreamEvent::TripleAdded { metadata, .. } => &metadata.event_id,
326            StreamEvent::TripleRemoved { metadata, .. } => &metadata.event_id,
327            StreamEvent::QuadAdded { metadata, .. } => &metadata.event_id,
328            StreamEvent::QuadRemoved { metadata, .. } => &metadata.event_id,
329            StreamEvent::GraphCreated { metadata, .. } => &metadata.event_id,
330            StreamEvent::GraphCleared { metadata, .. } => &metadata.event_id,
331            StreamEvent::GraphDeleted { metadata, .. } => &metadata.event_id,
332            StreamEvent::SparqlUpdate { metadata, .. } => &metadata.event_id,
333            StreamEvent::TransactionBegin { metadata, .. } => &metadata.event_id,
334            StreamEvent::TransactionCommit { metadata, .. } => &metadata.event_id,
335            StreamEvent::TransactionAbort { metadata, .. } => &metadata.event_id,
336            StreamEvent::SchemaChanged { metadata, .. } => &metadata.event_id,
337            StreamEvent::Heartbeat { metadata, .. } => &metadata.event_id,
338            StreamEvent::QueryResultAdded { metadata, .. } => &metadata.event_id,
339            StreamEvent::QueryResultRemoved { metadata, .. } => &metadata.event_id,
340            StreamEvent::QueryCompleted { metadata, .. } => &metadata.event_id,
341            StreamEvent::GraphMetadataUpdated { metadata, .. } => &metadata.event_id,
342            StreamEvent::GraphPermissionsChanged { metadata, .. } => &metadata.event_id,
343            StreamEvent::GraphStatisticsUpdated { metadata, .. } => &metadata.event_id,
344            StreamEvent::GraphRenamed { metadata, .. } => &metadata.event_id,
345            StreamEvent::GraphMerged { metadata, .. } => &metadata.event_id,
346            StreamEvent::GraphSplit { metadata, .. } => &metadata.event_id,
347            StreamEvent::SchemaDefinitionAdded { metadata, .. } => &metadata.event_id,
348            StreamEvent::SchemaDefinitionRemoved { metadata, .. } => &metadata.event_id,
349            StreamEvent::SchemaDefinitionModified { metadata, .. } => &metadata.event_id,
350            StreamEvent::OntologyImported { metadata, .. } => &metadata.event_id,
351            StreamEvent::OntologyRemoved { metadata, .. } => &metadata.event_id,
352            StreamEvent::ConstraintAdded { metadata, .. } => &metadata.event_id,
353            StreamEvent::ConstraintRemoved { metadata, .. } => &metadata.event_id,
354            StreamEvent::ConstraintViolated { metadata, .. } => &metadata.event_id,
355            StreamEvent::IndexCreated { metadata, .. } => &metadata.event_id,
356            StreamEvent::IndexDropped { metadata, .. } => &metadata.event_id,
357            StreamEvent::IndexRebuilt { metadata, .. } => &metadata.event_id,
358            StreamEvent::SchemaUpdated { metadata, .. } => &metadata.event_id,
359            StreamEvent::ShapeAdded { metadata, .. } => &metadata.event_id,
360            StreamEvent::ShapeUpdated { metadata, .. } => &metadata.event_id,
361            StreamEvent::ShapeRemoved { metadata, .. } => &metadata.event_id,
362            StreamEvent::ShapeModified { metadata, .. } => &metadata.event_id,
363            StreamEvent::ShapeValidationStarted { metadata, .. } => &metadata.event_id,
364            StreamEvent::ShapeValidationCompleted { metadata, .. } => &metadata.event_id,
365            StreamEvent::ShapeViolationDetected { metadata, .. } => &metadata.event_id,
366            StreamEvent::ErrorOccurred { metadata, .. } => &metadata.event_id,
367        }
368    }
369}
370
371/// Event metadata for tracking and provenance
372#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct EventMetadata {
374    /// Unique event identifier
375    pub event_id: String,
376    /// Event timestamp
377    pub timestamp: DateTime<Utc>,
378    /// Source identification
379    pub source: String,
380    /// User/session that triggered the event
381    pub user: Option<String>,
382    /// Operation context
383    pub context: Option<String>,
384    /// Causality tracking - event that caused this event
385    pub caused_by: Option<String>,
386    /// Event version for schema evolution
387    pub version: String,
388    /// Custom properties
389    pub properties: HashMap<String, String>,
390    /// Checksum for integrity
391    pub checksum: Option<String>,
392}
393
394impl Default for EventMetadata {
395    fn default() -> Self {
396        Self {
397            event_id: uuid::Uuid::new_v4().to_string(),
398            timestamp: chrono::Utc::now(),
399            source: "default".to_string(),
400            user: None,
401            context: None,
402            caused_by: None,
403            version: "1.0".to_string(),
404            properties: HashMap::new(),
405            checksum: None,
406        }
407    }
408}
409
410/// SPARQL operation types
411#[derive(Debug, Clone, Serialize, Deserialize)]
412pub enum SparqlOperationType {
413    Insert,
414    Delete,
415    Update,
416    Load,
417    Clear,
418    Create,
419    Drop,
420    Copy,
421    Move,
422    Add,
423}
424
425/// Transaction isolation levels
426#[derive(Debug, Clone, Serialize, Deserialize)]
427pub enum IsolationLevel {
428    ReadUncommitted,
429    ReadCommitted,
430    RepeatableRead,
431    Serializable,
432}
433
434/// Schema types
435#[derive(Debug, Clone, Serialize, Deserialize)]
436pub enum SchemaType {
437    Ontology,
438    Vocabulary,
439    Constraint,
440    Rule,
441}
442
443/// Schema change types
444#[derive(Debug, Clone, Serialize, Deserialize)]
445pub enum SchemaChangeType {
446    Added,
447    Modified,
448    Removed,
449    Versioned,
450}
451
452/// Stream event types for classification and filtering
453#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
454pub enum StreamEventType {
455    TripleAdded,
456    TripleRemoved,
457    QuadAdded,
458    QuadRemoved,
459    GraphCreated,
460    GraphCleared,
461    GraphDeleted,
462    GraphMetadataUpdated,
463    GraphPermissionsChanged,
464    GraphStatisticsUpdated,
465    GraphRenamed,
466    GraphMerged,
467    GraphSplit,
468    SparqlUpdate,
469    TransactionBegin,
470    TransactionCommit,
471    TransactionAbort,
472    SchemaChanged,
473    SchemaDefinitionAdded,
474    SchemaDefinitionRemoved,
475    SchemaDefinitionModified,
476    OntologyImported,
477    OntologyRemoved,
478    ConstraintAdded,
479    ConstraintRemoved,
480    ConstraintViolated,
481    IndexCreated,
482    IndexDropped,
483    IndexRebuilt,
484    SchemaUpdated,
485    ShapeAdded,
486    ShapeRemoved,
487    ShapeModified,
488    ShapeUpdated,
489    ShapeValidationStarted,
490    ShapeValidationCompleted,
491    ShapeViolationDetected,
492    QueryResultAdded,
493    QueryResultRemoved,
494    QueryCompleted,
495    Heartbeat,
496    ErrorOccurred,
497}
498
499/// Query result placeholder (to be imported from store integration)
500#[derive(Debug, Clone, Serialize, Deserialize)]
501pub struct QueryResult {
502    pub query_id: String,
503    pub bindings: HashMap<String, String>,
504    pub execution_time: Duration,
505}
506
507impl StreamEvent {
508    /// Get the metadata for this event
509    pub fn metadata(&self) -> &EventMetadata {
510        match self {
511            StreamEvent::TripleAdded { metadata, .. } => metadata,
512            StreamEvent::TripleRemoved { metadata, .. } => metadata,
513            StreamEvent::QuadAdded { metadata, .. } => metadata,
514            StreamEvent::QuadRemoved { metadata, .. } => metadata,
515            StreamEvent::GraphCreated { metadata, .. } => metadata,
516            StreamEvent::GraphCleared { metadata, .. } => metadata,
517            StreamEvent::GraphDeleted { metadata, .. } => metadata,
518            StreamEvent::GraphMetadataUpdated { metadata, .. } => metadata,
519            StreamEvent::GraphPermissionsChanged { metadata, .. } => metadata,
520            StreamEvent::GraphStatisticsUpdated { metadata, .. } => metadata,
521            StreamEvent::GraphRenamed { metadata, .. } => metadata,
522            StreamEvent::GraphMerged { metadata, .. } => metadata,
523            StreamEvent::GraphSplit { metadata, .. } => metadata,
524            StreamEvent::SparqlUpdate { metadata, .. } => metadata,
525            StreamEvent::TransactionBegin { metadata, .. } => metadata,
526            StreamEvent::TransactionCommit { metadata, .. } => metadata,
527            StreamEvent::TransactionAbort { metadata, .. } => metadata,
528            StreamEvent::SchemaChanged { metadata, .. } => metadata,
529            StreamEvent::SchemaDefinitionAdded { metadata, .. } => metadata,
530            StreamEvent::SchemaDefinitionRemoved { metadata, .. } => metadata,
531            StreamEvent::SchemaDefinitionModified { metadata, .. } => metadata,
532            StreamEvent::OntologyImported { metadata, .. } => metadata,
533            StreamEvent::OntologyRemoved { metadata, .. } => metadata,
534            StreamEvent::ConstraintAdded { metadata, .. } => metadata,
535            StreamEvent::ConstraintRemoved { metadata, .. } => metadata,
536            StreamEvent::ConstraintViolated { metadata, .. } => metadata,
537            StreamEvent::IndexCreated { metadata, .. } => metadata,
538            StreamEvent::IndexDropped { metadata, .. } => metadata,
539            StreamEvent::IndexRebuilt { metadata, .. } => metadata,
540            StreamEvent::SchemaUpdated { metadata, .. } => metadata,
541            StreamEvent::ShapeAdded { metadata, .. } => metadata,
542            StreamEvent::ShapeRemoved { metadata, .. } => metadata,
543            StreamEvent::ShapeModified { metadata, .. } => metadata,
544            StreamEvent::ShapeUpdated { metadata, .. } => metadata,
545            StreamEvent::ShapeValidationStarted { metadata, .. } => metadata,
546            StreamEvent::ShapeValidationCompleted { metadata, .. } => metadata,
547            StreamEvent::ShapeViolationDetected { metadata, .. } => metadata,
548            StreamEvent::QueryResultAdded { metadata, .. } => metadata,
549            StreamEvent::QueryResultRemoved { metadata, .. } => metadata,
550            StreamEvent::QueryCompleted { metadata, .. } => metadata,
551            StreamEvent::Heartbeat { metadata, .. } => metadata,
552            StreamEvent::ErrorOccurred { metadata, .. } => metadata,
553        }
554    }
555
556    // Helper methods for creating specific event types
557
558    /// Create a named graph metadata update event
559    pub fn graph_metadata_updated(
560        graph: String,
561        metadata_type: String,
562        old_value: Option<String>,
563        new_value: String,
564    ) -> Self {
565        StreamEvent::GraphMetadataUpdated {
566            graph,
567            metadata_type,
568            old_value,
569            new_value,
570            metadata: EventMetadata::default(),
571        }
572    }
573
574    /// Create a graph permissions change event
575    pub fn graph_permissions_changed(
576        graph: String,
577        permission_type: String,
578        principal: String,
579        granted: bool,
580    ) -> Self {
581        StreamEvent::GraphPermissionsChanged {
582            graph,
583            permission_type,
584            principal,
585            granted,
586            metadata: EventMetadata::default(),
587        }
588    }
589
590    /// Create a graph statistics update event
591    pub fn graph_statistics_updated(graph: String, triple_count: u64, size_bytes: u64) -> Self {
592        StreamEvent::GraphStatisticsUpdated {
593            graph,
594            triple_count,
595            size_bytes,
596            last_modified: std::time::SystemTime::now()
597                .duration_since(std::time::UNIX_EPOCH)
598                .expect("SystemTime should be after UNIX_EPOCH")
599                .as_secs(),
600            metadata: EventMetadata::default(),
601        }
602    }
603
604    /// Create a schema definition added event
605    pub fn schema_definition_added(
606        schema_type: String,
607        schema_uri: String,
608        definition: String,
609    ) -> Self {
610        StreamEvent::SchemaDefinitionAdded {
611            schema_type,
612            schema_uri,
613            definition,
614            metadata: EventMetadata::default(),
615        }
616    }
617
618    /// Create a schema definition modified event
619    pub fn schema_definition_modified(
620        schema_type: String,
621        schema_uri: String,
622        old_definition: String,
623        new_definition: String,
624    ) -> Self {
625        StreamEvent::SchemaDefinitionModified {
626            schema_type,
627            schema_uri,
628            old_definition,
629            new_definition,
630            metadata: EventMetadata::default(),
631        }
632    }
633
634    /// Create an ontology import event
635    pub fn ontology_imported(
636        ontology_uri: String,
637        version: Option<String>,
638        import_method: String,
639    ) -> Self {
640        StreamEvent::OntologyImported {
641            ontology_uri,
642            version,
643            import_method,
644            metadata: EventMetadata::default(),
645        }
646    }
647
648    /// Create a constraint violation event
649    pub fn constraint_violated(
650        constraint_type: String,
651        target: String,
652        violating_data: String,
653        severity: String,
654    ) -> Self {
655        StreamEvent::ConstraintViolated {
656            constraint_type,
657            target,
658            violating_data,
659            severity,
660            metadata: EventMetadata::default(),
661        }
662    }
663
664    /// Create an index creation event
665    pub fn index_created(
666        index_name: String,
667        index_type: String,
668        target_properties: Vec<String>,
669        graph: Option<String>,
670    ) -> Self {
671        StreamEvent::IndexCreated {
672            index_name,
673            index_type,
674            target_properties,
675            graph,
676            metadata: EventMetadata::default(),
677        }
678    }
679
680    /// Create a SHACL shape added event
681    pub fn shape_added(
682        shape_uri: String,
683        shape_definition: String,
684        target_class: Option<String>,
685    ) -> Self {
686        StreamEvent::ShapeAdded {
687            shape_uri,
688            shape_definition,
689            target_class,
690            metadata: EventMetadata::default(),
691        }
692    }
693
694    /// Create a SHACL shape validation completed event
695    pub fn shape_validation_completed(
696        shape_uri: String,
697        validation_id: String,
698        success: bool,
699        violation_count: u32,
700        duration_ms: u64,
701    ) -> Self {
702        StreamEvent::ShapeValidationCompleted {
703            shape_uri,
704            validation_id,
705            success,
706            violation_count,
707            duration_ms,
708            metadata: EventMetadata::default(),
709        }
710    }
711
712    /// Create a SHACL shape violation detected event
713    pub fn shape_violation_detected(
714        shape_uri: String,
715        violation_path: String,
716        violating_node: String,
717        severity: String,
718        message: String,
719    ) -> Self {
720        StreamEvent::ShapeViolationDetected {
721            shape_uri,
722            violation_path,
723            violating_node,
724            severity,
725            message,
726            metadata: EventMetadata::default(),
727        }
728    }
729
730    /// Get the event category for classification
731    pub fn category(&self) -> EventCategory {
732        match self {
733            StreamEvent::TripleAdded { .. }
734            | StreamEvent::TripleRemoved { .. }
735            | StreamEvent::QuadAdded { .. }
736            | StreamEvent::QuadRemoved { .. } => EventCategory::Data,
737
738            StreamEvent::GraphCreated { .. }
739            | StreamEvent::GraphCleared { .. }
740            | StreamEvent::GraphDeleted { .. }
741            | StreamEvent::GraphMetadataUpdated { .. }
742            | StreamEvent::GraphPermissionsChanged { .. }
743            | StreamEvent::GraphStatisticsUpdated { .. }
744            | StreamEvent::GraphRenamed { .. }
745            | StreamEvent::GraphMerged { .. }
746            | StreamEvent::GraphSplit { .. } => EventCategory::Graph,
747
748            StreamEvent::TransactionBegin { .. }
749            | StreamEvent::TransactionCommit { .. }
750            | StreamEvent::TransactionAbort { .. } => EventCategory::Transaction,
751
752            StreamEvent::SchemaChanged { .. }
753            | StreamEvent::SchemaDefinitionAdded { .. }
754            | StreamEvent::SchemaDefinitionRemoved { .. }
755            | StreamEvent::SchemaDefinitionModified { .. }
756            | StreamEvent::SchemaUpdated { .. }
757            | StreamEvent::OntologyImported { .. }
758            | StreamEvent::OntologyRemoved { .. }
759            | StreamEvent::ConstraintAdded { .. }
760            | StreamEvent::ConstraintRemoved { .. }
761            | StreamEvent::ConstraintViolated { .. } => EventCategory::Schema,
762
763            StreamEvent::IndexCreated { .. }
764            | StreamEvent::IndexDropped { .. }
765            | StreamEvent::IndexRebuilt { .. } => EventCategory::Index,
766
767            StreamEvent::ShapeAdded { .. }
768            | StreamEvent::ShapeRemoved { .. }
769            | StreamEvent::ShapeModified { .. }
770            | StreamEvent::ShapeUpdated { .. }
771            | StreamEvent::ShapeValidationStarted { .. }
772            | StreamEvent::ShapeValidationCompleted { .. }
773            | StreamEvent::ShapeViolationDetected { .. } => EventCategory::Shape,
774
775            StreamEvent::SparqlUpdate { .. } => EventCategory::Query,
776
777            StreamEvent::QueryResultAdded { .. }
778            | StreamEvent::QueryResultRemoved { .. }
779            | StreamEvent::QueryCompleted { .. } => EventCategory::Query,
780
781            StreamEvent::Heartbeat { .. } => EventCategory::Data,
782
783            StreamEvent::ErrorOccurred { .. } => EventCategory::Data,
784        }
785    }
786
787    /// Get the specific event type for filtering and classification
788    pub fn event_type(&self) -> StreamEventType {
789        match self {
790            StreamEvent::TripleAdded { .. } => StreamEventType::TripleAdded,
791            StreamEvent::TripleRemoved { .. } => StreamEventType::TripleRemoved,
792            StreamEvent::QuadAdded { .. } => StreamEventType::QuadAdded,
793            StreamEvent::QuadRemoved { .. } => StreamEventType::QuadRemoved,
794            StreamEvent::GraphCreated { .. } => StreamEventType::GraphCreated,
795            StreamEvent::GraphCleared { .. } => StreamEventType::GraphCleared,
796            StreamEvent::GraphDeleted { .. } => StreamEventType::GraphDeleted,
797            StreamEvent::GraphMetadataUpdated { .. } => StreamEventType::GraphMetadataUpdated,
798            StreamEvent::GraphPermissionsChanged { .. } => StreamEventType::GraphPermissionsChanged,
799            StreamEvent::GraphStatisticsUpdated { .. } => StreamEventType::GraphStatisticsUpdated,
800            StreamEvent::GraphRenamed { .. } => StreamEventType::GraphRenamed,
801            StreamEvent::GraphMerged { .. } => StreamEventType::GraphMerged,
802            StreamEvent::GraphSplit { .. } => StreamEventType::GraphSplit,
803            StreamEvent::SparqlUpdate { .. } => StreamEventType::SparqlUpdate,
804            StreamEvent::TransactionBegin { .. } => StreamEventType::TransactionBegin,
805            StreamEvent::TransactionCommit { .. } => StreamEventType::TransactionCommit,
806            StreamEvent::TransactionAbort { .. } => StreamEventType::TransactionAbort,
807            StreamEvent::SchemaChanged { .. } => StreamEventType::SchemaChanged,
808            StreamEvent::SchemaDefinitionAdded { .. } => StreamEventType::SchemaDefinitionAdded,
809            StreamEvent::SchemaDefinitionRemoved { .. } => StreamEventType::SchemaDefinitionRemoved,
810            StreamEvent::SchemaDefinitionModified { .. } => {
811                StreamEventType::SchemaDefinitionModified
812            }
813            StreamEvent::OntologyImported { .. } => StreamEventType::OntologyImported,
814            StreamEvent::OntologyRemoved { .. } => StreamEventType::OntologyRemoved,
815            StreamEvent::ConstraintAdded { .. } => StreamEventType::ConstraintAdded,
816            StreamEvent::ConstraintRemoved { .. } => StreamEventType::ConstraintRemoved,
817            StreamEvent::ConstraintViolated { .. } => StreamEventType::ConstraintViolated,
818            StreamEvent::IndexCreated { .. } => StreamEventType::IndexCreated,
819            StreamEvent::IndexDropped { .. } => StreamEventType::IndexDropped,
820            StreamEvent::IndexRebuilt { .. } => StreamEventType::IndexRebuilt,
821            StreamEvent::SchemaUpdated { .. } => StreamEventType::SchemaUpdated,
822            StreamEvent::ShapeAdded { .. } => StreamEventType::ShapeAdded,
823            StreamEvent::ShapeRemoved { .. } => StreamEventType::ShapeRemoved,
824            StreamEvent::ShapeModified { .. } => StreamEventType::ShapeModified,
825            StreamEvent::ShapeUpdated { .. } => StreamEventType::ShapeUpdated,
826            StreamEvent::ShapeValidationStarted { .. } => StreamEventType::ShapeValidationStarted,
827            StreamEvent::ShapeValidationCompleted { .. } => {
828                StreamEventType::ShapeValidationCompleted
829            }
830            StreamEvent::ShapeViolationDetected { .. } => StreamEventType::ShapeViolationDetected,
831            StreamEvent::QueryResultAdded { .. } => StreamEventType::QueryResultAdded,
832            StreamEvent::QueryResultRemoved { .. } => StreamEventType::QueryResultRemoved,
833            StreamEvent::QueryCompleted { .. } => StreamEventType::QueryCompleted,
834            StreamEvent::Heartbeat { .. } => StreamEventType::Heartbeat,
835            StreamEvent::ErrorOccurred { .. } => StreamEventType::ErrorOccurred,
836        }
837    }
838
839    /// Check if this event affects a specific graph
840    pub fn affects_graph(&self, target_graph: &str) -> bool {
841        match self {
842            StreamEvent::TripleAdded { graph, .. } | StreamEvent::TripleRemoved { graph, .. } => {
843                graph.as_ref().is_some_and(|g| g == target_graph)
844            }
845            StreamEvent::QuadAdded { graph, .. } | StreamEvent::QuadRemoved { graph, .. } => {
846                graph == target_graph
847            }
848            StreamEvent::GraphCreated { graph, .. }
849            | StreamEvent::GraphDeleted { graph, .. }
850            | StreamEvent::GraphMetadataUpdated { graph, .. }
851            | StreamEvent::GraphPermissionsChanged { graph, .. }
852            | StreamEvent::GraphStatisticsUpdated { graph, .. } => graph == target_graph,
853            StreamEvent::GraphCleared { graph, .. } => {
854                graph.as_ref().map_or(true, |g| g == target_graph)
855            }
856            StreamEvent::GraphRenamed {
857                old_name, new_name, ..
858            } => old_name == target_graph || new_name == target_graph,
859            StreamEvent::GraphMerged {
860                source_graphs,
861                target_graph: target,
862                ..
863            } => source_graphs.contains(&target_graph.to_string()) || target == target_graph,
864            StreamEvent::GraphSplit {
865                source_graph,
866                target_graphs,
867                ..
868            } => source_graph == target_graph || target_graphs.contains(&target_graph.to_string()),
869            StreamEvent::IndexCreated { graph, .. } => {
870                graph.as_ref().is_some_and(|g| g == target_graph)
871            }
872            StreamEvent::ShapeValidationStarted {
873                target_graph: shape_target,
874                ..
875            } => shape_target.as_ref().is_some_and(|g| g == target_graph),
876            _ => false,
877        }
878    }
879
880    /// Get the priority level of this event
881    pub fn priority(&self) -> EventPriority {
882        match self {
883            StreamEvent::ConstraintViolated { severity, .. } => match severity.as_str() {
884                "error" => EventPriority::High,
885                "warning" => EventPriority::Medium,
886                _ => EventPriority::Low,
887            },
888            StreamEvent::ShapeViolationDetected { severity, .. } => match severity.as_str() {
889                "error" => EventPriority::High,
890                "warning" => EventPriority::Medium,
891                _ => EventPriority::Low,
892            },
893            StreamEvent::TransactionAbort { .. } | StreamEvent::GraphDeleted { .. } => {
894                EventPriority::High
895            }
896            StreamEvent::IndexDropped { .. }
897            | StreamEvent::OntologyRemoved { .. }
898            | StreamEvent::SchemaDefinitionRemoved { .. } => EventPriority::Medium,
899            _ => EventPriority::Low,
900        }
901    }
902}
903
904/// Event categories for classification and filtering
905#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
906pub enum EventCategory {
907    Data,        // Triple/Quad operations
908    Graph,       // Graph management
909    Transaction, // Transaction control
910    Schema,      // Schema and ontology changes
911    Index,       // Index management
912    Shape,       // SHACL shapes and validation
913    Query,       // SPARQL operations
914}
915
916/// Event priority levels
917#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
918pub enum EventPriority {
919    Low,
920    Medium,
921    High,
922    Critical,
923}
924
925impl EventCategory {
926    /// Get all available categories
927    pub fn all() -> Vec<EventCategory> {
928        vec![
929            EventCategory::Data,
930            EventCategory::Graph,
931            EventCategory::Transaction,
932            EventCategory::Schema,
933            EventCategory::Index,
934            EventCategory::Shape,
935            EventCategory::Query,
936        ]
937    }
938
939    /// Get human-readable description
940    pub fn description(&self) -> &'static str {
941        match self {
942            EventCategory::Data => "Triple and quad data operations",
943            EventCategory::Graph => "Named graph management operations",
944            EventCategory::Transaction => "Transaction control operations",
945            EventCategory::Schema => "Schema and ontology changes",
946            EventCategory::Index => "Index management operations",
947            EventCategory::Shape => "SHACL shape definition and validation",
948            EventCategory::Query => "SPARQL query and update operations",
949        }
950    }
951}