Skip to content

Commit

Permalink
feat: split ocafile validation and building logic
Browse files Browse the repository at this point in the history
  • Loading branch information
edytapawlak committed Mar 29, 2024
1 parent 857a01d commit d44215e
Showing 1 changed file with 109 additions and 87 deletions.
196 changes: 109 additions & 87 deletions oca/src/facade/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ use crate::repositories::{
#[cfg(feature = "local-references")]
use log::debug;
use oca_ast::ast::{OCAAst, ObjectKind, RefValue, ReferenceAttrType};
use oca_bundle::build::OCABuild;
use oca_bundle::build::{OCABuild, OCABuildStep};
use oca_bundle::state::oca::OCABundle;
use oca_bundle::Encode;
use oca_dag::build_core_db_model;

use std::borrow::Borrow;

#[derive(thiserror::Error, Debug, serde::Serialize)]
#[serde(untagged)]
pub enum Error {
Expand Down Expand Up @@ -62,6 +60,63 @@ impl References for Box<dyn DataStorage> {
}

impl Facade {
#[cfg(not(feature = "local-references"))]
pub fn validate_ocafile(&self, ocafile: String) -> Result<OCABuild, Vec<ValidationError>> {
let (base, oca_ast) = Self::parse_and_check_base(self.storage(), ocafile)?;
oca_bundle::build::from_ast(base, &oca_ast).map_err(|e| {
e.iter()
.map(|e| ValidationError::OCABundleBuild(e.clone()))
.collect::<Vec<_>>()
})
}

/// Validate ocafile using external references for dereferencing `refn`. It
/// won't update facade internal database with `refn`-> `said` mapping, so `refn`
/// can't be dereferenced in ocafiles processed later.
#[cfg(feature = "local-references")]
pub fn validate_ocafile_with_external_references<R: References>(
&self,
ocafile: String,
references: &mut R,
) -> Result<OCABuild, Vec<ValidationError>> {
let (base, oca_ast) = Self::parse_and_check_base(self.storage(), ocafile)?;
Self::oca_ast_to_oca_build_with_references(base, oca_ast, references)
}

/// Validate ocafile using internal references for dereferencing `refn`.
/// Mapping between `refn` -> `said` is saved in facades database, so it can
/// be dereferenced in other ocafiles later.
#[cfg(feature = "local-references")]
pub fn validate_ocafile(&mut self, ocafile: String) -> Result<OCABuild, Vec<ValidationError>> {
let (base, oca_ast) = Self::parse_and_check_base(self.storage(), ocafile)?;
Self::oca_ast_to_oca_build_with_references(base, oca_ast, &mut self.db)
}

pub fn build(&mut self, oca_build: &OCABuild) -> Result<OCABundle, Vec<Error>> {
self.build_cache(&oca_build.oca_bundle);

self.build_meta(&oca_build.oca_bundle);

oca_build
.steps
.iter()
.for_each(|step| self.build_step(step));

let _ = self.add_relations(oca_build.oca_bundle.clone());

self.build_models(&oca_build);

Ok(oca_build.oca_bundle.clone())
}

pub fn build_from_ocafile(&mut self, ocafile: String) -> Result<OCABundle, Vec<Error>> {
let oca_build = self
.validate_ocafile(ocafile)
.map_err(|errs| vec![Error::ValidationError(errs)])?;

self.build(&oca_build)
}

fn parse_and_check_base(
storage: &dyn DataStorage,
ocafile: String,
Expand Down Expand Up @@ -147,61 +202,30 @@ impl Facade {
Ok(oca_build)
}

#[cfg(feature = "local-references")]
pub fn validate_ocafile<R: References>(
storage: &dyn DataStorage,
ocafile: String,
references: &mut R,
) -> Result<OCABuild, Vec<ValidationError>> {
let (base, oca_ast) = Self::parse_and_check_base(storage, ocafile)?;
Self::oca_ast_to_oca_build_with_references(base, oca_ast, references)
}

#[cfg(not(feature = "local-references"))]
pub fn validate_ocafile(
storage: &dyn DataStorage,
ocafile: String,
) -> Result<OCABuild, Vec<ValidationError>> {
let (base, oca_ast) = Self::parse_and_check_base(storage, ocafile)?;
oca_bundle::build::from_ast(base, &oca_ast).map_err(|e| {
e.iter()
.map(|e| ValidationError::OCABundleBuild(e.clone()))
.collect::<Vec<_>>()
})
}

pub fn build_from_ocafile(&mut self, ocafile: String) -> Result<OCABundle, Vec<Error>> {
let oca_build = Self::validate_ocafile(
self.db_cache.borrow(),
ocafile,
#[cfg(feature = "local-references")]
&mut self.db,
)
.map_err(|errs| vec![Error::ValidationError(errs)])?;

fn build_cache(&self, oca_bundle: &OCABundle) {
let oca_bundle_cache_repo = OCABundleCacheRepo::new(self.connection());
let oca_bundle_cache_record = OCABundleCacheRecord::new(&oca_build.oca_bundle);
let oca_bundle_cache_record = OCABundleCacheRecord::new(&oca_bundle);
oca_bundle_cache_repo.insert(oca_bundle_cache_record);

let capture_base_cache_repo = CaptureBaseCacheRepo::new(self.connection());
let capture_base_cache_record =
CaptureBaseCacheRecord::new(&oca_build.oca_bundle.capture_base);
let capture_base_cache_record = CaptureBaseCacheRecord::new(&oca_bundle.capture_base);
capture_base_cache_repo.insert(capture_base_cache_record);
}

let meta_overlays = oca_build
.oca_bundle
fn build_meta(&self, oca_bundle: &OCABundle) {
let meta_overlays = oca_bundle
.overlays
.iter()
.filter_map(|x| {
x.as_any()
.downcast_ref::<oca_bundle::state::oca::overlay::Meta>()
})
.collect::<Vec<_>>();
if !meta_overlays.is_empty() {
if meta_overlays.is_empty() {
let oca_bundle_fts_repo = OCABundleFTSRepo::new(self.connection());
for meta_overlay in meta_overlays {
let oca_bundle_fts_record = OCABundleFTSRecord::new(
oca_build.oca_bundle.said.clone().unwrap().to_string(),
oca_bundle.said.clone().unwrap().to_string(),
meta_overlay
.attr_pairs
.get(&"name".to_string())
Expand All @@ -218,59 +242,59 @@ impl Facade {
oca_bundle_fts_repo.insert(oca_bundle_fts_record);
}
}
}

oca_build.steps.iter().for_each(|step| {
let mut input: Vec<u8> = vec![];
match &step.parent_said {
Some(said) => {
input.push(said.to_string().as_bytes().len().try_into().unwrap());
input.extend(said.to_string().as_bytes());
}
None => {
input.push(0);
}
fn build_step(&mut self, step: &OCABuildStep) {
let mut input: Vec<u8> = vec![];
match &step.parent_said {
Some(said) => {
input.push(said.to_string().as_bytes().len().try_into().unwrap());
input.extend(said.to_string().as_bytes());
}
None => {
input.push(0);
}
}

let command_str = serde_json::to_string(&step.command).unwrap();
input.extend(command_str.as_bytes());
let result_bundle = step.result.clone();
self.db
.insert(
Namespace::OCA,
&format!("oca.{}.operation", result_bundle.said.clone().unwrap()),
&input,
)
.unwrap();

self.db_cache
.insert(
Namespace::OCABundlesJSON,
&result_bundle.said.clone().unwrap().to_string(),
&result_bundle.encode().unwrap(),
)
.unwrap();
let command_str = serde_json::to_string(&step.command).unwrap();
input.extend(command_str.as_bytes());
let result_bundle = step.result.clone();
self.db
.insert(
Namespace::OCA,
&format!("oca.{}.operation", result_bundle.said.clone().unwrap()),
&input,
)
.unwrap();

self.db_cache
.insert(
Namespace::OCABundlesJSON,
&result_bundle.said.clone().unwrap().to_string(),
&result_bundle.encode().unwrap(),
)
.unwrap();
self.db_cache
.insert(
Namespace::OCAObjectsJSON,
&result_bundle.capture_base.said.clone().unwrap().to_string(),
&serde_json::to_string(&result_bundle.capture_base)
.unwrap()
.into_bytes(),
)
.unwrap();
result_bundle.overlays.iter().for_each(|overlay| {
self.db_cache
.insert(
Namespace::OCAObjectsJSON,
&result_bundle.capture_base.said.clone().unwrap().to_string(),
&serde_json::to_string(&result_bundle.capture_base)
.unwrap()
.into_bytes(),
&overlay.said().clone().unwrap().to_string(),
&serde_json::to_string(&overlay).unwrap().into_bytes(),
)
.unwrap();
result_bundle.overlays.iter().for_each(|overlay| {
self.db_cache
.insert(
Namespace::OCAObjectsJSON,
&overlay.said().clone().unwrap().to_string(),
&serde_json::to_string(&overlay).unwrap().into_bytes(),
)
.unwrap();
});
});
}

let _ = self.add_relations(oca_build.oca_bundle.clone());

fn build_models(&mut self, oca_build: &OCABuild) {
let result_models = build_core_db_model(&oca_build);
result_models.iter().for_each(|model| {
if let Some(command_model) = &model.command {
Expand Down Expand Up @@ -384,7 +408,5 @@ impl Facade {
.unwrap();
}
});

Ok(oca_build.oca_bundle)
}
}

0 comments on commit d44215e

Please sign in to comment.