use ifc_model::{EntityId, Model, Transaction, Value};
use super::connections::{check_realizing, distinct};
use super::relationships::check_factor;
use super::release::stage;
use super::{check_relate, check_relate_one, SpatialAuthoringResult};
use crate::relation::slots::{
RelSlots, ADHERES_TO_ELEMENT, ASSIGNS_TO_ACTOR, ASSIGNS_TO_GROUP_BY_FACTOR, ASSIGNS_TO_PROCESS,
ASSIGNS_TO_PRODUCT, ASSIGNS_TO_RESOURCE, ASSOCIATES_PROFILE_DEF, CONNECTS_ELEMENTS,
CONNECTS_WITH_REALIZING, COVERS_ELEMENTS, COVERS_SPACES, DECLARES, DEFINES_BY_OBJECT,
FILLS_ELEMENT, FLOW_CONTROL_ELEMENTS, INTERFERES_ELEMENTS, POSITIONS, PROJECTS_ELEMENT,
SERVICES_BUILDINGS, VOIDS_ELEMENT,
};
pub(super) fn refs(ids: &[EntityId]) -> Value {
Value::List(ids.iter().copied().map(Value::Ref).collect())
}
#[allow(clippy::too_many_arguments)]
pub(super) fn relate_owned(
tx: &mut Transaction,
model: &Model,
rel: RelSlots,
global_id: &str,
parent: EntityId,
children: &[EntityId],
extra: Vec<(&'static str, Value)>,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
check_relate(rel, global_id, parent, children)?;
let mut values = vec![
("GlobalId", Value::Text(global_id.into())),
(rel.relating_name(), Value::Ref(parent)),
(rel.related_name(), refs(children)),
];
values.extend(extra);
stage(tx, model, rel.type_name, values, Some(owner_history))
}
fn relate_one_owned(
tx: &mut Transaction,
model: &Model,
rel: RelSlots,
global_id: &str,
relating: EntityId,
related: EntityId,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
check_relate_one(rel, global_id, relating, related)?;
let values = vec![
("GlobalId", Value::Text(global_id.into())),
(rel.relating_name(), Value::Ref(relating)),
(rel.related_name(), Value::Ref(related)),
];
stage(tx, model, rel.type_name, values, Some(owner_history))
}
#[allow(clippy::too_many_arguments)]
fn pair_owned(
tx: &mut Transaction,
model: &Model,
rel: RelSlots,
global_id: &str,
relating: EntityId,
related: EntityId,
extra: Vec<(&'static str, Value)>,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
distinct(rel, global_id, relating, related)?;
let mut values = vec![
("GlobalId", Value::Text(global_id.into())),
(rel.relating_name(), Value::Ref(relating)),
(rel.related_name(), Value::Ref(related)),
];
values.extend(extra);
stage(tx, model, rel.type_name, values, Some(owner_history))
}
macro_rules! set_valued {
($(#[$doc:meta])* $name:ident, $plain:ident, $rel:ident, $parent:ident, $children:ident) => {
$(#[$doc])*
#[doc = concat!("Those of [`", stringify!($plain), "`](super::", stringify!($plain), "),")]
pub fn $name(
tx: &mut Transaction,
model: &Model,
global_id: &str,
$parent: EntityId,
$children: &[EntityId],
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
relate_owned(
tx,
model,
$rel,
global_id,
$parent,
$children,
Vec::new(),
owner_history,
)
}
};
}
macro_rules! single_valued {
($(#[$doc:meta])* $name:ident, $plain:ident, $rel:ident, $relating:ident, $related:ident) => {
$(#[$doc])*
#[doc = concat!("Those of [`", stringify!($plain), "`](super::", stringify!($plain), "),")]
pub fn $name(
tx: &mut Transaction,
model: &Model,
global_id: &str,
$relating: EntityId,
$related: EntityId,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
relate_one_owned(tx, model, $rel, global_id, $relating, $related, owner_history)
}
};
}
set_valued!(
cover_elements_with_owner_history, cover_elements, COVERS_ELEMENTS, element, coverings
);
set_valued!(
cover_spaces_with_owner_history, cover_spaces, COVERS_SPACES, space, coverings
);
set_valued!(
declare_with_owner_history, declare, DECLARES, context, definitions
);
set_valued!(
define_by_object_with_owner_history, define_by_object, DEFINES_BY_OBJECT, defining, defined
);
set_valued!(
serve_buildings_with_owner_history, serve_buildings, SERVICES_BUILDINGS, system, buildings
);
set_valued!(
control_flow_element_with_owner_history,
control_flow_element,
FLOW_CONTROL_ELEMENTS,
flow_element,
controls
);
set_valued!(
assign_to_actor_with_owner_history, assign_to_actor, ASSIGNS_TO_ACTOR, actor, objects
);
set_valued!(
assign_to_product_with_owner_history, assign_to_product, ASSIGNS_TO_PRODUCT, product, objects
);
set_valued!(
assign_to_process_with_owner_history, assign_to_process, ASSIGNS_TO_PROCESS, process, objects
);
set_valued!(
adhere_to_element_with_owner_history, adhere_to_element, ADHERES_TO_ELEMENT, element, features
);
set_valued!(
position_products_with_owner_history, position_products, POSITIONS, positioning, products
);
set_valued!(
assign_to_resource_with_owner_history, assign_to_resource, ASSIGNS_TO_RESOURCE, resource, objects
);
set_valued!(
associate_profile_def_with_owner_history,
associate_profile_def,
ASSOCIATES_PROFILE_DEF,
profile,
objects
);
single_valued!(
void_element_with_owner_history, void_element, VOIDS_ELEMENT, element, opening
);
single_valued!(
fill_element_with_owner_history, fill_element, FILLS_ELEMENT, opening, filling
);
single_valued!(
project_element_with_owner_history, project_element, PROJECTS_ELEMENT, element, feature
);
pub fn assign_to_group_by_factor_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
group: EntityId,
members: &[EntityId],
factor: f64,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
check_factor(factor)?;
relate_owned(
tx,
model,
ASSIGNS_TO_GROUP_BY_FACTOR,
global_id,
group,
members,
vec![("Factor", Value::Real(factor))],
owner_history,
)
}
pub fn connect_elements_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
relating: EntityId,
related: EntityId,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
pair_owned(
tx,
model,
CONNECTS_ELEMENTS,
global_id,
relating,
related,
Vec::new(),
owner_history,
)
}
pub fn connect_with_realizing_elements_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
relating: EntityId,
related: EntityId,
realizing: &[EntityId],
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
check_realizing(realizing)?;
pair_owned(
tx,
model,
CONNECTS_WITH_REALIZING,
global_id,
relating,
related,
vec![("RealizingElements", refs(realizing))],
owner_history,
)
}
pub fn interfere_elements_with_owner_history(
tx: &mut Transaction,
model: &Model,
global_id: &str,
relating: EntityId,
related: EntityId,
implied_order: Option<bool>,
owner_history: EntityId,
) -> SpatialAuthoringResult<EntityId> {
pair_owned(
tx,
model,
INTERFERES_ELEMENTS,
global_id,
relating,
related,
vec![(
"ImpliedOrder",
implied_order.map_or(Value::LogicalUnknown, Value::Bool),
)],
owner_history,
)
}