Skip to main content

openbim_dt/
domain.rs

1//! Owned ISO 23387 type contracts used across standard boundaries.
2
3use crate::{
4    AnyUri, Base, Concept, DataTypeName, DateTime, Decimal, Language, MultiLanguageText, Rational,
5    Reference, Scale,
6};
7
8/// Owned `SubjectType` core shared by object types, groups, and data templates.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Subject {
11    concept: Concept,
12    has_part_refs: Vec<Reference>,
13    is_subtype_of_ref: Option<Reference>,
14}
15
16impl Subject {
17    #[must_use]
18    pub const fn new(concept: Concept) -> Self {
19        Self {
20            concept,
21            has_part_refs: Vec::new(),
22            is_subtype_of_ref: None,
23        }
24    }
25    #[must_use]
26    pub const fn concept(&self) -> &Concept {
27        &self.concept
28    }
29    #[must_use]
30    pub fn has_part_refs(&self) -> &[Reference] {
31        &self.has_part_refs
32    }
33    #[must_use]
34    pub const fn is_subtype_of_ref(&self) -> Option<&Reference> {
35        self.is_subtype_of_ref.as_ref()
36    }
37    pub fn add_has_part_ref(&mut self, value: Reference) {
38        self.has_part_refs.push(value);
39    }
40    pub fn set_is_subtype_of_ref(&mut self, value: Option<Reference>) {
41        self.is_subtype_of_ref = value;
42    }
43}
44
45/// ISO 23387 `ObjectTypeType`.
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub struct ObjectType(Subject);
48impl ObjectType {
49    #[must_use]
50    pub const fn new(subject: Subject) -> Self {
51        Self(subject)
52    }
53    #[must_use]
54    pub const fn subject(&self) -> &Subject {
55        &self.0
56    }
57    #[must_use]
58    pub fn into_subject(self) -> Subject {
59        self.0
60    }
61}
62
63/// One ordered simple value in ISO 23387 `ValueListType`.
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct DataValue {
66    value: String,
67    order: Option<i32>,
68}
69impl DataValue {
70    #[must_use]
71    pub fn new(value: impl Into<String>, order: Option<i32>) -> Self {
72        Self {
73            value: value.into(),
74            order,
75        }
76    }
77    #[must_use]
78    pub fn value(&self) -> &str {
79        &self.value
80    }
81    #[must_use]
82    pub const fn order(&self) -> Option<i32> {
83        self.order
84    }
85}
86
87/// One language-specific ISO 23387 `ValueListType`.
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct ValueList {
90    language: Language,
91    values: Vec<DataValue>,
92}
93impl ValueList {
94    #[must_use]
95    pub fn new(language: Language, first_value: DataValue) -> Self {
96        Self {
97            language,
98            values: vec![first_value],
99        }
100    }
101    #[must_use]
102    pub const fn language(&self) -> &Language {
103        &self.language
104    }
105    #[must_use]
106    pub fn values(&self) -> &[DataValue] {
107        &self.values
108    }
109    pub fn add_value(&mut self, value: DataValue) {
110        self.values.push(value);
111    }
112}
113
114/// One constraint carried by `DataTypeType`.
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub enum DataTypeConstraint {
117    MinInclusive(String),
118    MinExclusive(String),
119    MaxInclusive(String),
120    MaxExclusive(String),
121}
122
123/// ISO 23387 `DataTypeType`.
124#[derive(Debug, Clone, PartialEq, Eq, Default)]
125pub struct DataType {
126    name: Option<DataTypeName>,
127    constraints: Vec<DataTypeConstraint>,
128    data_formats: Vec<String>,
129    possible_values: Vec<ValueList>,
130}
131impl DataType {
132    #[must_use]
133    pub fn new(name: Option<DataTypeName>) -> Self {
134        Self {
135            name,
136            ..Self::default()
137        }
138    }
139    #[must_use]
140    pub const fn name(&self) -> Option<&DataTypeName> {
141        self.name.as_ref()
142    }
143    #[must_use]
144    pub fn constraints(&self) -> &[DataTypeConstraint] {
145        &self.constraints
146    }
147    #[must_use]
148    pub fn data_formats(&self) -> &[String] {
149        &self.data_formats
150    }
151    #[must_use]
152    pub fn possible_values(&self) -> &[ValueList] {
153        &self.possible_values
154    }
155    pub fn add_constraint(&mut self, value: DataTypeConstraint) {
156        self.constraints.push(value);
157    }
158    pub fn add_data_format(&mut self, value: impl Into<String>) {
159        self.data_formats.push(value.into());
160    }
161    pub fn add_possible_values(&mut self, value: ValueList) {
162        self.possible_values.push(value);
163    }
164}
165
166/// ISO 23387 `PropertyType`.
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub struct Property {
169    concept: Concept,
170    data_type: DataType,
171    symbols: Vec<String>,
172    dimension_ref: Option<Reference>,
173    unit_refs: Vec<Reference>,
174    quantity_kind_refs: Vec<Reference>,
175    dependency_refs: Vec<Reference>,
176    specialization_ref: Option<Reference>,
177}
178impl Property {
179    #[must_use]
180    pub const fn new(concept: Concept, data_type: DataType) -> Self {
181        Self {
182            concept,
183            data_type,
184            symbols: Vec::new(),
185            dimension_ref: None,
186            unit_refs: Vec::new(),
187            quantity_kind_refs: Vec::new(),
188            dependency_refs: Vec::new(),
189            specialization_ref: None,
190        }
191    }
192    #[must_use]
193    pub const fn concept(&self) -> &Concept {
194        &self.concept
195    }
196
197    #[must_use]
198    pub const fn data_type(&self) -> &DataType {
199        &self.data_type
200    }
201    #[must_use]
202    pub fn symbols(&self) -> &[String] {
203        &self.symbols
204    }
205    #[must_use]
206    pub const fn dimension_ref(&self) -> Option<&Reference> {
207        self.dimension_ref.as_ref()
208    }
209    #[must_use]
210    pub fn unit_refs(&self) -> &[Reference] {
211        &self.unit_refs
212    }
213    #[must_use]
214    pub fn quantity_kind_refs(&self) -> &[Reference] {
215        &self.quantity_kind_refs
216    }
217    #[must_use]
218    pub fn dependency_refs(&self) -> &[Reference] {
219        &self.dependency_refs
220    }
221    #[must_use]
222    pub const fn specialization_ref(&self) -> Option<&Reference> {
223        self.specialization_ref.as_ref()
224    }
225    pub fn add_symbol(&mut self, value: impl Into<String>) {
226        self.symbols.push(value.into());
227    }
228    pub fn set_dimension_ref(&mut self, value: Option<Reference>) {
229        self.dimension_ref = value;
230    }
231    pub fn add_unit_ref(&mut self, value: Reference) {
232        self.unit_refs.push(value);
233    }
234    pub fn add_quantity_kind_ref(&mut self, value: Reference) {
235        self.quantity_kind_refs.push(value);
236    }
237    pub fn add_dependency_ref(&mut self, value: Reference) {
238        self.dependency_refs.push(value);
239    }
240    pub fn set_specialization_ref(&mut self, value: Option<Reference>) {
241        self.specialization_ref = value;
242    }
243}
244
245/// ISO 23387 `QuantityKindType`.
246#[derive(Debug, Clone, PartialEq, Eq)]
247pub struct QuantityKind {
248    concept: Concept,
249    dimension_ref: Reference,
250}
251impl QuantityKind {
252    #[must_use]
253    pub const fn new(concept: Concept, dimension_ref: Reference) -> Self {
254        Self {
255            concept,
256            dimension_ref,
257        }
258    }
259    #[must_use]
260    pub const fn concept(&self) -> &Concept {
261        &self.concept
262    }
263    #[must_use]
264    pub const fn dimension_ref(&self) -> &Reference {
265        &self.dimension_ref
266    }
267}
268
269/// ISO 23387 `GroupOfPropertiesType`; the constructor enforces its non-empty property-reference sequence.
270#[derive(Debug, Clone, PartialEq, Eq)]
271pub struct GroupOfProperties {
272    subject: Subject,
273    property_refs: Vec<Reference>,
274}
275impl GroupOfProperties {
276    #[must_use]
277    pub fn new(subject: Subject, first_property_ref: Reference) -> Self {
278        Self {
279            subject,
280            property_refs: vec![first_property_ref],
281        }
282    }
283    #[must_use]
284    pub const fn subject(&self) -> &Subject {
285        &self.subject
286    }
287    #[must_use]
288    pub fn property_refs(&self) -> &[Reference] {
289        &self.property_refs
290    }
291    pub fn add_property_ref(&mut self, value: Reference) {
292        self.property_refs.push(value);
293    }
294}
295
296/// ISO 23387 `ReferenceDocumentType`.
297#[derive(Debug, Clone, PartialEq, Eq)]
298pub struct ReferenceDocument {
299    concept: Concept,
300    languages: Vec<Language>,
301    date_of_publication: Option<DateTime>,
302    author: Option<String>,
303    isbn: Option<String>,
304    publisher: Option<String>,
305    uri: Option<AnyUri>,
306}
307impl ReferenceDocument {
308    pub fn new(concept: Concept, first_language: Language) -> Self {
309        Self {
310            concept,
311            languages: vec![first_language],
312            date_of_publication: None,
313            author: None,
314            isbn: None,
315            publisher: None,
316            uri: None,
317        }
318    }
319    #[must_use]
320    pub const fn concept(&self) -> &Concept {
321        &self.concept
322    }
323    #[must_use]
324    pub fn languages(&self) -> &[Language] {
325        &self.languages
326    }
327    pub fn add_language(&mut self, value: Language) {
328        self.languages.push(value);
329    }
330    #[must_use]
331    pub const fn date_of_publication(&self) -> Option<&DateTime> {
332        self.date_of_publication.as_ref()
333    }
334    pub fn set_date_of_publication(&mut self, value: Option<DateTime>) {
335        self.date_of_publication = value;
336    }
337    #[must_use]
338    pub fn author(&self) -> Option<&str> {
339        self.author.as_deref()
340    }
341    pub fn set_author(&mut self, value: Option<String>) {
342        self.author = value;
343    }
344    #[must_use]
345    pub fn isbn(&self) -> Option<&str> {
346        self.isbn.as_deref()
347    }
348    pub fn set_isbn(&mut self, value: Option<String>) {
349        self.isbn = value;
350    }
351    #[must_use]
352    pub fn publisher(&self) -> Option<&str> {
353        self.publisher.as_deref()
354    }
355    pub fn set_publisher(&mut self, value: Option<String>) {
356        self.publisher = value;
357    }
358    #[must_use]
359    pub fn uri(&self) -> Option<&str> {
360        self.uri.as_ref().map(AnyUri::as_str)
361    }
362    pub fn set_uri(&mut self, value: Option<AnyUri>) {
363        self.uri = value;
364    }
365}
366
367/// Seven SI base-dimension exponents in Annex E declaration order.
368#[derive(Debug, Clone, PartialEq, Eq)]
369pub struct Dimension {
370    concept: Concept,
371    exponents: [Decimal; 7],
372}
373impl Dimension {
374    #[must_use]
375    pub const fn new(concept: Concept, exponents: [Decimal; 7]) -> Self {
376        Self { concept, exponents }
377    }
378    #[must_use]
379    pub const fn concept(&self) -> &Concept {
380        &self.concept
381    }
382    #[must_use]
383    pub const fn exponents(&self) -> &[Decimal; 7] {
384        &self.exponents
385    }
386}
387
388/// ISO 23387 `UnitType`, with all required scalar/reference fields present.
389#[derive(Debug, Clone, PartialEq, Eq)]
390pub struct Unit {
391    concept: Concept,
392    symbols: Vec<MultiLanguageText>,
393    dimension_ref: Reference,
394    scale: Scale,
395    base: Base,
396    coefficient: Rational,
397    offset: Rational,
398}
399impl Unit {
400    #[must_use]
401    pub const fn new(
402        concept: Concept,
403        dimension_ref: Reference,
404        scale: Scale,
405        base: Base,
406        coefficient: Rational,
407        offset: Rational,
408    ) -> Self {
409        Self {
410            concept,
411            symbols: Vec::new(),
412            dimension_ref,
413            scale,
414            base,
415            coefficient,
416            offset,
417        }
418    }
419    #[must_use]
420    pub const fn concept(&self) -> &Concept {
421        &self.concept
422    }
423    #[must_use]
424    pub fn symbols(&self) -> &[MultiLanguageText] {
425        &self.symbols
426    }
427    pub fn add_symbol(&mut self, value: MultiLanguageText) {
428        self.symbols.push(value);
429    }
430    #[must_use]
431    pub const fn dimension_ref(&self) -> &Reference {
432        &self.dimension_ref
433    }
434    #[must_use]
435    pub const fn scale(&self) -> &Scale {
436        &self.scale
437    }
438    #[must_use]
439    pub const fn base(&self) -> &Base {
440        &self.base
441    }
442    #[must_use]
443    pub const fn coefficient(&self) -> &Rational {
444        &self.coefficient
445    }
446    #[must_use]
447    pub const fn offset(&self) -> &Rational {
448        &self.offset
449    }
450}
451
452/// ISO 23387 `DataTemplateType`.
453#[derive(Debug, Clone, PartialEq, Eq)]
454pub struct DataTemplate {
455    subject: Subject,
456    object_type_ref: Option<Reference>,
457    property_refs: Vec<Reference>,
458    group_of_properties_refs: Vec<Reference>,
459}
460impl DataTemplate {
461    #[must_use]
462    pub const fn new(subject: Subject) -> Self {
463        Self {
464            subject,
465            object_type_ref: None,
466            property_refs: Vec::new(),
467            group_of_properties_refs: Vec::new(),
468        }
469    }
470    #[must_use]
471    pub const fn subject(&self) -> &Subject {
472        &self.subject
473    }
474    #[must_use]
475    pub const fn object_type_ref(&self) -> Option<&Reference> {
476        self.object_type_ref.as_ref()
477    }
478    #[must_use]
479    pub fn property_refs(&self) -> &[Reference] {
480        &self.property_refs
481    }
482    pub fn add_property_ref(&mut self, value: Reference) {
483        self.property_refs.push(value);
484    }
485    #[must_use]
486    pub fn group_of_properties_refs(&self) -> &[Reference] {
487        &self.group_of_properties_refs
488    }
489    pub fn add_group_of_properties_ref(&mut self, value: Reference) {
490        self.group_of_properties_refs.push(value);
491    }
492    pub fn set_object_type_ref(&mut self, value: Option<Reference>) {
493        self.object_type_ref = value;
494    }
495}