use ifc_model::guid::Guid;
use ifc_model::{Entity, EntityId, Transaction, Value};
use super::{invalid, optional_text, SpatialAuthoringResult};
const EXTERNAL_KIND: &[&str] = &[
"EXTERNAL",
"EXTERNAL_EARTH",
"EXTERNAL_FIRE",
"EXTERNAL_WATER",
"USERDEFINED",
"NOTDEFINED",
];
#[derive(Debug, Clone, Copy, Default)]
pub struct ExternalSpatialDraft<'a> {
pub name: Option<&'a str>,
pub description: Option<&'a str>,
pub object_type: Option<&'a str>,
pub placement: Option<EntityId>,
pub representation: Option<EntityId>,
pub long_name: Option<&'a str>,
pub predefined_type: Option<&'a str>,
}
pub fn create_external_spatial_element(
tx: &mut Transaction,
global_id: &str,
draft: ExternalSpatialDraft<'_>,
) -> SpatialAuthoringResult<EntityId> {
const ENTITY: &str = "IFCEXTERNALSPATIALELEMENT";
if Guid::parse(global_id).is_none() {
return Err(invalid(ENTITY, "GlobalId", global_id));
}
if let Some(token) = draft.predefined_type {
if !EXTERNAL_KIND.contains(&token) {
return Err(invalid(ENTITY, "PredefinedType", token));
}
if token == "USERDEFINED"
&& draft
.object_type
.is_none_or(|value| value.trim().is_empty())
{
return Err(invalid(ENTITY, "ObjectType", "required by USERDEFINED"));
}
}
let mut attributes = vec![Value::Null; 9];
attributes[0] = Value::Text(global_id.into());
attributes[2] = optional_text(draft.name);
attributes[3] = optional_text(draft.description);
attributes[4] = optional_text(draft.object_type);
attributes[5] = draft.placement.map_or(Value::Null, Value::Ref);
attributes[6] = draft.representation.map_or(Value::Null, Value::Ref);
attributes[7] = optional_text(draft.long_name);
attributes[8] = draft
.predefined_type
.map_or(Value::Null, |t| Value::Enum(t.into()));
Ok(tx.create(Entity::new(ENTITY, attributes)))
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ProjectLibraryDraft<'a> {
pub name: Option<&'a str>,
pub description: Option<&'a str>,
pub object_type: Option<&'a str>,
pub long_name: Option<&'a str>,
pub phase: Option<&'a str>,
pub units: Option<EntityId>,
}
pub fn create_project_library(
tx: &mut Transaction,
global_id: &str,
draft: ProjectLibraryDraft<'_>,
representation_contexts: &[EntityId],
) -> SpatialAuthoringResult<EntityId> {
const ENTITY: &str = "IFCPROJECTLIBRARY";
if Guid::parse(global_id).is_none() {
return Err(invalid(ENTITY, "GlobalId", global_id));
}
let mut attributes = vec![Value::Null; 9];
attributes[0] = Value::Text(global_id.into());
attributes[2] = optional_text(draft.name);
attributes[3] = optional_text(draft.description);
attributes[4] = optional_text(draft.object_type);
attributes[5] = optional_text(draft.long_name);
attributes[6] = optional_text(draft.phase);
if !representation_contexts.is_empty() {
attributes[7] = Value::List(
representation_contexts
.iter()
.copied()
.map(Value::Ref)
.collect(),
);
}
attributes[8] = draft.units.map_or(Value::Null, Value::Ref);
Ok(tx.create(Entity::new(ENTITY, attributes)))
}