#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Dataspace {
pub uri: String,
pub name: String,
pub created: Option<String>,
pub last_changed: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ObjectSummary {
pub uri: String,
pub uuid: String,
pub qualified_type: String,
pub content_type: String,
pub locator: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ObjectHeader {
pub summary: ObjectSummary,
pub title: Option<String>,
pub originator: Option<String>,
pub creation: Option<String>,
pub last_update: Option<String>,
pub format: Option<String>,
pub object_version: Option<String>,
pub schema_version: Option<String>,
}
impl ObjectHeader {
pub fn uri(&self) -> &str {
&self.summary.uri
}
pub fn display_name(&self) -> &str {
match self.title.as_deref() {
Some(title) if !title.trim().is_empty() => title,
_ => &self.summary.uuid,
}
}
pub fn titled(&self) -> String {
match self
.object_version
.as_deref()
.map(str::trim)
.filter(|version| !version.is_empty())
{
Some(version) => format!("{} (version {version})", self.display_name()),
None => self.display_name().to_string(),
}
}
pub fn label(&self) -> String {
match energyml_core::identity::ObjectId::from_qualified_type(
&self.summary.qualified_type,
&self.summary.uuid,
) {
Ok(mut id) => {
id.object_version = self.object_version.clone();
id.label(self.title.as_deref())
}
Err(_) => format!("{} - {}", self.summary.qualified_type, self.display_name()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Relationship {
pub id: String,
pub kind: String,
pub target: String,
pub external: bool,
}
impl Relationship {
pub fn short_kind(&self) -> &str {
self.kind.rsplit('/').next().unwrap_or(&self.kind)
}
pub fn is_external_resource(&self) -> bool {
self.external || self.short_kind() == "externalResource"
}
}
pub fn type_matches(qualified_type: &str, filter: &str) -> bool {
qualified_type.to_lowercase().contains(&filter.to_lowercase())
}
pub fn title_matches(title: &str, filter: &str) -> bool {
title.to_lowercase().contains(&filter.to_lowercase())
}
#[cfg(test)]
mod tests {
use super::*;
fn header(title: Option<&str>, version: Option<&str>) -> ObjectHeader {
ObjectHeader {
summary: ObjectSummary {
uri: "eml:///resqml22.BoundaryFeature(7f000000-0000-4000-8000-000000000001)".into(),
uuid: "7f000000-0000-4000-8000-000000000001".into(),
qualified_type: "resqml22.BoundaryFeature".into(),
content_type: String::new(),
locator: String::new(),
},
title: title.map(str::to_string),
originator: None,
creation: None,
last_update: None,
format: None,
object_version: version.map(str::to_string),
schema_version: None,
}
}
#[test]
fn a_view_shows_the_version_when_the_object_declares_one() {
let versioned = header(Some("Top Brent"), Some("2"));
assert_eq!(
versioned.label(),
"resqml22.BoundaryFeature - Top Brent (version 2)"
);
assert_eq!(versioned.titled(), "Top Brent (version 2)");
}
#[test]
fn no_version_a_blank_one_or_no_title_changes_nothing_but_what_is_missing() {
for none in [None, Some(""), Some(" ")] {
let plain = header(Some("Top Brent"), none);
assert_eq!(plain.label(), "resqml22.BoundaryFeature - Top Brent", "{none:?}");
assert_eq!(plain.titled(), "Top Brent", "{none:?}");
}
let untitled = header(None, Some("1"));
assert_eq!(
untitled.titled(),
"7f000000-0000-4000-8000-000000000001 (version 1)"
);
}
}