ggen_core/
ontology_pack.rs

1//! Ontology Pack Metadata and Core Data Structures
2//!
3//! Extension of GpackMetadata for ontology-specific packs. Ontology packs are
4//! specialized template packs that focus on code generation from RDF/OWL ontologies.
5//!
6//! # Example
7//!
8//! ```rust,no_run
9//! use ggen_core::ontology_pack::{OntologyPackMetadata, OntologyConfig, OntologyDefinition};
10//!
11//! let pack_metadata = OntologyPackMetadata {
12//!     base: Default::default(),
13//!     ontology: OntologyConfig {
14//!         ontologies: vec![
15//!             OntologyDefinition {
16//!                 id: "schema.org".to_string(),
17//!                 name: "Schema.org".to_string(),
18//!                 version: "15.0".to_string(),
19//!                 namespace: "https://schema.org/".to_string(),
20//!                 file_path: "ontologies/schema-org.ttl".to_string(),
21//!                 format: OntologyFormat::Turtle,
22//!                 description: "Schema.org vocabulary".to_string(),
23//!                 spec_url: Some("https://schema.org".to_string()),
24//!                 classes_count: 792,
25//!                 properties_count: 1453,
26//!             }
27//!         ],
28//!         ..Default::default()
29//!     },
30//! };
31//! ```
32
33use serde::{Deserialize, Serialize};
34use std::collections::BTreeMap;
35
36/// Ontology pack metadata - extends GpackMetadata with ontology-specific fields
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct OntologyPackMetadata {
39    /// Base gpack metadata (id, name, version, description, etc.)
40    #[serde(flatten)]
41    pub base: crate::gpack::GpackMetadata,
42
43    /// Ontology-specific configuration
44    #[serde(default)]
45    pub ontology: OntologyConfig,
46}
47
48/// Ontology-specific configuration
49#[derive(Debug, Clone, Serialize, Deserialize, Default)]
50pub struct OntologyConfig {
51    /// Ontologies included in this pack
52    #[serde(default)]
53    pub ontologies: Vec<OntologyDefinition>,
54
55    /// Default namespace for generated code
56    pub default_namespace: Option<String>,
57
58    /// Code generation targets supported by this pack
59    #[serde(default)]
60    pub targets: Vec<CodeGenTarget>,
61
62    /// Template organization (language-specific paths)
63    #[serde(default)]
64    pub template_paths: BTreeMap<String, String>,
65
66    /// Ontology-specific prefixes
67    #[serde(default)]
68    pub prefixes: BTreeMap<String, String>,
69}
70
71/// An ontology definition (SCHEMA.ORG, FOAF, etc.)
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct OntologyDefinition {
74    /// Ontology identifier (e.g., "schema.org", "foaf", "dublincore")
75    pub id: String,
76
77    /// Human-readable name
78    pub name: String,
79
80    /// Ontology version
81    pub version: String,
82
83    /// Namespace URI
84    pub namespace: String,
85
86    /// Path to ontology file within pack (TTL, RDF/XML, etc.)
87    pub file_path: String,
88
89    /// Format (turtle, rdfxml, ntriples, jsonld)
90    pub format: OntologyFormat,
91
92    /// Description
93    pub description: String,
94
95    /// Official specification URL
96    pub spec_url: Option<String>,
97
98    /// Classes count (populated after extraction)
99    #[serde(default)]
100    pub classes_count: usize,
101
102    /// Properties count (populated after extraction)
103    #[serde(default)]
104    pub properties_count: usize,
105}
106
107/// Ontology file format
108#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
109#[serde(rename_all = "lowercase")]
110pub enum OntologyFormat {
111    /// Turtle format (.ttl)
112    Turtle,
113    /// RDF/XML format (.rdf, .xml)
114    RdfXml,
115    /// N-Triples format (.nt)
116    NTriples,
117    /// JSON-LD format (.jsonld)
118    JsonLd,
119}
120
121impl OntologyFormat {
122    /// Get file extension for this format
123    pub fn extension(&self) -> &str {
124        match self {
125            OntologyFormat::Turtle => "ttl",
126            OntologyFormat::RdfXml => "rdf",
127            OntologyFormat::NTriples => "nt",
128            OntologyFormat::JsonLd => "jsonld",
129        }
130    }
131}
132
133/// Code generation target (language + features)
134#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct CodeGenTarget {
136    /// Target language (typescript, rust, python, etc.)
137    pub language: String,
138
139    /// Features enabled for this target
140    #[serde(default)]
141    pub features: Vec<String>, // ["zod", "utilities", "graphql", etc.]
142
143    /// Template path for this target (relative to pack root)
144    pub template_path: String,
145
146    /// Output file pattern (e.g., "{class_name}.ts", "types.ts")
147    pub output_pattern: String,
148}
149
150/// Extracted ontology schema (intermediate representation)
151#[derive(Debug, Clone, Serialize, Deserialize, Default)]
152pub struct OntologySchema {
153    /// Schema namespace
154    pub namespace: String,
155
156    /// Classes extracted from ontology
157    #[serde(default)]
158    pub classes: Vec<OntologyClass>,
159
160    /// Properties extracted from ontology
161    #[serde(default)]
162    pub properties: Vec<OntologyProperty>,
163
164    /// Relationships between classes
165    #[serde(default)]
166    pub relationships: Vec<OntologyRelationship>,
167
168    /// Prefixes used in ontology
169    #[serde(default)]
170    pub prefixes: BTreeMap<String, String>,
171}
172
173/// Ontology class
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct OntologyClass {
176    /// Class URI
177    pub uri: String,
178
179    /// Class name (extracted from URI)
180    pub name: String,
181
182    /// Label (rdfs:label)
183    pub label: Option<String>,
184
185    /// Comment (rdfs:comment)
186    pub comment: Option<String>,
187
188    /// Properties belonging to this class
189    #[serde(default)]
190    pub properties: Vec<String>, // URIs
191
192    /// Superclasses
193    #[serde(default)]
194    pub super_classes: Vec<String>,
195
196    /// Subclasses
197    #[serde(default)]
198    pub sub_classes: Vec<String>,
199}
200
201/// Ontology property
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct OntologyProperty {
204    /// Property URI
205    pub uri: String,
206
207    /// Property name
208    pub name: String,
209
210    /// Label
211    pub label: Option<String>,
212
213    /// Comment
214    pub comment: Option<String>,
215
216    /// Domain (class this property applies to)
217    pub domain: String,
218
219    /// Range (value type or target class)
220    pub range: PropertyRange,
221
222    /// Cardinality constraints
223    pub cardinality: Option<Cardinality>,
224
225    /// Is this a functional property (single value)?
226    #[serde(default)]
227    pub is_functional: bool,
228}
229
230/// Property range (value type)
231#[derive(Debug, Clone, Serialize, Deserialize)]
232#[serde(tag = "type", rename_all = "lowercase")]
233pub enum PropertyRange {
234    /// Primitive type (string, integer, boolean, etc.)
235    Datatype {
236        /// XSD datatype (xsd:string, xsd:integer, etc.)
237        datatype: String,
238    },
239
240    /// Reference to another class
241    Reference {
242        /// Class URI
243        class_uri: String,
244    },
245
246    /// Array of values
247    Array {
248        /// Item type
249        item_type: Box<PropertyRange>,
250    },
251}
252
253/// Cardinality constraint
254#[derive(Debug, Clone, Serialize, Deserialize)]
255pub struct Cardinality {
256    /// Minimum occurrences (0 = optional, 1 = required)
257    pub min: Option<usize>,
258
259    /// Maximum occurrences (None = unbounded)
260    pub max: Option<usize>,
261}
262
263/// Relationship between classes
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct OntologyRelationship {
266    /// Source class URI
267    pub from: String,
268
269    /// Target class URI
270    pub to: String,
271
272    /// Property URI that defines this relationship
273    pub via_property: String,
274
275    /// Relationship type
276    pub relationship_type: RelationshipType,
277}
278
279/// Type of relationship between classes
280#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
281#[serde(rename_all = "lowercase")]
282pub enum RelationshipType {
283    /// rdfs:subClassOf inheritance
284    Inheritance,
285    /// Composition (part-of relationship)
286    Composition,
287    /// General association
288    Association,
289}
290
291#[cfg(test)]
292mod tests {
293    use super::*;
294
295    #[test]
296    fn test_ontology_format_extension() {
297        assert_eq!(OntologyFormat::Turtle.extension(), "ttl");
298        assert_eq!(OntologyFormat::RdfXml.extension(), "rdf");
299        assert_eq!(OntologyFormat::NTriples.extension(), "nt");
300        assert_eq!(OntologyFormat::JsonLd.extension(), "jsonld");
301    }
302
303    #[test]
304    fn test_ontology_class_serialization() {
305        let class = OntologyClass {
306            uri: "https://schema.org/Product".to_string(),
307            name: "Product".to_string(),
308            label: Some("Product".to_string()),
309            comment: Some("A manufactured product".to_string()),
310            properties: vec!["https://schema.org/name".to_string()],
311            super_classes: vec![],
312            sub_classes: vec![],
313        };
314
315        let json = serde_json::to_string(&class).unwrap();
316        let deserialized: OntologyClass = serde_json::from_str(&json).unwrap();
317
318        assert_eq!(deserialized.name, "Product");
319        assert_eq!(deserialized.properties.len(), 1);
320    }
321}