1use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11
12#[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 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#[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#[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
171pub 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}