use core::fmt;
use openbim_core::Detected;
use crate::{IdsVersion, Occurrence};
#[derive(Debug, Clone, PartialEq)]
pub struct Ids {
pub version: Detected<IdsVersion>,
pub info: Info,
pub specifications: Vec<Specification>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Info {
pub title: String,
pub copyright: Option<String>,
pub version: Option<String>,
pub description: Option<String>,
pub author: Option<String>,
pub date: Option<String>,
pub purpose: Option<String>,
pub milestone: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Specification {
pub name: String,
pub ifc_versions: Vec<IfcVersion>,
pub identifier: Option<String>,
pub description: Option<String>,
pub instructions: Option<String>,
pub applicability: Applicability,
pub requirements: Option<Requirements>,
}
impl Specification {
#[must_use]
pub fn occurrence(&self) -> Occurrence {
self.applicability.occurrence()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum IfcVersion {
Ifc2x3,
Ifc4,
Ifc4x3Add2,
}
impl IfcVersion {
pub const ALL: [IfcVersion; 3] = [IfcVersion::Ifc2x3, IfcVersion::Ifc4, IfcVersion::Ifc4x3Add2];
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
IfcVersion::Ifc2x3 => "IFC2X3",
IfcVersion::Ifc4 => "IFC4",
IfcVersion::Ifc4x3Add2 => "IFC4X3_ADD2",
}
}
#[must_use]
pub fn from_token(token: &str) -> Option<IfcVersion> {
IfcVersion::ALL.into_iter().find(|v| v.as_str() == token)
}
}
impl fmt::Display for IfcVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Applicability {
pub min_occurs: u32,
pub max_occurs: Option<u32>,
pub facets: Vec<Facet>,
}
impl Applicability {
#[must_use]
pub fn occurrence(&self) -> Occurrence {
Occurrence::from_xs_occurs(self.min_occurs, self.max_occurs)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Requirements {
pub description: Option<String>,
pub facets: Vec<Requirement>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Requirement {
pub facet: Facet,
pub occurrence: Occurrence,
pub uri: Option<String>,
pub instructions: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Facet {
Entity(Entity),
PartOf(PartOf),
Classification(Classification),
Attribute(Attribute),
Property(Property),
Material(Material),
}
impl Facet {
#[must_use]
pub fn kind(&self) -> &'static str {
match self {
Facet::Entity(_) => "entity",
Facet::PartOf(_) => "partOf",
Facet::Classification(_) => "classification",
Facet::Attribute(_) => "attribute",
Facet::Property(_) => "property",
Facet::Material(_) => "material",
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Entity {
pub name: Value,
pub predefined_type: Option<Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct PartOf {
pub entity: Entity,
pub relation: Option<Relation>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Relation {
Aggregates,
AssignsToGroup,
ContainedInSpatialStructure,
Nests,
VoidsElementFillsElement,
}
impl Relation {
pub const ALL: [Relation; 5] = [
Relation::Aggregates,
Relation::AssignsToGroup,
Relation::ContainedInSpatialStructure,
Relation::Nests,
Relation::VoidsElementFillsElement,
];
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Relation::Aggregates => "IFCRELAGGREGATES",
Relation::AssignsToGroup => "IFCRELASSIGNSTOGROUP",
Relation::ContainedInSpatialStructure => "IFCRELCONTAINEDINSPATIALSTRUCTURE",
Relation::Nests => "IFCRELNESTS",
Relation::VoidsElementFillsElement => "IFCRELVOIDSELEMENT IFCRELFILLSELEMENT",
}
}
#[must_use]
pub fn from_token(token: &str) -> Option<Relation> {
Relation::ALL.into_iter().find(|r| r.as_str() == token)
}
}
impl fmt::Display for Relation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Classification {
pub value: Option<Value>,
pub system: Value,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Attribute {
pub name: Value,
pub value: Option<Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Property {
pub property_set: Value,
pub base_name: Value,
pub value: Option<Value>,
pub data_type: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Material {
pub value: Option<Value>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
Simple(String),
Restriction(Box<Restriction>),
}
impl Value {
#[must_use]
pub fn as_simple(&self) -> Option<&str> {
match self {
Value::Simple(value) => Some(value),
Value::Restriction(_) => None,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Restriction {
pub base: String,
pub enumeration: Vec<String>,
pub patterns: Vec<String>,
pub min_inclusive: Option<String>,
pub max_inclusive: Option<String>,
pub min_exclusive: Option<String>,
pub max_exclusive: Option<String>,
pub length: Option<u64>,
pub min_length: Option<u64>,
pub max_length: Option<u64>,
pub total_digits: Option<u64>,
pub fraction_digits: Option<u64>,
}