cobia/cape_pmc_enumerator.rs
1use crate::C;
2use crate::*;
3
4/// Enumerator for all registered PMCs.
5///
6/// This is used to get the details of each PMC by name or UUID,
7/// or to get all registered PMCs.
8
9pub struct CapePMCEnumerator {
10 pub(crate) interface: *mut C::ICapePMCEnumerator,
11}
12
13impl CapePMCEnumerator {
14
15 /// Create a new PMC enumerator.
16 ///
17 /// # Examples
18 ///
19 /// ```
20 /// use cobia;
21 /// use cobia::prelude::*;
22 /// cobia::cape_open_initialize().unwrap();
23 /// let pmc_enumerator = cobia::CapePMCEnumerator::new().unwrap();
24 /// //...
25 /// cobia::cape_open_cleanup();
26 /// ```
27
28 pub fn new() -> Result<CapePMCEnumerator, COBIAError> {
29 let mut interface: *mut C::ICapePMCEnumerator = std::ptr::null_mut();
30 let result =
31 unsafe { C::capeGetPMCEnumerator(&mut interface as *mut *mut C::ICapePMCEnumerator) };
32 if result == COBIAERR_NOERROR {
33 Ok(CapePMCEnumerator { interface })
34 } else {
35 Err(COBIAError::Code(result))
36 }
37 }
38
39 /// Get a PMC by its UUID.
40 ///
41 /// Typically a PME will enumerate PMCs to allow the user to pick one.
42 /// Then the PME stores the UUID of the PMC that the user picked, so
43 /// that in future sessions, it can be re-created.
44 ///
45 /// Upon saving a flowsheet, the UUID of the PMC is stored in the
46 /// flowsheet, along with the UUID of the PME, and perhaps additional
47 /// information that is needed to re-create the PMC (such as the package
48 /// name in case of a Property Package created from a CAPE-OPEN 1.2
49 /// Property Package Manager).
50 ///
51 /// Then, when restoring the flowsheet, the PMC is created from its
52 /// UUID, and subsequently depersisted.
53 ///
54 /// # Examples
55 ///
56 /// ```
57 /// use cobia;
58 /// use cobia::prelude::*;
59 /// cobia::cape_open_initialize().unwrap();
60 /// let pmc_enumerator = cobia::CapePMCEnumerator::new().unwrap();
61 /// let mut first_pmc : Option<cobia::CapePMCRegistrationDetails> = None;
62 /// for pmc in pmc_enumerator.all_pmcs().unwrap() {
63 /// first_pmc = Some(pmc);
64 /// break;
65 /// }
66 /// if let Some(pmc) = first_pmc {
67 /// let uuid = pmc.get_uuid().unwrap();
68 /// let pmc = pmc_enumerator.get_pmc_by_uuid(&uuid).unwrap();
69 /// assert_eq!(pmc.get_uuid().unwrap(),uuid);
70 /// }
71 /// cobia::cape_open_cleanup();
72 /// ```
73
74 pub fn get_pmc_by_uuid(&self, uuid: &CapeUUID) -> Result<CapePMCRegistrationDetails, COBIAError> {
75 let mut interface: *mut C::ICapePMCRegistrationDetails = std::ptr::null_mut();
76 let result = unsafe {
77 ((*(*self.interface).vTbl).getPMCbyUUID.unwrap())(
78 (*self.interface).me,
79 (uuid as *const C::CapeUUID).cast_mut(),
80 &mut interface as *mut *mut C::ICapePMCRegistrationDetails,
81 )
82 };
83 if result == COBIAERR_NOERROR {
84 Ok(CapePMCRegistrationDetails { interface })
85 } else {
86 Err(COBIAError::Code(result))
87 }
88 }
89
90 pub fn get_pmc_by_prog_id(
91 &self,
92 prog_id: &str,
93 ) -> Result<CapePMCRegistrationDetails, COBIAError> {
94 let mut interface: *mut C::ICapePMCRegistrationDetails = std::ptr::null_mut();
95 let result = unsafe {
96 ((*(*self.interface).vTbl).getPMCbyProgId.unwrap())(
97 (*self.interface).me,
98 CapeStringImpl::from_string(prog_id).as_capechar_const(),
99 &mut interface as *mut *mut C::ICapePMCRegistrationDetails,
100 )
101 };
102 if result == COBIAERR_NOERROR {
103 Ok(CapePMCRegistrationDetails { interface })
104 } else {
105 Err(COBIAError::Code(result))
106 }
107 }
108
109 /// Get all registered PMCs of specific type(s).
110 ///
111 /// Get a collection of all registered PMCs, of a given type or
112 /// multiple given types.
113 ///
114 /// In a typical scenario the PME is interested in instantiating, and therefore
115 /// selecting,a specific type of PMC, such as a Property Package, Unit Operation, ...
116 /// This function provides a collection with all PMCs of the given type(s).
117 ///
118 /// On Windows, COM based PMCs are included in the collection.
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// use cobia;
124 /// use cobia::prelude::*;
125 /// use cobia::cape_open;
126 /// cobia::cape_open_initialize().unwrap();
127 /// let pmc_enumerator = cobia::CapePMCEnumerator::new().unwrap();
128 /// //let's create some thermo! Enumerate all Property Package Managers and stand-alone Property Packages
129 /// let pmc_types=[cape_open::CATEGORYID_PROPERTYPACKAGEMANAGER,cape_open::CATEGORYID_STANDALONEPROPERTYPACKAGE];
130 /// let pmcs = pmc_enumerator.pmcs(&pmc_types).unwrap();
131 /// for pmc in pmcs {
132 /// println!("Found Thermo-PMC: {} ({})",pmc.get_name().unwrap(),pmc.get_description().unwrap());
133 /// }
134 /// cobia::cape_open_cleanup();
135 /// ```
136
137 pub fn pmcs(&self,cat_ids: &[CapeUUID]) -> Result<CobiaCollection<CapePMCRegistrationDetails>,COBIAError> {
138 let mut p: *mut C::ICobiaCollection = std::ptr::null_mut();
139 let result = unsafe {
140 //let cat_ids_repr: std::raw::Slice<CapeUUID> = cat_ids.repr(); TODO std::raw::Slice is unstable, use when available
141 let mut v: std::vec::Vec<CapeUUID> = Vec::new(); //work-around: store in a local vector
142 v.extend_from_slice(cat_ids);
143 ((*(*self.interface).vTbl).getPMCsByCategory.unwrap())(
144 (*self.interface).me,
145 v.as_ptr(),
146 v.len() as C::CapeSize,
147 &mut p as *mut *mut C::ICobiaCollection
148 )
149 };
150 if result == COBIAERR_NOERROR {
151 if p.is_null() {
152 Err(COBIAError::Code(COBIAERR_NULLPOINTER))
153 } else {
154 Ok(CobiaCollection::attach(p))
155 }
156 } else {
157 Err(COBIAError::Code(result))
158 }
159 }
160
161 /// Get all registered PMCs of any type.
162 ///
163 /// Get a collection of all registered PMCs, of any PMC type.
164 ///
165 /// This function is not typically used, as in a typical scenario
166 /// the PME is interested in instantiating, and therefore selecting,
167 /// a specific type of PMC, such as a Property Package, Unit Operation, ...
168 ///
169 /// On Windows, COM based PMCs are included in the collection.
170 ///
171 /// # Examples
172 ///
173 /// ```
174 /// use cobia;
175 /// use cobia::prelude::*;
176 /// cobia::cape_open_initialize().unwrap();
177 /// let pmc_enumerator = cobia::CapePMCEnumerator::new().unwrap();
178 /// let pmcs = pmc_enumerator.all_pmcs().unwrap();
179 /// for pmc in pmcs {
180 /// println!("Found PMC: {} ({})",pmc.get_name().unwrap(),pmc.get_description().unwrap());
181 /// }
182 /// cobia::cape_open_cleanup();
183 /// ```
184
185 pub fn all_pmcs(&self) -> Result<CobiaCollection<CapePMCRegistrationDetails>,COBIAError> {
186 let mut p: *mut C::ICobiaCollection = std::ptr::null_mut();
187 let result = unsafe {
188 ((*(*self.interface).vTbl).getAllPMCs.unwrap())(
189 (*self.interface).me,
190 &mut p as *mut *mut C::ICobiaCollection
191 )
192 };
193 if result == COBIAERR_NOERROR {
194 if p.is_null() {
195 Err(COBIAError::Code(COBIAERR_NULLPOINTER))
196 } else {
197 Ok(CobiaCollection::attach(p))
198 }
199 } else {
200 Err(COBIAError::Code(result))
201 }
202 }
203
204}
205
206/// Release pointer
207///
208/// ICapePMCEnumerator derives from ICobiaBase, which contains
209/// addReference() and release(). The Drop trait calls release.
210
211impl Drop for CapePMCEnumerator {
212 fn drop(&mut self) {
213 unsafe {
214 ((*(*self.interface).vTbl).base.release.unwrap())((*self.interface).me);
215 }
216 }
217}
218
219/// Add pointer reference
220///
221/// ICapePMCEnumerator derives from ICobiaBase, which contains
222/// addReference() and release(). The Clone trait calls addReference.
223
224impl Clone for CapePMCEnumerator {
225 fn clone(&self) -> Self {
226 unsafe {
227 ((*(*self.interface).vTbl).base.addReference.unwrap())((*self.interface).me);
228 }
229 CapePMCEnumerator {
230 interface: self.interface,
231 }
232 }
233}