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}