introduce the concept of a hierarchy root

feat/vaults
Tomáš Mládek 2021-08-18 11:06:39 +02:00
parent 2944ce3d81
commit 96d0ec3be7
1 changed files with 68 additions and 75 deletions

View File

@ -12,10 +12,18 @@ use crate::database::constants::{
HIER_ADDR, HIER_HAS_ATTR, HIER_INVARIANT, HIER_LABEL_ATTR, IS_OF_TYPE_ATTR, TYPE_ADDR,
TYPE_HAS_ATTR, TYPE_ID_ATTR,
};
use crate::database::entry::{Entry, EntryValue};
use crate::database::entry::{Entry, EntryValue, InvariantEntry};
use crate::database::lang::{EntryQuery, Query, QueryComponent, QueryPart};
use crate::database::{bulk_retrieve_objects, insert_entry, query, DbPool};
lazy_static! {
static ref HIER_ROOT_INVARIANT: InvariantEntry = InvariantEntry {
attribute: String::from(HIER_LABEL_ATTR),
value: EntryValue::Value(Value::from("/")),
};
static ref HIER_ROOT_INVARIANT_ADDR: Address = HIER_ROOT_INVARIANT.entity().unwrap();
}
#[derive(Debug, Clone, PartialEq)]
pub struct UNode(String);
@ -94,53 +102,49 @@ impl EntryList for Vec<Entry> {
}
}
pub fn list_roots<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Address>> {
let all_directories: Vec<Entry> = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Any,
attribute: QueryComponent::Exact(IS_OF_TYPE_ATTR.to_string()),
value: QueryComponent::Exact(EntryValue::Address(HIER_ADDR.clone())),
})),
)?;
let directories_with_parents: Vec<Address> = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Any,
attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
value: QueryComponent::Any,
})),
)?
.extract_addresses();
Ok(all_directories
.into_iter()
.filter(|entry| !directories_with_parents.contains(&entry.entity))
.map(|e| e.entity)
.collect())
}
// pub fn list_orphans<C: Connection<Backend = Sqlite>>(connection: &C) -> Result<Vec<Address>> {
// let all_directories: Vec<Entry> = query(
// connection,
// Query::SingleQuery(QueryPart::Matches(EntryQuery {
// entity: QueryComponent::Any,
// attribute: QueryComponent::Exact(IS_OF_TYPE_ATTR.to_string()),
// value: QueryComponent::Exact(EntryValue::Address(HIER_ADDR.clone())),
// })),
// )?;
//
// let directories_with_parents: Vec<Address> = query(
// connection,
// Query::SingleQuery(QueryPart::Matches(EntryQuery {
// entity: QueryComponent::Any,
// attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
// value: QueryComponent::Any,
// })),
// )?
// .extract_addresses();
//
// Ok(all_directories
// .into_iter()
// .filter(|entry| !directories_with_parents.contains(&entry.entity))
// .map(|e| e.entity)
// .collect())
// }
pub async fn list_node<C: Connection<Backend = Sqlite>>(
connection: &C,
path: &UPath,
) -> Result<Vec<Entry>> {
let entry_addresses = if path.0.is_empty() {
list_roots(connection)?
} else {
let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
let last = resolved_path.last().unwrap();
let resolved_path: Vec<Address> = resolve_path(connection, path, false)?;
let last = resolved_path.last().unwrap();
query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Exact(last.clone()),
attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
value: QueryComponent::Any,
})),
)?
.extract_addresses()
};
let entry_addresses = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Exact(last.clone()),
attribute: QueryComponent::Exact(HIER_HAS_ATTR.to_string()),
value: QueryComponent::Any,
})),
)?
.extract_addresses();
Ok(bulk_retrieve_objects(connection, entry_addresses)?
.into_iter()
@ -159,6 +163,8 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
None => trace!("FETCHING/CREATING /{:#}", directory),
}
let parent = parent.unwrap_or_else(|| HIER_ROOT_INVARIANT_ADDR.clone());
let matching_directories: Vec<Address> = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
@ -173,31 +179,20 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
.map(|e: Entry| e.entity)
.collect();
let valid_directories: Vec<Address> = match parent.clone() {
Some(address) => {
let parent_has: Vec<Address> = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Exact(address),
attribute: QueryComponent::Exact(String::from(HIER_HAS_ATTR)),
value: QueryComponent::Any,
})),
)?
.extract_addresses();
let parent_has: Vec<Address> = query(
connection,
Query::SingleQuery(QueryPart::Matches(EntryQuery {
entity: QueryComponent::Exact(parent.clone()),
attribute: QueryComponent::Exact(String::from(HIER_HAS_ATTR)),
value: QueryComponent::Any,
})),
)?
.extract_addresses();
matching_directories
.into_iter()
.filter(|a| parent_has.contains(a))
.collect()
}
None => {
let roots = list_roots(connection)?;
matching_directories
.into_iter()
.filter(|a| roots.contains(a))
.collect()
}
};
let valid_directories: Vec<Address> = matching_directories
.into_iter()
.filter(|a| parent_has.contains(a))
.collect();
match valid_directories.len() {
0 => {
@ -217,14 +212,12 @@ pub fn fetch_or_create_dir<C: Connection<Backend = Sqlite>>(
};
insert_entry(connection, directory_entry)?;
if let Some(parent_addr) = parent {
let has_entry = Entry {
entity: parent_addr,
attribute: String::from(HIER_HAS_ATTR),
value: EntryValue::Address(new_directory_address.clone()),
};
insert_entry(connection, has_entry)?;
}
let has_entry = Entry {
entity: parent,
attribute: String::from(HIER_HAS_ATTR),
value: EntryValue::Address(new_directory_address.clone()),
};
insert_entry(connection, has_entry)?;
Ok(new_directory_address)
} else {
@ -243,7 +236,7 @@ pub fn resolve_path<C: Connection<Backend = Sqlite>>(
path: &UPath,
create: bool,
) -> Result<Vec<Address>> {
let mut result: Vec<Address> = vec![];
let mut result: Vec<Address> = vec![HIER_ROOT_INVARIANT_ADDR.clone()];
let mut path_stack = path.0.to_vec();
path_stack.reverse();