Skip to main content

genesis_schema/
lib.rs

1//! KNHK V2 Schema System - Pattern definitions and workflow schemas
2//!
3//! This crate provides:
4//! - OpenAPI specifications for REST/GRPC APIs
5//! - RDF ontology for semantic understanding
6//! - Pattern definitions for all 43 YAWL patterns
7//! - Workflow schema validation
8
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12/// OpenAPI v3.1 compliant API specification
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct OpenApiSpec {
15    pub openapi: String,
16    pub info: ApiInfo,
17    pub paths: HashMap<String, PathItem>,
18    pub components: Components,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ApiInfo {
23    pub title: String,
24    pub version: String,
25    pub description: Option<String>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct PathItem {
30    pub post: Option<Operation>,
31    pub get: Option<Operation>,
32    pub put: Option<Operation>,
33    pub delete: Option<Operation>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct Operation {
38    pub summary: String,
39    #[serde(rename = "operationId")]
40    pub operation_id: String,
41    pub parameters: Vec<Parameter>,
42    #[serde(rename = "requestBody")]
43    pub request_body: Option<RequestBody>,
44    pub responses: HashMap<String, Response>,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct Parameter {
49    pub name: String,
50    pub in_: String,
51    pub required: bool,
52    pub schema: SchemaRef,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct RequestBody {
57    pub required: bool,
58    pub content: HashMap<String, MediaType>,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct MediaType {
63    pub schema: SchemaRef,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct Response {
68    pub description: String,
69    pub content: Option<HashMap<String, MediaType>>,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73#[serde(untagged)]
74pub enum SchemaRef {
75    Ref {
76        #[serde(rename = "$ref")]
77        ref_: String,
78    },
79    Schema {
80        schema: Box<JsonSchema>,
81    },
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct JsonSchema {
86    #[serde(rename = "type")]
87    pub schema_type: String,
88    pub properties: Option<HashMap<String, Box<JsonSchema>>>,
89    pub required: Option<Vec<String>>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct Components {
94    pub schemas: HashMap<String, Box<JsonSchema>>,
95}
96
97impl OpenApiSpec {
98    pub fn new(title: String, version: String) -> Self {
99        Self {
100            openapi: "3.1.0".to_string(),
101            info: ApiInfo {
102                title,
103                version,
104                description: None,
105            },
106            paths: HashMap::new(),
107            components: Components {
108                schemas: HashMap::new(),
109            },
110        }
111    }
112
113    /// Add an endpoint to the API specification
114    pub fn add_endpoint(&mut self, path: String, method: String, operation: Operation) {
115        let path_item = self.paths.entry(path).or_insert(PathItem {
116            post: None,
117            get: None,
118            put: None,
119            delete: None,
120        });
121
122        match method.as_str() {
123            "POST" => path_item.post = Some(operation),
124            "GET" => path_item.get = Some(operation),
125            "PUT" => path_item.put = Some(operation),
126            "DELETE" => path_item.delete = Some(operation),
127            _ => {}
128        }
129    }
130}
131
132/// RDF/Turtle ontology for semantic integration
133#[derive(Debug, Clone)]
134pub struct RdfOntology {
135    pub namespace: String,
136    pub triples: Vec<(String, String, String)>,
137}
138
139impl RdfOntology {
140    pub fn new(namespace: String) -> Self {
141        Self {
142            namespace,
143            triples: Vec::new(),
144        }
145    }
146
147    pub fn add_triple(&mut self, subject: String, predicate: String, object: String) {
148        self.triples.push((subject, predicate, object));
149    }
150
151    pub fn to_turtle(&self) -> String {
152        let mut turtle = format!("@prefix : <{}> .\n\n", self.namespace);
153        for (subj, pred, obj) in &self.triples {
154            turtle.push_str(&format!("{}  {}  {} .\n", subj, pred, obj));
155        }
156        turtle
157    }
158}
159
160/// Pattern metadata supporting all 43 YAWL patterns
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct PatternMetadata {
163    pub id: u32,
164    pub name: String,
165    pub category: String,
166    pub description: String,
167    pub yawl_pattern_id: String,
168    pub is_control_flow: bool,
169}
170
171/// Registry of all 43 YAWL patterns
172pub struct PatternRegistry {
173    patterns: HashMap<u32, PatternMetadata>,
174}
175
176impl PatternRegistry {
177    pub fn new() -> Self {
178        Self {
179            patterns: HashMap::new(),
180        }
181    }
182
183    pub fn register(&mut self, pattern: PatternMetadata) {
184        self.patterns.insert(pattern.id, pattern);
185    }
186
187    pub fn get(&self, id: u32) -> Option<&PatternMetadata> {
188        self.patterns.get(&id)
189    }
190
191    pub fn list_all(&self) -> Vec<&PatternMetadata> {
192        self.patterns.values().collect()
193    }
194
195    pub fn list_by_category(&self, category: &str) -> Vec<&PatternMetadata> {
196        self.patterns
197            .values()
198            .filter(|p| p.category == category)
199            .collect()
200    }
201}
202
203impl Default for PatternRegistry {
204    fn default() -> Self {
205        Self::new()
206    }
207}
208
209#[cfg(test)]
210mod tests {
211    use super::*;
212
213    #[test]
214    fn test_openapi_spec_creation() {
215        let spec = OpenApiSpec::new("Test API".to_string(), "1.0.0".to_string());
216        assert_eq!(spec.info.title, "Test API");
217        assert_eq!(spec.openapi, "3.1.0");
218    }
219
220    #[test]
221    fn test_rdf_ontology() {
222        let mut onto = RdfOntology::new("http://example.org/knhk#".to_string());
223        onto.add_triple(
224            "Pattern".to_string(),
225            "rdf:type".to_string(),
226            "owl:Class".to_string(),
227        );
228        let turtle = onto.to_turtle();
229        assert!(turtle.contains("Pattern"));
230        assert!(turtle.contains("rdf:type"));
231    }
232
233    #[test]
234    fn test_pattern_registry() {
235        let mut registry = PatternRegistry::new();
236        let pattern = PatternMetadata {
237            id: 1,
238            name: "Sequence".to_string(),
239            category: "Basic".to_string(),
240            description: "Sequential execution of tasks".to_string(),
241            yawl_pattern_id: "WCP-1".to_string(),
242            is_control_flow: true,
243        };
244
245        registry.register(pattern);
246        assert!(registry.get(1).is_some());
247        assert_eq!(registry.list_all().len(), 1);
248    }
249}