Skip to main content

ifc_properties/template/check/
finding.rs

1//! What a template check reports.
2
3use std::sync::Arc;
4
5use ifc_model::EntityId;
6
7use crate::error::PropertyAnomaly;
8
9/// Which measure-type attribute of an `IfcSimplePropertyTemplate` a value
10/// was checked against.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum MeasureRole {
14    /// `PrimaryMeasureType`.
15    Primary,
16    /// `SecondaryMeasureType`.
17    Secondary,
18}
19
20/// Why a check could not decide whether a set conforms to its template.
21///
22/// Each reason names something IFC leaves undefined or the file leaves
23/// unstated. The checker reports it rather than guessing either way.
24#[derive(Debug, Clone, PartialEq, Eq)]
25#[non_exhaustive]
26pub enum UndecidedReason {
27    /// A `TemplateType` constant that is not a member of the declared
28    /// release's enumeration, e.g. `Q_NUMBER` in an IFC4 file.
29    UnknownTemplateType {
30        /// The constant as written.
31        value: Arc<str>,
32    },
33    /// A `TemplateType` constant whose documentation in the declared release
34    /// does not say which entity it governs: IFC4X3 ADD2 documents
35    /// `Q_NUMBER` with "No description available".
36    UndocumentedTemplateType {
37        /// The constant.
38        value: Arc<str>,
39    },
40    /// A `PrimaryMeasureType` or `SecondaryMeasureType` that names no type
41    /// or entity the declared release declares.
42    UnknownMeasureType {
43        /// Which of the two.
44        measure: MeasureRole,
45        /// The label as written.
46        value: Arc<str>,
47    },
48    /// A value whose type cannot be read: a select member written without
49    /// its type, or a reference to an entity absent from the file.
50    UntypedValue {
51        /// The property attribute holding it, e.g. `NominalValue`.
52        attribute: &'static str,
53    },
54    /// A property template without a `Name`, which cannot be matched to any
55    /// property: templates are matched to properties by `Name` alone.
56    UnnamedTemplate,
57    /// An `ApplicableEntity` entry that names no entity of the declared
58    /// release, or does not follow the documented form
59    /// `IfcEntity[/PREDEFINEDTYPE][[PerformanceHistory]]`.
60    UnknownApplicableEntity {
61        /// The entry, trimmed.
62        entry: Arc<str>,
63    },
64    /// An `ApplicableEntity` entry qualified by a predefined type, on an
65    /// object of that entity whose own `PredefinedType` is unset,
66    /// `NOTDEFINED`, or not an attribute of its entity. The type object may
67    /// state it instead, and that is not followed here.
68    PredefinedTypeUnstated {
69        /// The entry, trimmed.
70        entry: Arc<str>,
71    },
72    /// An `ApplicableEntity` entry qualified by `[PerformanceHistory]` on an
73    /// `IfcPerformanceHistory`: the entry names the object the history is
74    /// assigned to by `IfcRelAssignsToControl`, which is not followed here.
75    PerformanceHistory {
76        /// The entry, trimmed.
77        entry: Arc<str>,
78    },
79    /// The templated set is a predefined property set (e.g.
80    /// `IfcDoorLiningProperties`), whose members are fixed attributes of its
81    /// entity rather than named properties; templates are documented for
82    /// `IfcPropertySet` and `IfcElementQuantity` only.
83    PredefinedSet {
84        /// The set's IFC type name.
85        found: Arc<str>,
86    },
87}
88
89/// One way a templated property set deviates from an
90/// `IfcPropertySetTemplate` linked to it by `IfcRelDefinesByTemplate`.
91///
92/// Every finding names the set and the set template; findings about one
93/// property also name the property and/or the (possibly nested) property
94/// template. A finding is a deviation from the in-file template, which is
95/// what the caller asked about; except where noted, IFC does not make it a
96/// schema violation.
97#[derive(Debug, Clone, PartialEq, Eq)]
98#[non_exhaustive]
99pub enum TemplateFinding {
100    /// A property template has no property of its `Name` in the set (or, for
101    /// a nested template, in the complex property).
102    MissingProperty {
103        /// The templated set.
104        set: EntityId,
105        /// The `IfcPropertySetTemplate`.
106        template: EntityId,
107        /// The set, or the complex property or quantity whose members were
108        /// compared.
109        container: EntityId,
110        /// The property template with no property.
111        property_template: EntityId,
112        /// Its `Name`.
113        name: Arc<str>,
114    },
115    /// A property whose `Name` no property template of the set template (or
116    /// of the complex template) states.
117    UnexpectedProperty {
118        /// The templated set.
119        set: EntityId,
120        /// The `IfcPropertySetTemplate`.
121        template: EntityId,
122        /// The set, or the complex property or quantity holding it.
123        container: EntityId,
124        /// The property or quantity.
125        property: EntityId,
126        /// Its `Name`.
127        name: Arc<str>,
128    },
129    /// A property whose entity is not the one its template's `TemplateType`
130    /// prescribes, e.g. an `IfcPropertySingleValue` where the template says
131    /// `P_ENUMERATEDVALUE`.
132    WrongForm {
133        /// The templated set.
134        set: EntityId,
135        /// The `IfcPropertySetTemplate`.
136        template: EntityId,
137        /// The property or quantity.
138        property: EntityId,
139        /// Its template.
140        property_template: EntityId,
141        /// The template's `TemplateType`; `None` when unset, when any simple
142        /// (for a simple template) or complex (for a complex one) property
143        /// or quantity is expected.
144        template_type: Option<Arc<str>>,
145        /// The entities any of which would conform (subtypes included).
146        expected: &'static [&'static str],
147        /// The property's IFC type name.
148        found: Arc<str>,
149    },
150    /// A value whose declared type is not the template's measure type.
151    WrongMeasureType {
152        /// The templated set.
153        set: EntityId,
154        /// The `IfcPropertySetTemplate`.
155        template: EntityId,
156        /// The property.
157        property: EntityId,
158        /// Its template.
159        property_template: EntityId,
160        /// Which measure type of the template applies.
161        measure: MeasureRole,
162        /// The property attribute checked, e.g. `NominalValue`.
163        attribute: &'static str,
164        /// The template's measure type, as written.
165        expected: Arc<str>,
166        /// The first nonconforming value's type, or the referenced entity's
167        /// type for a reference value.
168        found: Arc<str>,
169    },
170    /// The set is not the entity the template's `TemplateType` governs: a
171    /// `PSET_*` template on an `IfcElementQuantity`, a `QTO_*` template on
172    /// an `IfcPropertySet`, or (IFC4X3) a material- or profile-driven
173    /// template on any property set definition.
174    WrongSetKind {
175        /// The templated set.
176        set: EntityId,
177        /// The `IfcPropertySetTemplate`.
178        template: EntityId,
179        /// The template's `TemplateType`.
180        template_type: Arc<str>,
181        /// The entity the template type governs.
182        expected: &'static str,
183        /// The set's IFC type name.
184        found: Arc<str>,
185    },
186    /// The set sits on an object its template's `TemplateType` excludes: a
187    /// `*_TYPEDRIVENONLY` set on an occurrence, an `*_OCCURRENCEDRIVEN` set
188    /// on a type, a `PSET_PERFORMANCEDRIVEN` set on anything but an
189    /// `IfcPerformanceHistory`.
190    WrongAttachment {
191        /// The templated set.
192        set: EntityId,
193        /// The `IfcPropertySetTemplate`.
194        template: EntityId,
195        /// The object carrying the set.
196        object: EntityId,
197        /// The template's `TemplateType`.
198        template_type: Arc<str>,
199        /// The object's IFC type name.
200        found: Arc<str>,
201    },
202    /// The set sits on an object that no entry of the template's
203    /// `ApplicableEntity` admits.
204    OutsideApplicableEntity {
205        /// The templated set.
206        set: EntityId,
207        /// The `IfcPropertySetTemplate`.
208        template: EntityId,
209        /// The object carrying the set.
210        object: EntityId,
211        /// The object's IFC type name.
212        found: Arc<str>,
213        /// The template's `ApplicableEntity`, as written.
214        applicable_entity: Arc<str>,
215    },
216    /// Whether `subject` conforms cannot be decided from the file and the
217    /// release's documentation.
218    Undecided {
219        /// The templated set.
220        set: EntityId,
221        /// The `IfcPropertySetTemplate`.
222        template: EntityId,
223        /// What could not be decided: a property, a property template, the
224        /// set template, or an object carrying the set.
225        subject: EntityId,
226        /// Why.
227        reason: UndecidedReason,
228    },
229}
230
231/// Everything a template check found.
232#[derive(Debug, Clone, PartialEq, Default)]
233#[non_exhaustive]
234pub struct TemplateReport {
235    /// Deviations, grouped by set (ascending id), then template (ascending
236    /// id); within one pair, the set's kind, then its members in file
237    /// order, then its missing members in template order, then the objects
238    /// carrying it (ascending id).
239    pub findings: Vec<TemplateFinding>,
240    /// Malformed facts met while reading templates, sets and relationships.
241    /// A member or template left out because of one is not compared, so a
242    /// report with anomalies is not a proof of conformance.
243    pub anomalies: Vec<PropertyAnomaly>,
244}