termivar_scanner/knowledge/
store.rs1use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
4
5use termivar_core::{
6 ConceptId, Ontology, OntologyAxiom, OntologyConcept, OntologyError, OntologyRelationType,
7 OntologyWrite, RelationTypeId,
8};
9
10use crate::knowledge::{
11 bump_ontology_revision, KnowledgeAuthority, KnowledgeBaseStats, KnowledgeState,
12};
13
14#[derive(Debug, Clone, Default)]
54pub struct KnowledgeBase {
55 pub(super) authority: KnowledgeAuthority,
56 state: Arc<RwLock<KnowledgeState>>,
57}
58
59impl KnowledgeBase {
60 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn register_concept(
67 &self,
68 concept: OntologyConcept,
69 ) -> Result<OntologyWrite, OntologyError> {
70 let mut state = self.write_state();
71 let write = state.ontology.add_concept(concept)?;
72 if write == OntologyWrite::Inserted {
73 bump_ontology_revision(&mut state);
74 }
75 Ok(write)
76 }
77
78 pub fn register_relation_type(
80 &self,
81 relation_type: OntologyRelationType,
82 ) -> Result<OntologyWrite, OntologyError> {
83 let mut state = self.write_state();
84 let write = state.ontology.add_relation_type(relation_type)?;
85 if write == OntologyWrite::Inserted {
86 bump_ontology_revision(&mut state);
87 }
88 Ok(write)
89 }
90
91 pub fn register_axiom(&self, axiom: OntologyAxiom) -> Result<OntologyWrite, OntologyError> {
93 let mut state = self.write_state();
94 let write = state.ontology.add_axiom(axiom)?;
95 if write == OntologyWrite::Inserted {
96 bump_ontology_revision(&mut state);
97 }
98 Ok(write)
99 }
100
101 pub(crate) fn install_ontology_definitions(
102 &self,
103 concepts: &[OntologyConcept],
104 axioms: &[OntologyAxiom],
105 ) -> Result<(usize, usize), OntologyError> {
106 let mut state = self.write_state();
107 let mut prospective = state.ontology.clone();
108 let mut concepts_inserted = 0;
109 let mut axioms_inserted = 0;
110
111 for concept in concepts {
112 concepts_inserted += usize::from(matches!(
113 prospective.add_concept(concept.clone())?,
114 OntologyWrite::Inserted
115 ));
116 }
117 for axiom in axioms {
118 axioms_inserted += usize::from(matches!(
119 prospective.add_axiom(axiom.clone())?,
120 OntologyWrite::Inserted
121 ));
122 }
123
124 state.ontology = prospective;
125 if concepts_inserted != 0 || axioms_inserted != 0 {
126 bump_ontology_revision(&mut state);
127 }
128 Ok((concepts_inserted, axioms_inserted))
129 }
130
131 pub fn ontology_snapshot(&self) -> Ontology {
133 self.read_state().ontology.clone()
134 }
135
136 pub fn ontology_is_related(
138 &self,
139 subject: &ConceptId,
140 relation: &RelationTypeId,
141 object: &ConceptId,
142 ) -> Result<bool, OntologyError> {
143 self.read_state()
144 .ontology
145 .is_related(subject, relation, object)
146 }
147
148 pub fn ontology_is_a(
150 &self,
151 child: &ConceptId,
152 ancestor: &ConceptId,
153 ) -> Result<bool, OntologyError> {
154 self.read_state().ontology.is_a(child, ancestor)
155 }
156
157 pub fn stats(&self) -> KnowledgeBaseStats {
159 let state = self.read_state();
160 KnowledgeBaseStats {
161 evidence: state.evidence.len(),
162 facts: state.facts.len(),
163 hypotheses: state.hypotheses.len(),
164 entities: state.entities.len(),
165 relations: state.relations.len(),
166 ontology: state.ontology.stats(),
167 }
168 }
169
170 pub(super) fn read_state(&self) -> RwLockReadGuard<'_, KnowledgeState> {
171 self.state
172 .read()
173 .unwrap_or_else(std::sync::PoisonError::into_inner)
174 }
175
176 pub(super) fn write_state(&self) -> RwLockWriteGuard<'_, KnowledgeState> {
177 self.state
178 .write()
179 .unwrap_or_else(std::sync::PoisonError::into_inner)
180 }
181}