Skip to main content

openbim_loin/
model.rs

1//! ISO 7817-3 contracts that directly consume ISO 23387-owned types.
2
3use openbim_dt::{
4    Concept, DateTime, Dimension, GroupOfProperties, Guid, Language, MultiLanguageText, ObjectType,
5    Property, QuantityKind, Reference, ReferenceDocument, Unit,
6};
7
8/// LOIN `PurposeType`; its identity, text, and references are DT-owned contracts.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Purpose {
11    guid: Guid,
12    name: MultiLanguageText,
13    definition: Option<MultiLanguageText>,
14    reference_documents: Vec<Reference>,
15    descriptions: Vec<MultiLanguageText>,
16    language: Option<Language>,
17    region: Option<String>,
18    dictionary_ref: Option<Reference>,
19}
20
21impl Purpose {
22    #[must_use]
23    pub const fn new(guid: Guid, name: MultiLanguageText) -> Self {
24        Self {
25            guid,
26            name,
27            definition: None,
28            reference_documents: Vec::new(),
29            descriptions: Vec::new(),
30            language: None,
31            region: None,
32            dictionary_ref: None,
33        }
34    }
35
36    #[must_use]
37    pub const fn guid(&self) -> &Guid {
38        &self.guid
39    }
40    #[must_use]
41    pub const fn name(&self) -> &MultiLanguageText {
42        &self.name
43    }
44    pub fn set_definition(&mut self, value: Option<MultiLanguageText>) {
45        self.definition = value;
46    }
47    pub fn add_reference_document(&mut self, value: Reference) {
48        self.reference_documents.push(value);
49    }
50    pub fn add_description(&mut self, value: MultiLanguageText) {
51        self.descriptions.push(value);
52    }
53    pub fn set_language(&mut self, value: Option<Language>) {
54        self.language = value;
55    }
56    #[must_use]
57    pub const fn language(&self) -> Option<&Language> {
58        self.language.as_ref()
59    }
60    pub fn set_region(&mut self, value: Option<String>) {
61        self.region = value;
62    }
63    pub fn set_dictionary_ref(&mut self, value: Option<Reference>) {
64        self.dictionary_ref = value;
65    }
66}
67
68/// LOIN `ActorType`, using DT identity and multilingual text.
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct Actor {
71    guid: Guid,
72    role: MultiLanguageText,
73    description: Option<MultiLanguageText>,
74}
75
76impl Actor {
77    #[must_use]
78    pub const fn new(guid: Guid, role: MultiLanguageText) -> Self {
79        Self {
80            guid,
81            role,
82            description: None,
83        }
84    }
85    #[must_use]
86    pub const fn guid(&self) -> &Guid {
87        &self.guid
88    }
89    #[must_use]
90    pub const fn role(&self) -> &MultiLanguageText {
91        &self.role
92    }
93    pub fn set_role(&mut self, value: MultiLanguageText) {
94        self.role = value;
95    }
96    pub fn set_description(&mut self, value: Option<MultiLanguageText>) {
97        self.description = value;
98    }
99}
100
101/// LOIN `InformationDeliveryMilestoneType`.
102#[derive(Debug, Clone, PartialEq, Eq)]
103pub struct InformationDeliveryMilestone {
104    guid: Guid,
105    name: MultiLanguageText,
106    descriptions: Vec<MultiLanguageText>,
107    reference_documents: Vec<Reference>,
108    date: Option<DateTime>,
109}
110
111impl InformationDeliveryMilestone {
112    #[must_use]
113    pub const fn new(guid: Guid, name: MultiLanguageText) -> Self {
114        Self {
115            guid,
116            name,
117            descriptions: Vec::new(),
118            reference_documents: Vec::new(),
119            date: None,
120        }
121    }
122    #[must_use]
123    pub const fn guid(&self) -> &Guid {
124        &self.guid
125    }
126    #[must_use]
127    pub const fn name(&self) -> &MultiLanguageText {
128        &self.name
129    }
130    pub fn add_description(&mut self, value: MultiLanguageText) {
131        self.descriptions.push(value);
132    }
133    pub fn add_reference_document(&mut self, value: Reference) {
134        self.reference_documents.push(value);
135    }
136    pub fn set_date(&mut self, value: Option<DateTime>) {
137        self.date = value;
138    }
139}
140
141/// LOIN prerequisites; all referenced identities are DT-owned GUID contracts.
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct Prerequisites {
144    guid: Guid,
145    purpose: Purpose,
146    milestone: InformationDeliveryMilestone,
147    providing_actor: Actor,
148    receiving_actor: Actor,
149}
150
151impl Prerequisites {
152    #[must_use]
153    pub const fn new(
154        guid: Guid,
155        purpose: Purpose,
156        milestone: InformationDeliveryMilestone,
157        providing_actor: Actor,
158        receiving_actor: Actor,
159    ) -> Self {
160        Self {
161            guid,
162            purpose,
163            milestone,
164            providing_actor,
165            receiving_actor,
166        }
167    }
168    #[must_use]
169    pub const fn guid(&self) -> &Guid {
170        &self.guid
171    }
172    #[must_use]
173    pub const fn purpose(&self) -> &Purpose {
174        &self.purpose
175    }
176    #[must_use]
177    pub const fn milestone(&self) -> &InformationDeliveryMilestone {
178        &self.milestone
179    }
180    #[must_use]
181    pub const fn providing_actor(&self) -> &Actor {
182        &self.providing_actor
183    }
184    #[must_use]
185    pub const fn receiving_actor(&self) -> &Actor {
186        &self.receiving_actor
187    }
188}
189
190/// Root LOIN specification contract.
191#[derive(Debug, Clone, PartialEq, Eq)]
192pub struct Specification {
193    guid: Guid,
194    name: String,
195    prerequisites: Prerequisites,
196    per_object: Vec<SpecificationPerObjectType>,
197}
198
199impl Specification {
200    #[must_use]
201    pub fn new(guid: Guid, name: impl Into<String>, prerequisites: Prerequisites) -> Self {
202        Self {
203            guid,
204            name: name.into(),
205            prerequisites,
206            per_object: Vec::new(),
207        }
208    }
209    #[must_use]
210    pub const fn guid(&self) -> &Guid {
211        &self.guid
212    }
213    #[must_use]
214    pub fn name(&self) -> &str {
215        &self.name
216    }
217    #[must_use]
218    pub const fn prerequisites(&self) -> &Prerequisites {
219        &self.prerequisites
220    }
221    pub fn add_per_object(&mut self, value: SpecificationPerObjectType) {
222        self.per_object.push(value);
223    }
224    #[must_use]
225    pub fn per_object(&self) -> &[SpecificationPerObjectType] {
226        &self.per_object
227    }
228}
229
230/// Anonymous LOIN alphanumerical-information content using imported DT types.
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct AlphanumericalInformation {
233    properties: Vec<Property>,
234    quantity_kinds: Vec<QuantityKind>,
235    groups_of_properties: Vec<GroupOfProperties>,
236    group_refs: Vec<Reference>,
237    reference_documents: Vec<ReferenceDocument>,
238    dimensions: Vec<Dimension>,
239    units: Vec<Unit>,
240}
241
242impl Default for AlphanumericalInformation {
243    fn default() -> Self {
244        Self::new()
245    }
246}
247
248impl AlphanumericalInformation {
249    #[must_use]
250    pub const fn new() -> Self {
251        Self {
252            properties: Vec::new(),
253            quantity_kinds: Vec::new(),
254            groups_of_properties: Vec::new(),
255            group_refs: Vec::new(),
256            reference_documents: Vec::new(),
257            dimensions: Vec::new(),
258            units: Vec::new(),
259        }
260    }
261    pub fn add_property(&mut self, value: Property) {
262        self.properties.push(value);
263    }
264    pub fn add_quantity_kind(&mut self, value: QuantityKind) {
265        self.quantity_kinds.push(value);
266    }
267    pub fn add_group_of_properties(&mut self, value: GroupOfProperties) {
268        self.groups_of_properties.push(value);
269    }
270    pub fn add_group_ref(&mut self, value: Reference) {
271        self.group_refs.push(value);
272    }
273    pub fn add_reference_document(&mut self, value: ReferenceDocument) {
274        self.reference_documents.push(value);
275    }
276    pub fn add_dimension(&mut self, value: Dimension) {
277        self.dimensions.push(value);
278    }
279    pub fn add_unit(&mut self, value: Unit) {
280        self.units.push(value);
281    }
282    #[must_use]
283    pub fn properties(&self) -> &[Property] {
284        &self.properties
285    }
286    #[must_use]
287    pub fn quantity_kinds(&self) -> &[QuantityKind] {
288        &self.quantity_kinds
289    }
290    #[must_use]
291    pub fn groups_of_properties(&self) -> &[GroupOfProperties] {
292        &self.groups_of_properties
293    }
294    #[must_use]
295    pub fn group_refs(&self) -> &[Reference] {
296        &self.group_refs
297    }
298    #[must_use]
299    pub fn reference_documents(&self) -> &[ReferenceDocument] {
300        &self.reference_documents
301    }
302    #[must_use]
303    pub fn dimensions(&self) -> &[Dimension] {
304        &self.dimensions
305    }
306    #[must_use]
307    pub fn units(&self) -> &[Unit] {
308        &self.units
309    }
310}
311
312/// One LOIN requirement per object type; its base and imported content are DT-owned.
313#[derive(Debug, Clone, PartialEq, Eq)]
314pub struct SpecificationPerObjectType {
315    concept: Concept,
316    object_type: ObjectType,
317    alphanumerical_information: Option<AlphanumericalInformation>,
318    documentation: Option<Documentation>,
319    geometrical_information: Option<GeometricalInformation>,
320}
321
322impl SpecificationPerObjectType {
323    #[must_use]
324    pub const fn new(concept: Concept, object_type: ObjectType) -> Self {
325        Self {
326            concept,
327            object_type,
328            alphanumerical_information: None,
329            documentation: None,
330            geometrical_information: None,
331        }
332    }
333    #[must_use]
334    pub const fn concept(&self) -> &Concept {
335        &self.concept
336    }
337    #[must_use]
338    pub const fn object_type(&self) -> &ObjectType {
339        &self.object_type
340    }
341    pub fn set_alphanumerical_information(&mut self, value: Option<AlphanumericalInformation>) {
342        self.alphanumerical_information = value;
343    }
344    #[must_use]
345    pub const fn alphanumerical_information(&self) -> Option<&AlphanumericalInformation> {
346        self.alphanumerical_information.as_ref()
347    }
348    pub fn set_documentation(&mut self, value: Option<Documentation>) {
349        self.documentation = value;
350    }
351    #[must_use]
352    pub const fn documentation(&self) -> Option<&Documentation> {
353        self.documentation.as_ref()
354    }
355    pub fn set_geometrical_information(&mut self, value: Option<GeometricalInformation>) {
356        self.geometrical_information = value;
357    }
358    #[must_use]
359    pub const fn geometrical_information(&self) -> Option<&GeometricalInformation> {
360        self.geometrical_information.as_ref()
361    }
362}
363
364/// LOIN `FormatType` using DT multilingual text and references.
365#[derive(Debug, Clone, PartialEq, Eq)]
366pub struct DocumentFormat {
367    names: Vec<MultiLanguageText>,
368    versions: Vec<MultiLanguageText>,
369    specifications: Vec<Reference>,
370}
371
372impl DocumentFormat {
373    #[must_use]
374    pub fn new(name: MultiLanguageText, version: MultiLanguageText) -> Self {
375        Self {
376            names: vec![name],
377            versions: vec![version],
378            specifications: Vec::new(),
379        }
380    }
381    pub fn add_name(&mut self, value: MultiLanguageText) {
382        self.names.push(value);
383    }
384    pub fn add_version(&mut self, value: MultiLanguageText) {
385        self.versions.push(value);
386    }
387    pub fn add_specification(&mut self, value: Reference) {
388        self.specifications.push(value);
389    }
390}
391
392/// LOIN `DocumentationType`, whose identity attribute is DT-owned.
393#[derive(Debug, Clone, PartialEq, Eq)]
394pub struct Documentation {
395    guid: Guid,
396    required_documents: Vec<RequiredDocument>,
397}
398
399impl Documentation {
400    #[must_use]
401    pub const fn new(guid: Guid) -> Self {
402        Self {
403            guid,
404            required_documents: Vec::new(),
405        }
406    }
407    #[must_use]
408    pub const fn guid(&self) -> &Guid {
409        &self.guid
410    }
411    pub fn add_required_document(&mut self, value: RequiredDocument) {
412        self.required_documents.push(value);
413    }
414    #[must_use]
415    pub fn required_documents(&self) -> &[RequiredDocument] {
416        &self.required_documents
417    }
418}
419
420/// LOIN geometrical-information identity using the imported DT GUID attribute.
421#[derive(Debug, Clone, PartialEq, Eq)]
422pub struct GeometricalInformation {
423    guid: Guid,
424}
425
426impl GeometricalInformation {
427    #[must_use]
428    pub const fn new(guid: Guid) -> Self {
429        Self { guid }
430    }
431    #[must_use]
432    pub const fn guid(&self) -> &Guid {
433        &self.guid
434    }
435}
436
437/// LOIN `RequiredDocumentType`.
438#[derive(Debug, Clone, PartialEq, Eq)]
439pub struct RequiredDocument {
440    guid: Guid,
441    name: MultiLanguageText,
442    format: DocumentFormat,
443    references: Vec<Reference>,
444    descriptions: Vec<MultiLanguageText>,
445}
446
447impl RequiredDocument {
448    #[must_use]
449    pub const fn new(guid: Guid, name: MultiLanguageText, format: DocumentFormat) -> Self {
450        Self {
451            guid,
452            name,
453            format,
454            references: Vec::new(),
455            descriptions: Vec::new(),
456        }
457    }
458    #[must_use]
459    pub const fn guid(&self) -> &Guid {
460        &self.guid
461    }
462    pub fn add_reference(&mut self, value: Reference) {
463        self.references.push(value);
464    }
465    pub fn add_description(&mut self, value: MultiLanguageText) {
466        self.descriptions.push(value);
467    }
468}
469
470/// LOIN threshold dimension importing DT unit and text contracts.
471#[derive(Debug, Clone, PartialEq)]
472pub struct ThresholdDimension {
473    threshold: f64,
474    unit: Unit,
475    definition: MultiLanguageText,
476}
477
478impl ThresholdDimension {
479    #[must_use]
480    pub const fn new(threshold: f64, unit: Unit, definition: MultiLanguageText) -> Self {
481        Self {
482            threshold,
483            unit,
484            definition,
485        }
486    }
487    #[must_use]
488    pub const fn unit(&self) -> &Unit {
489        &self.unit
490    }
491}
492
493/// LOIN geometry detail with an optional DT dictionary reference.
494#[derive(Debug, Clone, PartialEq, Eq)]
495pub struct Detail {
496    dictionary: Option<Reference>,
497}
498
499impl Detail {
500    #[must_use]
501    pub const fn new(dictionary: Option<Reference>) -> Self {
502        Self { dictionary }
503    }
504    #[must_use]
505    pub const fn dictionary(&self) -> Option<&Reference> {
506        self.dictionary.as_ref()
507    }
508}
509
510/// LOIN datum-registry reference using DT text and reference types.
511#[derive(Debug, Clone, PartialEq, Eq)]
512pub struct DatumRegistryReference {
513    name: MultiLanguageText,
514    descriptions: Vec<MultiLanguageText>,
515    registry_reference: Option<Reference>,
516}
517
518impl DatumRegistryReference {
519    #[must_use]
520    pub const fn new(name: MultiLanguageText) -> Self {
521        Self {
522            name,
523            descriptions: Vec::new(),
524            registry_reference: None,
525        }
526    }
527    #[must_use]
528    pub const fn name(&self) -> &MultiLanguageText {
529        &self.name
530    }
531    #[must_use]
532    pub fn descriptions(&self) -> &[MultiLanguageText] {
533        &self.descriptions
534    }
535    pub fn add_description(&mut self, value: MultiLanguageText) {
536        self.descriptions.push(value);
537    }
538    pub fn set_registry_reference(&mut self, value: Option<Reference>) {
539        self.registry_reference = value;
540    }
541}