Skip to main content

egml_core/model/base/
abstract_gml.rs

1use crate::model::abstract_object::{AbstractObject, AsAbstractObject, AsAbstractObjectMut};
2use crate::model::base::Id;
3use crate::model::basic_types::Code;
4
5/// Base data shared by every GML object ([OGC 07-036 ยง7.2.2.2](https://docs.ogc.org/is/07-036/07-036.pdf), `gml:AbstractGMLType`).
6///
7/// Every GML object carries an optional stable [`Id`] and zero-or-more human-readable
8/// name strings.  Concrete geometry and feature types embed `AbstractGml` and
9/// expose it through the [`AsAbstractGml`] trait.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
11pub struct AbstractGml {
12    pub abstract_object: AbstractObject,
13    /// Optional stable identifier for this GML object.
14    id: Option<Id>,
15    /// Human-readable names associated with this GML object.
16    names: Vec<Code>,
17}
18
19impl AbstractGml {
20    /// Creates a new `AbstractGml` with no id and no names.
21    ///
22    /// # Examples
23    ///
24    /// ```rust
25    /// use egml_core::model::base::AbstractGml;
26    /// use crate::egml_core::model::base::AsAbstractGml;
27    ///
28    /// let gml = AbstractGml::new();
29    /// assert!(gml.id().is_none());
30    /// assert!(gml.names().is_empty());
31    /// ```
32    pub fn new() -> Self {
33        Self::default()
34    }
35
36    pub fn from_abstract_object(abstract_object: AbstractObject) -> Self {
37        Self {
38            abstract_object,
39            id: None,
40            names: Vec::new(),
41        }
42    }
43
44    /// Creates a new `AbstractGml` pre-populated with the given `id`.
45    ///
46    /// # Examples
47    ///
48    /// ```rust
49    /// use egml_core::model::base::{AbstractGml, Id};
50    /// use crate::egml_core::model::base::AsAbstractGml;
51    ///
52    /// let id = Id::from_hashed_string("my-object");
53    /// let gml = AbstractGml::with_id(id);
54    /// assert!(gml.id().is_some());
55    /// ```
56    pub fn with_id(id: Id) -> Self {
57        Self {
58            id: Some(id),
59            ..Default::default()
60        }
61    }
62
63    /// Creates a new `AbstractGml` with an optional id.
64    ///
65    /// Equivalent to [`with_id`](Self::with_id) when `id` is `Some`, and to
66    /// [`new`](Self::new) when `id` is `None`.
67    pub fn with_optional_id(id: Option<Id>) -> Self {
68        Self {
69            id,
70            ..Default::default()
71        }
72    }
73}
74
75/// Object-safe read accessor for [`AbstractGml`] fields.
76///
77/// Implemented by all GML object types.  The default methods delegate to
78/// [`abstract_gml()`](Self::abstract_gml), so implementors only need to
79/// provide that single method.
80pub trait AsAbstractGml: AsAbstractObject {
81    /// Returns a reference to the embedded [`AbstractGml`] base data.
82    fn abstract_gml(&self) -> &AbstractGml;
83
84    /// Returns the optional identifier of this GML object.
85    fn id(&self) -> Option<&Id> {
86        self.abstract_gml().id.as_ref()
87    }
88
89    /// Returns the names of this GML object.
90    fn names(&self) -> &[Code] {
91        &self.abstract_gml().names
92    }
93}
94
95/// Mutable companion to [`AsAbstractGml`].
96///
97/// Implemented by all GML object types that expose mutable access to their
98/// base data.
99pub trait AsAbstractGmlMut: AsAbstractObjectMut + AsAbstractGml {
100    /// Returns a mutable reference to the embedded [`AbstractGml`] base data.
101    fn abstract_gml_mut(&mut self) -> &mut AbstractGml;
102
103    /// Sets the identifier of this GML object.
104    fn set_id(&mut self, id: Id) {
105        self.abstract_gml_mut().id = Some(id);
106    }
107
108    /// Sets or clears the identifier of this GML object.
109    fn set_id_opt(&mut self, id: Option<Id>) {
110        self.abstract_gml_mut().id = id;
111    }
112
113    /// Clears the identifier of this GML object.
114    fn clear_id(&mut self) {
115        self.abstract_gml_mut().id = None;
116    }
117
118    fn set_names(&mut self, names: Vec<Code>) {
119        self.abstract_gml_mut().names = names;
120    }
121
122    fn push_name(&mut self, name: Code) {
123        self.abstract_gml_mut().names.push(name);
124    }
125
126    fn extend_names(&mut self, names: impl IntoIterator<Item = Code>) {
127        self.abstract_gml_mut().names.extend(names);
128    }
129}
130
131impl AsAbstractGml for AbstractGml {
132    fn abstract_gml(&self) -> &AbstractGml {
133        self
134    }
135}
136
137impl AsAbstractGmlMut for AbstractGml {
138    fn abstract_gml_mut(&mut self) -> &mut AbstractGml {
139        self
140    }
141}
142
143#[macro_export]
144macro_rules! impl_abstract_gml_traits {
145    ($type:ty) => {
146        impl $crate::model::AsAbstractObject for $type {
147            fn abstract_object(&self) -> &$crate::model::AbstractObject {
148                &<$type as $crate::model::base::AsAbstractGml>::abstract_gml(self).abstract_object
149            }
150        }
151    };
152}
153
154#[macro_export]
155macro_rules! impl_abstract_gml_mut_traits {
156    ($type:ty) => {
157        impl $crate::model::AsAbstractObjectMut for $type {
158            fn abstract_object_mut(&mut self) -> &mut $crate::model::AbstractObject {
159                &mut <$type as $crate::model::base::AsAbstractGmlMut>::abstract_gml_mut(self)
160                    .abstract_object
161            }
162        }
163    };
164}
165
166impl_abstract_gml_traits!(AbstractGml);
167impl_abstract_gml_mut_traits!(AbstractGml);