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);