1use anyhow::Result;
26use oxirs_core::model::{
27 BlankNode, GraphName, Literal as OxiLiteral, NamedNode, Quad, Subject, Term, Variable,
28};
29use oxirs_core::ConcreteStore;
30use std::sync::{Arc, Mutex};
31
32pub use oxirs_core::query::QueryResults;
34
35pub struct RdfStore {
39 store: Arc<Mutex<ConcreteStore>>,
40}
41
42impl std::fmt::Debug for RdfStore {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 f.debug_struct("RdfStore")
45 .field("store", &"Store { ... }")
46 .finish()
47 }
48}
49
50impl RdfStore {
51 pub fn new() -> Result<Self> {
52 Ok(Self {
53 store: Arc::new(Mutex::new(ConcreteStore::new()?)),
54 })
55 }
56
57 pub fn open<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
58 Ok(Self {
59 store: Arc::new(Mutex::new(ConcreteStore::open(path)?)),
60 })
61 }
62
63 pub fn query(&self, query: &str) -> Result<QueryResults> {
65 use oxirs_core::query::{QueryEngine, QueryResult};
66
67 let store = self
68 .store
69 .lock()
70 .map_err(|e| anyhow::anyhow!("Mutex lock error: {}", e))?;
71 let engine = QueryEngine::new();
72 let result = engine
73 .query(query, &*store)
74 .map_err(|e| anyhow::anyhow!("SPARQL query error: {}", e))?;
75
76 match result {
77 QueryResult::Select {
78 variables: _,
79 bindings,
80 } => {
81 let mut solutions = Vec::new();
82 for binding in bindings {
83 let mut solution = oxirs_core::query::Solution::new();
84 for (var_name, term) in binding {
85 if let Ok(var) = oxirs_core::model::Variable::new(&var_name) {
86 solution.bind(var, term);
87 }
88 }
89 solutions.push(solution);
90 }
91 Ok(QueryResults::Solutions(solutions))
92 }
93 QueryResult::Ask(result) => Ok(QueryResults::Boolean(result)),
94 QueryResult::Construct(triples) => {
95 Ok(QueryResults::Graph(triples))
97 }
98 }
99 }
100
101 pub fn triple_count(&self) -> Result<usize> {
103 let query = "SELECT (COUNT(*) as ?count) WHERE { ?s ?p ?o }";
104 if let QueryResults::Solutions(solutions) = self.query(query)? {
105 if let Some(solution) = solutions.first() {
106 let count_var = Variable::new("count")
107 .map_err(|e| anyhow::anyhow!("Failed to create count variable: {}", e))?;
108 if let Some(Term::Literal(lit)) = solution.get(&count_var) {
109 let count = lit.value().parse::<usize>().map_err(|e| {
110 anyhow::anyhow!("Failed to parse count value '{}': {}", lit.value(), e)
111 })?;
112 return Ok(count);
113 }
114 }
115 }
116 Ok(0)
117 }
118
119 pub fn get_subjects(&self, limit: Option<usize>) -> Result<Vec<String>> {
121 let limit_clause = match limit {
122 Some(l) => format!(" LIMIT {l}"),
123 None => String::new(),
124 };
125
126 let query = format!("SELECT DISTINCT ?s WHERE {{ ?s ?p ?o }}{limit_clause}");
127 let mut subjects = Vec::new();
128
129 let subject_var = Variable::new("s")
130 .map_err(|e| anyhow::anyhow!("Failed to create subject variable: {}", e))?;
131
132 if let QueryResults::Solutions(solutions) = self.query(&query)? {
133 for solution in &solutions {
134 if let Some(subject) = solution.get(&subject_var) {
135 subjects.push(subject.to_string());
136 }
137 }
138 }
139
140 Ok(subjects)
141 }
142
143 pub fn get_predicates(&self, limit: Option<usize>) -> Result<Vec<String>> {
145 let limit_clause = match limit {
146 Some(l) => format!(" LIMIT {l}"),
147 None => String::new(),
148 };
149
150 let query = format!("SELECT DISTINCT ?p WHERE {{ ?s ?p ?o }}{limit_clause}");
151 let mut predicates = Vec::new();
152
153 let predicate_var = Variable::new("p")
154 .map_err(|e| anyhow::anyhow!("Failed to create predicate variable: {}", e))?;
155
156 if let QueryResults::Solutions(solutions) = self.query(&query)? {
157 for solution in &solutions {
158 if let Some(predicate) = solution.get(&predicate_var) {
159 predicates.push(predicate.to_string());
160 }
161 }
162 }
163
164 Ok(predicates)
165 }
166
167 pub fn get_objects(&self, limit: Option<usize>) -> Result<Vec<(String, String)>> {
169 let limit_clause = match limit {
170 Some(l) => format!(" LIMIT {l}"),
171 None => String::new(),
172 };
173
174 let query = format!("SELECT DISTINCT ?o WHERE {{ ?s ?p ?o }}{limit_clause}");
175 let mut objects = Vec::new();
176
177 let object_var = Variable::new("o")
178 .map_err(|e| anyhow::anyhow!("Failed to create object variable: {}", e))?;
179
180 if let QueryResults::Solutions(solutions) = self.query(&query)? {
181 for solution in &solutions {
182 if let Some(object) = solution.get(&object_var) {
183 let object_type = match object {
184 Term::NamedNode(_) => "IRI".to_string(),
185 Term::BlankNode(_) => "BlankNode".to_string(),
186 Term::Literal(_) => "Literal".to_string(),
187 Term::Variable(_) => "Variable".to_string(),
188 Term::QuotedTriple(_) => "QuotedTriple".to_string(),
189 };
190 objects.push((object.to_string(), object_type));
191 }
192 }
193 }
194
195 Ok(objects)
196 }
197
198 pub fn insert_triple(&mut self, subject: &str, predicate: &str, object: &str) -> Result<()> {
200 let subject = if let Some(stripped) = subject.strip_prefix("_:") {
202 Subject::BlankNode(BlankNode::new(stripped)?)
203 } else {
204 Subject::NamedNode(NamedNode::new(subject)?)
205 };
206
207 let predicate = NamedNode::new(predicate)?;
208
209 let object = if object.starts_with("\"") && object.ends_with("\"") {
210 let literal_value = &object[1..object.len() - 1];
212 Term::Literal(OxiLiteral::new_simple_literal(literal_value))
213 } else if let Some(stripped) = object.strip_prefix("_:") {
214 Term::BlankNode(BlankNode::new(stripped)?)
216 } else {
217 Term::NamedNode(NamedNode::new(object)?)
219 };
220
221 let quad = Quad::new(subject, predicate, object, GraphName::DefaultGraph);
222 let store = self
223 .store
224 .lock()
225 .map_err(|e| anyhow::anyhow!("Mutex lock error: {}", e))?;
226 store.insert_quad(quad)?;
227 Ok(())
228 }
229
230 pub fn insert(&self, quad: &oxirs_core::model::Quad) -> Result<()> {
232 let store = self
233 .store
234 .lock()
235 .map_err(|e| anyhow::anyhow!("Mutex lock error: {}", e))?;
236 store.insert_quad(quad.clone())?;
237 Ok(())
238 }
239
240 pub fn load_file<P: AsRef<std::path::Path>>(&mut self, path: P, format: &str) -> Result<()> {
242 use oxirs_core::parser::{Parser, RdfFormat};
243 use std::fs;
244
245 let format = match format.to_lowercase().as_str() {
246 "turtle" | "ttl" => RdfFormat::Turtle,
247 "ntriples" | "nt" => RdfFormat::NTriples,
248 "rdfxml" | "rdf" => RdfFormat::RdfXml,
249 "jsonld" | "json" => RdfFormat::JsonLd,
250 _ => return Err(anyhow::anyhow!("Unsupported format: {}", format)),
251 };
252
253 let content = fs::read_to_string(path)?;
255
256 let parser = Parser::new(format);
258 let quads = parser.parse_str_to_quads(&content)?;
259
260 let store = self
262 .store
263 .lock()
264 .map_err(|e| anyhow::anyhow!("Mutex lock error: {}", e))?;
265 for quad in quads {
266 store.insert_quad(quad)?;
267 }
268
269 Ok(())
270 }
271}
272
273#[derive(Debug)]
275pub struct MockStore;
276
277impl MockStore {
278 pub fn new() -> Result<Self> {
279 Ok(Self)
280 }
281
282 pub fn open(_path: String) -> Result<Self> {
283 Ok(Self)
284 }
285}
286
287pub mod aggregation;
289pub mod ai;
290pub mod api_explorer;
291pub mod ast;
292pub mod auto_caching_strategies;
293pub mod custom_directives;
294pub mod custom_type_mappings;
295pub mod directive_registry;
296pub mod enhanced_errors;
297pub mod execution;
298pub mod federation;
299pub mod file_upload;
300pub mod graphiql_integration;
301pub mod historical_cost_estimator;
302pub mod horizontal_scaling;
303pub mod hybrid_optimizer;
304pub mod intelligent_federation_gateway;
305pub mod intelligent_query_cache;
306pub mod introspection;
307pub mod live_queries;
308pub mod mapping;
309pub mod ml_optimizer;
310pub mod optimizer;
311pub mod owl_enhanced_schema;
312pub mod pagination_filtering;
313pub mod parallel_field_resolver;
314pub mod parser;
315pub mod persisted_queries;
316pub mod playground_integration;
317pub mod quantum_optimizer;
318pub mod query_builder;
319pub mod query_debugger;
320pub mod query_prefetcher;
321pub mod rate_limiting;
322pub mod rdf_scalars;
323pub mod request_deduplication;
324pub mod resolvers;
325pub mod schema;
326pub mod schema_cache;
327pub mod schema_docs_generator;
328pub mod server;
329pub mod sse_subscriptions;
330pub mod subscriptions;
331pub mod types;
332pub mod validation;
333pub mod zero_trust_security;
334
335pub mod api_versioning;
337pub mod blue_green_deployment;
338pub mod canary_release;
339pub mod circuit_breaker;
340pub mod graphql_mesh;
341pub mod multi_region;
342pub mod performance_insights;
343pub mod schema_changelog;
344pub mod visual_schema_designer;
345
346pub mod content_security_policy;
348pub mod edge_caching;
349pub mod query_sanitization;
350pub mod response_streaming;
351pub mod webhook_support;
352
353pub mod cost_based_optimizer;
355pub mod incremental_execution;
356pub mod query_batching;
357pub mod query_plan_visualizer;
358pub mod query_result_streaming;
359
360pub mod graphql_span_attributes;
362pub mod performance_anomaly_detector;
363pub mod performance_heatmap;
364pub mod query_pattern_analyzer;
365pub mod trace_correlation;
366pub mod trace_sampling;
367pub mod trace_visualization;
368pub mod tracing_exporters;
369
370pub mod advanced_cache;
372pub mod advanced_security_system;
373pub mod ai_query_predictor;
374pub mod async_streaming;
375pub mod benchmarking;
376pub mod dataloader;
377pub mod neuromorphic_query_processor;
378pub mod performance;
379pub mod predictive_analytics;
380pub mod quantum_real_time_analytics;
381pub mod system_monitor;
382
383pub mod advanced_query_planner;
385pub mod advanced_subscriptions;
386pub mod ai_orchestration_engine;
387pub mod observability;
388
389pub mod production;
391
392pub mod cache;
394pub mod multitenancy;
395pub mod subscription;
396pub mod tenant;
398pub mod federation_v2;
400
401pub mod schema_registry;
403
404pub mod cursor_pagination;
406
407pub mod subscription_manager;
409
410pub mod batch_resolver;
412
413pub mod type_introspection;
415
416pub mod core;
418pub mod distributed_cache;
419pub mod docs;
420pub mod dynamic_query_planner;
421pub mod features;
422pub mod networking;
423pub mod rdf;
424
425pub mod field_resolver;
427
428pub mod query_complexity;
430
431pub mod error_formatter;
433
434pub mod directive_processor;
436
437pub mod pagination_handler;
439
440pub mod field_validator;
442
443pub mod enum_resolver;
445
446pub mod argument_coercer;
448
449pub mod juniper_schema;
451pub mod juniper_server; pub mod simple_juniper_server; pub use juniper_schema::{create_schema, GraphQLContext, Schema as JuniperSchema};
456pub use simple_juniper_server::{
457 start_graphql_server, start_graphql_server_with_config, GraphQLServerBuilder,
458 GraphQLServerConfig, JuniperGraphQLServer,
459};
460
461pub use intelligent_query_cache::{
463 IntelligentCacheConfig, IntelligentQueryCache, QueryPattern, QueryUsageStats,
464};
465
466pub use juniper_server::{
468 start_graphql_server as start_advanced_graphql_server,
469 start_graphql_server_with_config as start_advanced_graphql_server_with_config,
470 GraphQLServerBuilder as AdvancedGraphQLServerBuilder,
471 GraphQLServerConfig as AdvancedGraphQLServerConfig,
472 JuniperGraphQLServer as AdvancedJuniperGraphQLServer,
473};
474
475#[cfg(test)]
476mod tests;
477
478#[derive(Debug, Clone)]
480pub struct GraphQLConfig {
481 pub enable_introspection: bool,
482 pub enable_playground: bool,
483 pub max_query_depth: Option<usize>,
484 pub max_query_complexity: Option<usize>,
485 pub validation_config: validation::ValidationConfig,
486 pub enable_query_validation: bool,
487 pub distributed_cache_config: Option<distributed_cache::CacheConfig>,
488}
489
490impl Default for GraphQLConfig {
491 fn default() -> Self {
492 Self {
493 enable_introspection: true,
494 enable_playground: true,
495 max_query_depth: Some(10),
496 max_query_complexity: Some(1000),
497 validation_config: validation::ValidationConfig::default(),
498 enable_query_validation: true,
499 distributed_cache_config: None, }
501 }
502}
503
504pub struct GraphQLServer {
506 config: GraphQLConfig,
507 store: Arc<RdfStore>,
508 cache: Option<Arc<distributed_cache::GraphQLQueryCache>>,
509}
510
511impl GraphQLServer {
512 pub fn new(store: Arc<RdfStore>) -> Self {
513 Self {
514 config: GraphQLConfig::default(),
515 store,
516 cache: None,
517 }
518 }
519
520 pub fn new_with_mock(_store: Arc<MockStore>) -> Result<Self> {
521 let rdf_store = Arc::new(
523 RdfStore::new()
524 .map_err(|e| anyhow::anyhow!("Failed to create RDF store for mock: {}", e))?,
525 );
526 Ok(Self {
527 config: GraphQLConfig::default(),
528 store: rdf_store,
529 cache: None,
530 })
531 }
532
533 pub fn with_config(mut self, config: GraphQLConfig) -> Self {
534 self.config = config;
535 self
536 }
537
538 pub async fn with_distributed_cache(
540 mut self,
541 cache_config: distributed_cache::CacheConfig,
542 ) -> Result<Self> {
543 let cache = Arc::new(distributed_cache::GraphQLQueryCache::new(cache_config).await?);
544 self.cache = Some(cache);
545 Ok(self)
546 }
547
548 pub async fn get_cache_stats(&self) -> Option<distributed_cache::CacheStats> {
550 if let Some(cache) = &self.cache {
551 cache.get_stats().await.ok()
552 } else {
553 None
554 }
555 }
556
557 pub async fn start(&self, addr: &str) -> Result<()> {
558 tracing::info!("Starting GraphQL server on {}", addr);
559
560 let mut schema = types::Schema::new();
562
563 let mut query_type = types::ObjectType::new("Query".to_string())
565 .with_description("The root query type for RDF data access".to_string())
566 .with_field(
567 "hello".to_string(),
568 types::FieldType::new(
569 "hello".to_string(),
570 types::GraphQLType::Scalar(types::BuiltinScalars::string()),
571 )
572 .with_description("A simple greeting message".to_string()),
573 )
574 .with_field(
575 "version".to_string(),
576 types::FieldType::new(
577 "version".to_string(),
578 types::GraphQLType::Scalar(types::BuiltinScalars::string()),
579 )
580 .with_description("OxiRS GraphQL version".to_string()),
581 )
582 .with_field(
583 "triples".to_string(),
584 types::FieldType::new(
585 "triples".to_string(),
586 types::GraphQLType::Scalar(types::BuiltinScalars::int()),
587 )
588 .with_description("Count of triples in the store".to_string()),
589 )
590 .with_field(
591 "subjects".to_string(),
592 types::FieldType::new(
593 "subjects".to_string(),
594 types::GraphQLType::List(Box::new(types::GraphQLType::Scalar(
595 types::BuiltinScalars::string(),
596 ))),
597 )
598 .with_description("List of subject IRIs".to_string())
599 .with_argument(
600 "limit".to_string(),
601 types::ArgumentType::new(
602 "limit".to_string(),
603 types::GraphQLType::Scalar(types::BuiltinScalars::int()),
604 )
605 .with_default_value(ast::Value::IntValue(10))
606 .with_description("Maximum number of subjects to return".to_string()),
607 ),
608 )
609 .with_field(
610 "predicates".to_string(),
611 types::FieldType::new(
612 "predicates".to_string(),
613 types::GraphQLType::List(Box::new(types::GraphQLType::Scalar(
614 types::BuiltinScalars::string(),
615 ))),
616 )
617 .with_description("List of predicate IRIs".to_string())
618 .with_argument(
619 "limit".to_string(),
620 types::ArgumentType::new(
621 "limit".to_string(),
622 types::GraphQLType::Scalar(types::BuiltinScalars::int()),
623 )
624 .with_default_value(ast::Value::IntValue(10))
625 .with_description("Maximum number of predicates to return".to_string()),
626 ),
627 )
628 .with_field(
629 "objects".to_string(),
630 types::FieldType::new(
631 "objects".to_string(),
632 types::GraphQLType::List(Box::new(types::GraphQLType::Scalar(
633 types::BuiltinScalars::string(),
634 ))),
635 )
636 .with_description("List of objects".to_string())
637 .with_argument(
638 "limit".to_string(),
639 types::ArgumentType::new(
640 "limit".to_string(),
641 types::GraphQLType::Scalar(types::BuiltinScalars::int()),
642 )
643 .with_default_value(ast::Value::IntValue(10))
644 .with_description("Maximum number of objects to return".to_string()),
645 ),
646 )
647 .with_field(
648 "sparql".to_string(),
649 types::FieldType::new(
650 "sparql".to_string(),
651 types::GraphQLType::Scalar(types::BuiltinScalars::string()),
652 )
653 .with_description("Execute a raw SPARQL query".to_string())
654 .with_argument(
655 "query".to_string(),
656 types::ArgumentType::new(
657 "query".to_string(),
658 types::GraphQLType::NonNull(Box::new(types::GraphQLType::Scalar(
659 types::BuiltinScalars::string(),
660 ))),
661 )
662 .with_description("The SPARQL query to execute".to_string()),
663 ),
664 );
665
666 if self.config.enable_introspection {
668 query_type = query_type
669 .with_field(
670 "__schema".to_string(),
671 types::FieldType::new(
672 "__schema".to_string(),
673 types::GraphQLType::NonNull(Box::new(types::GraphQLType::Scalar(
674 types::ScalarType {
675 name: "__Schema".to_string(),
676 description: Some(
677 "A GraphQL Schema defines the capabilities of a GraphQL server"
678 .to_string(),
679 ),
680 serialize: |_| Ok(ast::Value::NullValue),
681 parse_value: |_| Err(anyhow::anyhow!("Cannot parse __Schema")),
682 parse_literal: |_| Err(anyhow::anyhow!("Cannot parse __Schema")),
683 },
684 ))),
685 )
686 .with_description("Access the current type schema of this server".to_string()),
687 )
688 .with_field(
689 "__type".to_string(),
690 types::FieldType::new(
691 "__type".to_string(),
692 types::GraphQLType::Scalar(types::ScalarType {
693 name: "__Type".to_string(),
694 description: Some(
695 "A GraphQL Schema defines the capabilities of a GraphQL server"
696 .to_string(),
697 ),
698 serialize: |_| Ok(ast::Value::NullValue),
699 parse_value: |_| Err(anyhow::anyhow!("Cannot parse __Type")),
700 parse_literal: |_| Err(anyhow::anyhow!("Cannot parse __Type")),
701 }),
702 )
703 .with_description("Request the type information of a single type".to_string())
704 .with_argument(
705 "name".to_string(),
706 types::ArgumentType::new(
707 "name".to_string(),
708 types::GraphQLType::NonNull(Box::new(types::GraphQLType::Scalar(
709 types::BuiltinScalars::string(),
710 ))),
711 )
712 .with_description("The name of the type to introspect".to_string()),
713 ),
714 );
715 }
716
717 schema.add_type(types::GraphQLType::Object(query_type));
718 schema.set_query_type("Query".to_string());
719
720 let schema_clone = schema.clone();
722 let mut server = server::Server::new(schema.clone())
723 .with_playground(self.config.enable_playground)
724 .with_introspection(self.config.enable_introspection);
725
726 if self.config.enable_query_validation {
728 server =
729 server.with_validation(self.config.validation_config.clone(), schema_clone.clone());
730 }
731
732 let query_resolvers = resolvers::QueryResolvers::new(Arc::clone(&self.store));
734 server.add_resolver("Query".to_string(), query_resolvers.rdf_resolver());
735
736 let introspection_resolver = Arc::new(introspection::IntrospectionResolver::new(Arc::new(
738 schema_clone,
739 )));
740 server.add_resolver("__Schema".to_string(), introspection_resolver.clone());
741 server.add_resolver("__Type".to_string(), introspection_resolver.clone());
742 server.add_resolver("__Field".to_string(), introspection_resolver.clone());
743 server.add_resolver("__InputValue".to_string(), introspection_resolver.clone());
744 server.add_resolver("__EnumValue".to_string(), introspection_resolver.clone());
745 server.add_resolver("__Directive".to_string(), introspection_resolver);
746
747 let socket_addr: std::net::SocketAddr = addr
749 .parse()
750 .map_err(|e| anyhow::anyhow!("Invalid address '{}': {}", addr, e))?;
751
752 server.start(socket_addr).await
753 }
754}
755
756