From 1a04b9bea72c37b95d2a413ef863bf28f468aafb Mon Sep 17 00:00:00 2001 From: Laurin Weger Date: Wed, 1 Oct 2025 21:43:44 +0200 Subject: [PATCH] create_orm_from_triples --- ng-verifier/src/orm.rs | 107 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 12 deletions(-) diff --git a/ng-verifier/src/orm.rs b/ng-verifier/src/orm.rs index cfa5bc1..84bfb05 100644 --- a/ng-verifier/src/orm.rs +++ b/ng-verifier/src/orm.rs @@ -43,6 +43,7 @@ use ng_repo::errors::NgError; use ng_repo::errors::VerifierError; use ng_repo::log::*; use regex::Regex; +use serde::de::IntoDeserializer; use serde_json::json; use serde_json::Value; @@ -599,23 +600,105 @@ impl Verifier { shape: &OrmSchemaShape, triples: &Vec, ) -> Result { - let changes = self.apply_changes_from_triples(scope, schema, shape, triples, vec![]); + let changes = self.apply_changes_from_triples(scope, schema, shape, triples, &vec![]); - let root_changes = changes.get(shape.iri).unwrap().values(); + let root_changes = changes.get(&shape.iri).unwrap().values(); let valid_roots = root_changes.filter(|v| v.valid == OrmTrackedSubjectValidity::Valid); let mut return_vals: Value = Value::Array(vec![]); - for root_change in root_changes { - let new_val = json!({"id": root_change.subject_iri}); - for (pred_iri, pred_change) in root_change.predicates { - // Add the readable predicate name - let property_name = pred_change.tracked_predicate.schema.readablePredicate; - - // For basic values, add value. - // For arrays of basic values, add array. - // For single nested object, add object. - // For multiple nested objects, create object with iri keys. + let return_val_vec = return_vals.as_array_mut().unwrap(); + + fn create_value_from_change( + change: &OrmTrackedSubjectChange, + changes: &HashMap>>, + shape: &OrmSchemaShape, + schema: &OrmSchema, + ) -> Value { + let mut new_val = json!({"id": change.subject_iri}); + let new_val_map = new_val.as_object_mut().unwrap(); + for pred_schema in &shape.predicates { + let property_name = pred_schema.readablePredicate.clone(); + let is_multi = pred_schema.maxCardinality > 1; + let pred_change = change.predicates.get(&pred_schema.iri).unwrap(); + + if pred_schema + .dataTypes + .iter() + .any(|dt| dt.valType == OrmSchemaLiteralType::shape) + { + // Helper to create nested objects. + let get_nested_value = |object_iri: &String| { + let shape_iris: Vec = pred_schema + .dataTypes + .iter() + .flat_map(|dt| dt.shape.clone()) + .collect(); + + // Find subject_change for this subject. There exists at least one (shape, subject). + let nested_subject_change = shape_iris + .iter() + .find_map(|shape_iri| { + changes + .get(shape_iri) + .and_then(|subject_changes| subject_changes.get(object_iri)) + }) + .unwrap(); + + // Recurse + create_value_from_change( + nested_subject_change, + changes, + schema.get(&nested_subject_change.subject_iri).unwrap(), + schema, + ) + }; + + if is_multi { + // Add each value to a new object (predicate being object IRIs). + let mut nested_objects = json!({"id": change.subject_iri}); + let nested_objects_map = nested_objects.as_object_mut().unwrap(); + + for new_val in &pred_change.values_added { + if let BasicType::Str(object_iri) = new_val { + new_val_map + .insert(object_iri.clone(), get_nested_value(&object_iri)); + } + } + } else { + if let Some(BasicType::Str(object_iri)) = pred_change.values_added.get(0) { + new_val_map.insert(property_name.clone(), get_nested_value(object_iri)); + } + } + } else { + if is_multi { + // Add values as array. + new_val_map.insert( + property_name, + Value::Array( + pred_change.values_added.iter().map(|v| json!(v)).collect(), + ), + ); + } else { + // Add value as primitive, if present. + if let Some(val) = pred_change.values_added.get(0) { + new_val_map.insert( + property_name, + match val { + BasicType::Bool(b) => json!(b), + BasicType::Num(n) => json!(n), + BasicType::Str(s) => json!(s), + }, + ); + } + } + } } + return new_val; + } + + for root_change in valid_roots { + let new_val = create_value_from_change(root_change, &changes, shape, schema); + return_val_vec.push(new_val); } return Ok(return_vals);