1use lang_extension::any::*;
4use std::sync::Arc;
5
6use crate::manager::default::*;
7use crate::manager::*;
8use crate::property::default::*;
9use crate::property::*;
10use crate::source::default::*;
11use crate::source::*;
12
13pub struct ConfigurationManagers;
15
16impl ConfigurationManagers {
17 pub fn new_config_builder() -> Box<dyn ConfigurationManagerConfigBuilder> {
18 Box::new(DefaultConfigurationManagerConfigBuilder::new())
19 }
20
21 pub fn new_manager(
22 config: Box<dyn ConfigurationManagerConfig>,
23 ) -> Box<dyn ConfigurationManager> {
24 Box::new(DefaultConfigurationManager::new(config))
25 }
26}
27
28#[derive(PartialEq, Debug, Clone)]
30pub struct ConfigurationProperties {
31 manager: Arc<Box<dyn ConfigurationManager>>,
32}
33
34unsafe impl Sync for ConfigurationProperties {}
35unsafe impl Send for ConfigurationProperties {}
36
37impl ConfigurationProperties {
38 pub fn new_config_builder<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>()
39 -> Box<dyn PropertyConfigBuilder<K, V>> {
40 Box::new(DefaultPropertyConfigBuilder::new())
41 }
42
43 pub fn new(manager: Box<dyn ConfigurationManager>) -> Self {
44 Self {
45 manager: Arc::new(manager),
46 }
47 }
48
49 pub fn get_manager(&self) -> &dyn ConfigurationManager {
50 self.manager.as_ref().as_ref()
51 }
52
53 pub fn get_property<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>(
54 &self,
55 config: &dyn PropertyConfig<K, V>,
56 ) -> Box<dyn Property<K, V>> {
57 let p = self
58 .manager
59 .get_property(RawPropertyConfig::as_trait_ref(config));
60 Property::to_boxed(DefaultProperty::from_raw(p.as_ref()))
61 }
62
63 pub fn get_property_value<K: ?Sized + KeyConstraint, V: ?Sized + ValueConstraint>(
64 &self,
65 config: &dyn PropertyConfig<K, V>,
66 ) -> Option<Box<V>> {
67 match self
68 .manager
69 .get_property_value(RawPropertyConfig::as_trait_ref(config))
70 {
71 Some(v) => match v.as_ref().as_any_ref().downcast_ref::<V>() {
72 Some(v) => Some(Box::new(v.clone())),
73 None => None,
74 },
75 None => None,
76 }
77 }
78}
79
80pub struct ConfigurationSources;
82
83impl ConfigurationSources {
84 pub fn new_config_builder() -> Box<dyn ConfigurationSourceConfigBuilder> {
85 Box::new(DefaultConfigurationSourceConfigBuilder::new())
86 }
87
88 pub fn new_config(name: &str) -> Box<dyn ConfigurationSourceConfig> {
89 DefaultConfigurationSourceConfigBuilder::new()
90 .set_name(name)
91 .build()
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use crate::tests::init_log;
99 use lang_extension::convert::*;
100 use std::any::*;
101 use std::collections::HashMap;
102 use std::sync::atomic::*;
103 use std::sync::*;
104
105 fn new_source(
106 config: Box<dyn ConfigurationSourceConfig>,
107 property_provider: PropertyProvider,
108 ) -> Box<dyn ConfigurationSource> {
109 ConfigurationSource::to_boxed(DefaultConfigurationSource::new(config, property_provider))
110 }
111
112 #[test]
113 fn new_property_config() {
114 let c =
115 DefaultTypeConverter::<String, i32>::new(Box::new(move |v| match v.parse::<i32>() {
116 Ok(v) => Ok(Box::new(v)),
117 Err(err) => Err(Box::new(err)),
118 }));
119 let f = DefaultValueFilter::new(Box::new(move |v| {
120 if *v > 10 {
121 Some(Box::new(*v + 1))
122 } else if *v >= 0 {
123 Some(v)
124 } else {
125 None
126 }
127 }));
128
129 let mut builder = ConfigurationProperties::new_config_builder::<String, i32>();
130 let config = builder
131 .set_key(Box::new("test".to_string()))
132 .set_default_value(Box::new(0))
133 .set_value_filter(ValueFilter::to_boxed(f))
134 .add_value_converter(RawTypeConverter::to_boxed(c))
135 .build();
136 println!("property config: {:?}", config);
137 assert_eq!("test".to_string(), *config.get_key());
138 assert_eq!(0.type_id(), config.get_value_type());
139 assert_eq!(Some(Box::new(0)), config.get_default_value());
140 assert_eq!(
141 Some(Value::to_boxed(12)),
142 config
143 .get_value_filter()
144 .unwrap()
145 .filter_raw(Value::to_boxed(11))
146 );
147 assert_eq!(
148 Ok(Value::to_boxed(10)),
149 config
150 .get_value_converters()
151 .get(0)
152 .unwrap()
153 .convert_raw(Value::as_trait_ref(&"10".to_string()))
154 );
155 }
156
157 #[test]
158 fn new_source_config() {
159 let mut builder = ConfigurationSources::new_config_builder();
160 let config = builder.set_name("test").build();
161 println!("source config: {:?}", config);
162 assert_eq!("test", config.get_name());
163 }
164
165 #[test]
166 fn new_source_test() {
167 init_log();
168
169 let mut builder = ConfigurationSources::new_config_builder();
170 let config = builder.set_name("test").build();
171 let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
172 if k.equals("10".to_string().as_any_ref()) {
173 Some(Value::to_boxed(10))
174 } else {
175 None
176 }
177 }));
178 let source = new_source(config, property_provider);
179 println!("configuration source: {:?}", source);
180 assert_eq!("test", source.get_config().get_name());
181 let property_config = ConfigurationProperties::new_config_builder::<String, i32>()
182 .set_key(Box::new("10".to_string()))
183 .build();
184 assert_eq!(
185 Some(Value::to_boxed(10)),
186 source.get_property_value(RawPropertyConfig::as_trait_ref(property_config.as_ref()))
187 );
188 let property_config = ConfigurationProperties::new_config_builder::<String, i32>()
189 .set_key(Box::new("11".to_string()))
190 .build();
191 assert_eq!(
192 None,
193 source.get_property_value(RawPropertyConfig::as_trait_ref(property_config.as_ref()))
194 );
195 }
196
197 #[test]
198 fn new_manager_config() {
199 let mut builder = ConfigurationSources::new_config_builder();
200 let config = builder.set_name("test").build();
201 let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
202 if k.equals("10".to_string().as_any_ref()) {
203 Some(Value::to_boxed(10))
204 } else {
205 None
206 }
207 }));
208 let source = new_source(config, property_provider);
209 let mut builder = ConfigurationManagers::new_config_builder();
210 let config = builder
211 .set_name("test-manager")
212 .add_source(1, source)
213 .build();
214 println!("manager config: {:?}", config);
215 assert_eq!("test-manager", config.get_name());
216 assert_eq!(1, config.get_sources().len());
217 let changed = Arc::new(AtomicBool::default());
218 let changed_clone = changed.clone();
219 let action: Box<dyn Fn()> = Box::new(move || {
220 changed_clone.swap(true, Ordering::Relaxed);
221 println!("OK");
222 });
223 config.get_task_executor()(&action);
224 assert_eq!(true, changed.fetch_and(true, Ordering::Relaxed));
225 }
226
227 #[test]
228 fn new_manager() {
229 init_log();
230
231 let mut builder = ConfigurationSources::new_config_builder();
232 let source_config = builder.set_name("test").build();
233 let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
234 if k.equals("10".to_string().as_any_ref()) {
235 Some(Value::to_boxed(10))
236 } else {
237 None
238 }
239 }));
240 let source = new_source(source_config, property_provider);
241 let mut builder = ConfigurationManagers::new_config_builder();
242 let config = builder
243 .set_name("test-manager")
244 .add_source(1, source)
245 .build();
246 let manager = ConfigurationManagers::new_manager(config);
247 println!("manager: {:?}", manager);
248 assert_eq!("test-manager", manager.get_config().get_name());
249
250 let c =
251 DefaultTypeConverter::<String, i32>::new(Box::new(move |v| match v.parse::<i32>() {
252 Ok(v) => Ok(Box::new(v)),
253 Err(err) => Err(Box::new(err)),
254 }));
255 let f = DefaultValueFilter::new(Box::new(move |v| {
256 if *v > 10 {
257 Some(Box::new(*v + 1))
258 } else if *v >= 0 {
259 Some(v)
260 } else {
261 None
262 }
263 }));
264 let mut builder = ConfigurationProperties::new_config_builder::<String, i32>();
265 let property_config = builder
266 .set_key(Box::new("10".to_string()))
267 .set_default_value(Box::new(0))
268 .set_value_filter(ValueFilter::to_boxed(f))
269 .add_value_converter(RawTypeConverter::to_boxed(c))
270 .build();
271 let property =
272 manager.get_property(RawPropertyConfig::as_trait_ref(property_config.as_ref()));
273 assert_eq!(Some(Value::to_boxed(10)), property.get_raw_value());
274
275 let value =
276 manager.get_property_value(RawPropertyConfig::as_trait_ref(property_config.as_ref()));
277 assert_eq!(Some(Value::to_boxed(10)), value);
278 }
279
280 #[test]
281 fn properties() {
282 init_log();
283
284 let mut builder = ConfigurationSources::new_config_builder();
285 let source_config = builder.set_name("test").build();
286 let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
287 if k.equals("key_ok".to_string().as_any_ref()) {
288 Some(Value::to_boxed(20))
289 } else {
290 None
291 }
292 }));
293 let source = new_source(source_config, property_provider);
294
295 let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
296 memory_map
297 .write()
298 .unwrap()
299 .insert("key_ok".to_string(), "10".to_string());
300 memory_map
301 .write()
302 .unwrap()
303 .insert("key_error".to_string(), "error".to_string());
304 let memory_map2 = memory_map.clone();
305 let source_config2 = ConfigurationSources::new_config_builder()
306 .set_name("dynamic_source")
307 .build();
308 let source2 = DefaultConfigurationSource::new(
309 source_config2,
310 Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
311 match o.as_any_ref().downcast_ref::<String>() {
312 Some(k) => memory_map2
313 .read()
314 .unwrap()
315 .get(k)
316 .map(|v| Value::clone_boxed(v)),
317 None => None,
318 }
319 })),
320 );
321
322 let mut builder = ConfigurationManagers::new_config_builder();
323 let config = builder
324 .set_name("test-manager")
325 .add_source(1, source)
326 .add_source(2, Box::new(source2.clone()))
327 .build();
328 let manager = ConfigurationManagers::new_manager(config);
329 let properties = ConfigurationProperties::new(manager);
330 println!("properties: {:?}", properties);
331
332 let c =
333 DefaultTypeConverter::<String, i32>::new(Box::new(move |v| match v.parse::<i32>() {
334 Ok(v) => Ok(Box::new(v)),
335 Err(err) => Err(Box::new(err)),
336 }));
337 let f = DefaultValueFilter::new(Box::new(move |v| {
338 if *v > 10 {
339 Some(Box::new(*v + 1))
340 } else if *v >= 0 {
341 Some(v)
342 } else {
343 None
344 }
345 }));
346 let mut builder = ConfigurationProperties::new_config_builder::<String, i32>();
347 let property_config = builder
348 .set_key(Box::new("key_ok".to_string()))
349 .set_default_value(Box::new(0))
350 .set_value_filter(ValueFilter::clone_boxed(&f))
351 .add_value_converter(RawTypeConverter::clone_boxed(&c))
352 .set_doc("for test")
353 .build();
354 let property = properties.get_property(property_config.as_ref());
355 let value = properties.get_property_value(property_config.as_ref());
356 assert_eq!(Some(Box::new(10)), property.get_value());
357 assert_eq!(Some(Box::new(10)), value);
358
359 let mut builder = ConfigurationProperties::new_config_builder::<String, i32>();
360 let property_config2 = builder
361 .set_key(Box::new("key_error".to_string()))
362 .set_value_filter(ValueFilter::to_boxed(f))
363 .add_value_converter(RawTypeConverter::to_boxed(c))
364 .build();
365 let property2 = properties.get_property(property_config2.as_ref());
366 let value2 = properties.get_property_value(property_config2.as_ref());
367 assert_eq!(None, property2.get_value());
368 assert_eq!(None, value2);
369
370 let changed = Arc::new(AtomicBool::new(false));
371 let changed_clone = changed.clone();
372 property.add_change_listener(Arc::new(Box::new(move |e| {
373 println!("changed: {:?}", e);
374 changed_clone.swap(true, Ordering::Relaxed);
375 })));
376 memory_map
377 .write()
378 .unwrap()
379 .insert("key_ok".to_string(), "12".to_string());
380 source2.raise_change_event();
381 assert_eq!(Some(Box::new(13)), property.get_value());
382 assert!(changed.fetch_and(true, Ordering::Relaxed));
383
384 memory_map.write().unwrap().remove(&"key_ok".to_string());
385 source2.raise_change_event();
386 assert_eq!(Some(Box::new(21)), property.get_value());
387 }
388}