1use std::collections::HashMap;
2use std::fmt;
3use std::sync::{Arc, RwLock};
4use std::time::*;
5
6use lang_extension::any::*;
7use lang_extension::fmt::*;
8
9use super::*;
10use crate::property::default::*;
11
12#[derive(Clone)]
13pub struct DefaultConfigurationManagerConfig {
14 name: String,
15 sources: Arc<Vec<Box<dyn ConfigurationSource>>>,
16 task_executor: ConsumerRef<Box<dyn Fn()>>,
17}
18
19impl PartialEq for DefaultConfigurationManagerConfig {
20 fn eq(&self, other: &Self) -> bool {
21 self.sources
22 .as_ref()
23 .reference_equals(other.sources.as_ref())
24 }
25}
26
27impl Eq for DefaultConfigurationManagerConfig {}
28
29impl fmt::Debug for DefaultConfigurationManagerConfig {
30 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31 write!(
32 f,
33 "{} {{\n\tname: {},\n\tsources: {:?},\n\ttask_executor:\n\t{}\n}}",
34 self.type_name(),
35 self.name,
36 self.sources,
37 self.task_executor.as_ref().to_instance_string()
38 )
39 }
40}
41
42unsafe impl Sync for DefaultConfigurationManagerConfig {}
43unsafe impl Send for DefaultConfigurationManagerConfig {}
44
45impl ConfigurationManagerConfig for DefaultConfigurationManagerConfig {
46 fn get_name(&self) -> &str {
47 self.name.as_str()
48 }
49
50 fn get_sources(&self) -> &Vec<Box<dyn ConfigurationSource>> {
51 self.sources.as_ref()
52 }
53
54 fn get_task_executor(&self) -> &dyn Fn(&Box<dyn Fn()>) {
55 self.task_executor.as_ref().as_ref()
56 }
57
58 as_boxed!(impl ConfigurationManagerConfig);
59}
60
61pub struct DefaultConfigurationManagerConfigBuilder {
62 name: Option<String>,
63 sources: HashMap<i32, Box<dyn ConfigurationSource>>,
64 task_executor: Option<ConsumerRef<Box<dyn Fn()>>>,
65}
66
67impl DefaultConfigurationManagerConfigBuilder {
68 pub fn new() -> Self {
69 Self {
70 name: None,
71 sources: HashMap::new(),
72 task_executor: Some(arc_boxed!(Self::execute)),
73 }
74 }
75
76 fn execute(action: &Box<dyn Fn()>) {
77 action()
78 }
79}
80
81impl ConfigurationManagerConfigBuilder for DefaultConfigurationManagerConfigBuilder {
82 fn set_name(&mut self, name: &str) -> &mut dyn ConfigurationManagerConfigBuilder {
83 self.name = Some(name.to_owned());
84 self
85 }
86
87 fn add_source(
88 &mut self,
89 priority: i32,
90 source: Box<dyn ConfigurationSource>,
91 ) -> &mut dyn ConfigurationManagerConfigBuilder {
92 if self.sources.contains_key(&priority) {
93 panic!("a source with priority {} exists", priority);
94 }
95 self.sources.insert(priority, source);
96 self
97 }
98
99 fn add_sources(
100 &mut self,
101 sources: HashMap<i32, Box<dyn ConfigurationSource>>,
102 ) -> &mut dyn ConfigurationManagerConfigBuilder {
103 for (k, v) in sources.into_iter() {
104 self.sources.insert(k, v);
105 }
106 self
107 }
108
109 fn set_task_executor(
110 &mut self,
111 task_executor: ConsumerRef<Box<dyn Fn()>>,
112 ) -> &mut dyn ConfigurationManagerConfigBuilder {
113 self.task_executor = Some(task_executor);
114 self
115 }
116
117 fn build(&self) -> Box<dyn ConfigurationManagerConfig> {
118 Box::new(DefaultConfigurationManagerConfig {
119 name: self.name.as_ref().unwrap().to_owned(),
120 sources: Arc::new({
121 let mut keys: Vec<_> = self
122 .sources
123 .keys()
124 .collect::<Vec<&i32>>()
125 .iter()
126 .map(|v| **v)
127 .collect();
128 keys.sort();
129 keys.reverse();
130 let mut sources = Vec::new();
131 for k in keys {
132 sources.push(ConfigurationSource::clone_boxed(
133 self.sources.get(&k).unwrap().as_ref(),
134 ));
135 }
136 sources
137 }),
138 task_executor: self.task_executor.as_ref().unwrap().clone(),
139 })
140 }
141}
142
143#[derive(Clone)]
144pub struct DefaultConfigurationManager {
145 config: Arc<Box<dyn ConfigurationManagerConfig>>,
146 properties: Arc<RwLock<HashMap<ImmutableKey, Box<dyn RawProperty>>>>,
147 change_listeners: Arc<RwLock<Vec<RawPropertyChangeListener>>>,
148}
149
150impl DefaultConfigurationManager {
151 pub fn new(config: Box<dyn ConfigurationManagerConfig>) -> DefaultConfigurationManager {
152 let manager = DefaultConfigurationManager {
153 config: Arc::new(config),
154 properties: Arc::new(RwLock::new(HashMap::new())),
155 change_listeners: Arc::new(RwLock::new(Vec::new())),
156 };
157 let clone = manager.clone();
158 let source_change_listener: ConfigurationSourceChangeListener =
159 Arc::new(Box::new(move |e| clone.on_source_change(e)));
160 for s in manager.config.get_sources() {
161 s.add_change_listener(source_change_listener.clone());
162 }
163 manager
164 }
165
166 fn on_source_change(&self, _event: &dyn ConfigurationSourceChangeEvent) {
167 let properties = self.properties.read().unwrap();
168 for property in properties.values() {
169 let (new_value, source) = self.do_get_property_value(property.get_raw_config());
170 let old_value = property.get_raw_value();
171 if new_value != old_value {
172 if property.get_raw_config().is_static() {
173 warn!(
174 "ignore dynamic change for static property, \
175 dynamic change for static property will be applied when app restart, \
176 static:\n\t{:?},\n\tdynamic:\n\t{:?},\n\tproperty: {:?}",
177 old_value,
178 new_value,
179 property.get_raw_config().get_raw_key()
180 );
181
182 continue;
183 }
184
185 if new_value.is_none() && property.get_raw_config().is_required() {
186 error!(
187 "ignore dynamic change for required property, \
188 required property cannot be changed to None, \
189 now keep its current value, you should fix the invalid change at once, \
190 or app will panic when next app restart, property:\n\t{:?}",
191 property.get_raw_config().get_raw_key()
192 );
193
194 continue;
195 }
196
197 let pe = DefaultRawPropertyChangeEvent::new(
198 Arc::new(RawProperty::clone_boxed(property.as_ref())),
199 old_value.map(|v| ImmutableValue::wrap(v)),
200 new_value.as_ref().map(|v| ImmutableValue::wrap(v.clone())),
201 SystemTime::now()
202 .duration_since(UNIX_EPOCH)
203 .unwrap()
204 .as_millis(),
205 );
206 let raw_property = property.as_ref();
207 let default_raw_property = raw_property
208 .as_any_ref()
209 .downcast_ref::<DefaultRawProperty>()
210 .unwrap()
211 .clone();
212 default_raw_property.update(new_value, source);
213 let pe_clone = pe.clone();
214 let mut action: Box<dyn Fn()> =
215 Box::new(move || default_raw_property.raise_change_event(&pe_clone));
216 self.config.get_task_executor()(&action);
217 let manager = self.clone();
218 action = Box::new(move || manager.raise_change_event(&pe));
219 self.config.get_task_executor()(&action);
220 }
221 }
222 }
223
224 fn do_get_property_value(
225 &self,
226 config: &dyn RawPropertyConfig,
227 ) -> (Option<Box<dyn Value>>, Option<Box<dyn ConfigurationSource>>) {
228 for source in self.config.get_sources().iter() {
229 let value = source.get_property_value(config);
230 let new_value = self.apply_value_filter(config, source.get_config().get_name(), value);
231 if new_value.is_some() {
232 return (new_value, Some(source.clone()));
233 }
234 }
235
236 (config.get_raw_default_value(), None)
237 }
238
239 fn apply_value_filter(
240 &self,
241 config: &dyn RawPropertyConfig,
242 source: &str,
243 value: Option<Box<dyn Value>>,
244 ) -> Option<Box<dyn Value>> {
245 if value.is_none() {
246 return None;
247 }
248
249 if config.get_value_filter().is_none() {
250 return value;
251 }
252
253 let new_value = config
254 .get_value_filter()
255 .unwrap()
256 .filter_raw(value.clone().unwrap());
257 if new_value.is_some() {
258 if new_value != value {
259 warn!(
260 "property value in config source {:?}\n\tchanged by property filter, \
261 from: {:?},\n\tto: {:?},\n\tproperty: {:?}",
262 source,
263 value.as_ref().unwrap(),
264 new_value.as_ref().unwrap(),
265 config
266 );
267 }
268
269 info!(
270 "use property value in config source {:?},\n\tvalue: {:?},\n\tproperty: {:?}",
271 source,
272 new_value.as_ref().unwrap(),
273 config.get_raw_key()
274 );
275 return new_value;
276 } else {
277 error!(
278 "property value in source {:?}\n\tignored by property filter, probably not valid, \
279 value: {:?},\n\tproperty: {:?}",
280 source,
281 value.unwrap(),
282 config
283 );
284 None
285 }
286 }
287
288 fn check_required(&self, config: &dyn RawPropertyConfig, value: Option<&Box<dyn Value>>) {
289 if config.is_required() && value.is_none() {
290 panic!(
291 "None is got for required property, forgot to config it?\n\
292 Property: {:?}",
293 config
294 );
295 }
296 }
297
298 fn raise_change_event(&self, event: &dyn RawPropertyChangeEvent) {
299 let listeners = self.change_listeners.read().unwrap();
300 for listener in listeners.iter() {
301 listener(event);
302 }
303 }
304}
305
306impl ConfigurationManager for DefaultConfigurationManager {
307 fn get_config(&self) -> &dyn ConfigurationManagerConfig {
308 self.config.as_ref().as_ref()
309 }
310
311 fn get_properties(&self) -> Vec<Box<dyn RawProperty>> {
312 let lock = self.properties.read().unwrap();
313 let mut properties = Vec::<Box<dyn RawProperty>>::new();
314 for (_, p) in lock.iter() {
315 properties.push(p.clone());
316 }
317
318 properties
319 }
320
321 fn get_property(&self, config: &dyn RawPropertyConfig) -> Box<dyn RawProperty> {
322 let key = ImmutableKey::wrap(config.get_raw_key());
323 let mut opt_property = self
324 .properties
325 .read()
326 .unwrap()
327 .get(&key)
328 .map(|p| RawProperty::clone_boxed(p.as_ref()));
329 if opt_property.is_none() {
330 let mut map = self.properties.write().unwrap();
331 opt_property = match map.get(&key) {
332 Some(p) => Some(RawProperty::clone_boxed(p.as_ref())),
333 None => {
334 let (value, source) = self.do_get_property_value(config);
335 self.check_required(config, value.as_ref());
336 let property = DefaultRawProperty::new(config);
337 property.update(value, source);
338 map.insert(key.clone(), RawProperty::clone_boxed(&property));
339 Some(Box::new(property))
340 }
341 };
342 }
343
344 let property = opt_property.unwrap();
345 if !config.equals(property.get_raw_config().as_any_ref()) {
346 panic!(
347 "make sure using same config for property: {:?},\n\tprevious config: {:?},\n\t\
348 current config: {:?}",
349 config.get_raw_key(),
350 property.get_raw_config(),
351 config
352 );
353 }
354
355 property
356 }
357
358 fn get_property_value(&self, config: &dyn RawPropertyConfig) -> Option<Box<dyn Value>> {
359 let (value, _) = self.do_get_property_value(config);
360 self.check_required(config, value.as_ref());
361 value
362 }
363
364 fn add_raw_change_listener(&self, listener: RawPropertyChangeListener) {
365 self.change_listeners.write().unwrap().push(listener);
366 }
367
368 as_boxed!(impl ConfigurationManager);
369}
370
371impl PartialEq for DefaultConfigurationManager {
372 fn eq(&self, other: &Self) -> bool {
373 self.properties
374 .as_ref()
375 .reference_equals(other.properties.as_ref())
376 }
377}
378
379impl Eq for DefaultConfigurationManager {}
380
381impl fmt::Debug for DefaultConfigurationManager {
382 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383 write!(
384 f,
385 "{} {{\n\tconfig: {:?},\n\tproperties: {:?}\n}}",
386 self.type_name(),
387 self.get_config(),
388 self.get_properties()
389 )
390 }
391}
392
393unsafe impl Sync for DefaultConfigurationManager {}
394unsafe impl Send for DefaultConfigurationManager {}
395
396#[cfg(test)]
397mod test {
398 use super::*;
399 use crate::source::default::*;
400 use crate::tests::init_log;
401 use lang_extension::convert::*;
402 use std::sync::atomic::*;
403 use std::thread;
404
405 fn new_source() -> DefaultConfigurationSource {
406 DefaultConfigurationSource::new(
407 DefaultConfigurationSourceConfigBuilder::new()
408 .set_name("test")
409 .build(),
410 Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
411 let x = if Key::as_trait_ref(&"key_ok".to_string()).equals(o.as_any_ref()) {
412 Some(Value::to_boxed("10".to_string()))
413 } else if Key::as_trait_ref(&"key_error".to_string()).equals(o.as_any_ref()) {
414 Some(Value::to_boxed("error".to_string()))
415 } else {
416 None
417 };
418 println!("raw_value: {:?}", x);
419 x
420 })),
421 )
422 }
423
424 fn new_value_converter() -> DefaultTypeConverter<String, i32> {
425 DefaultTypeConverter::<String, i32>::new(Box::new(|s| match s.parse::<i32>() {
426 Ok(v) => {
427 println!("parse value: {}", v);
428 Ok(Box::new(v))
429 }
430 Err(e) => {
431 println!("parse error: {}", e);
432 Err(Box::new(e.to_string()))
433 }
434 }))
435 }
436
437 fn new_property_config(
438 value_converter: &dyn TypeConverter<String, i32>,
439 ) -> Box<dyn PropertyConfig<String, i32>> {
440 DefaultPropertyConfigBuilder::<String, i32>::new()
441 .set_key(Box::new("key_ok".to_string()))
442 .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
443 .set_value_filter(Box::new(DefaultValueFilter::<i32>::new(Box::new(|v| {
444 if *v == 10 { Some(Box::new(5)) } else { Some(v) }
445 }))))
446 .set_doc("for test")
447 .build()
448 }
449
450 fn new_property_config2(
451 value_converter: &dyn TypeConverter<String, i32>,
452 ) -> Box<dyn PropertyConfig<String, i32>> {
453 DefaultPropertyConfigBuilder::<String, i32>::new()
454 .set_key(Box::new("key_error".to_string()))
455 .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
456 .build()
457 }
458
459 fn new_property_config3(
460 key: &str,
461 value_converter: &dyn TypeConverter<String, i32>,
462 ) -> Box<dyn PropertyConfig<String, i32>> {
463 DefaultPropertyConfigBuilder::<String, i32>::new()
464 .set_key(Box::new(key.to_string()))
465 .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
466 .set_required(true)
467 .build()
468 }
469
470 fn new_property_config4(
471 key: &str,
472 value_converter: &dyn TypeConverter<String, i32>,
473 ) -> Box<dyn PropertyConfig<String, i32>> {
474 DefaultPropertyConfigBuilder::<String, i32>::new()
475 .set_key(Box::new(key.to_string()))
476 .add_value_converter(RawTypeConverter::clone_boxed(value_converter))
477 .set_static(true)
478 .build()
479 }
480
481 #[test]
482 fn manager_config_test() {
483 let source = new_source();
484 let config = DefaultConfigurationManagerConfigBuilder::new()
485 .set_name("test")
486 .add_source(1, Box::new(source))
487 .build();
488 println!("manager config: {:?}", config);
489
490 assert_eq!("test", config.get_name());
491
492 assert_eq!(1, config.get_sources().len());
493
494 let action: Box<dyn Fn()> = Box::new(|| {
495 println!("task executed");
496 });
497 config.get_task_executor()(&action);
498
499 assert_eq!(&config, &config.clone());
500 }
501
502 #[test]
503 fn manager_test() {
504 init_log();
505
506 let source = ConfigurationSource::to_boxed(new_source());
507 let config = DefaultConfigurationManagerConfigBuilder::new()
508 .set_name("test")
509 .add_source(1, source.clone())
510 .build();
511 let manager = DefaultConfigurationManager::new(config);
512 println!("manager: {:?}", manager);
513 assert_eq!("test", manager.get_config().get_name());
514
515 let value_converter = new_value_converter();
516 let config = new_property_config(&value_converter);
517 let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
518 assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
519 assert_eq!(Some(source.clone()), property.get_source());
520 let config2 = new_property_config2(&value_converter);
521 let property2 = manager.get_property(RawPropertyConfig::as_trait_ref(config2.as_ref()));
522 assert_eq!(None, property2.get_raw_value());
523 assert_eq!(None, property2.get_source());
524
525 let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
526 assert_eq!(Some(Value::to_boxed(5)), value);
527 let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
528 assert_eq!(None, value2);
529
530 let manager_clone = manager.clone();
531 let config_clone = config.clone();
532 let handle = thread::spawn(move || {
533 let property =
534 manager_clone.get_property(RawPropertyConfig::as_trait_ref(config_clone.as_ref()));
535 assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
536 });
537 handle.join().unwrap();
538 }
539
540 #[test]
541 fn dynamic_test() {
542 init_log();
543
544 let mut builder = DefaultConfigurationSourceConfigBuilder::new();
545 let source_config = builder.set_name("test").build();
546 let property_provider: PropertyProvider = Arc::new(Box::new(|k| {
547 if k.equals("key_ok".to_string().as_any_ref()) {
548 Some(Value::to_boxed(20))
549 } else {
550 None
551 }
552 }));
553 let source0: Box<dyn ConfigurationSource> = Box::new(DefaultConfigurationSource::new(
554 source_config,
555 property_provider,
556 ));
557
558 let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
559 memory_map
560 .write()
561 .unwrap()
562 .insert("key_ok".to_string(), "10".to_string());
563 memory_map
564 .write()
565 .unwrap()
566 .insert("key_error".to_string(), "error".to_string());
567 let memory_map2 = memory_map.clone();
568 let source = DefaultConfigurationSource::new(
569 DefaultConfigurationSourceConfigBuilder::new()
570 .set_name("test")
571 .build(),
572 Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
573 match o.as_any_ref().downcast_ref::<String>() {
574 Some(k) => memory_map2
575 .read()
576 .unwrap()
577 .get(k)
578 .map(|v| Value::clone_boxed(v)),
579 None => None,
580 }
581 })),
582 );
583 let source_boxed = ConfigurationSource::clone_boxed(&source);
584 let config = DefaultConfigurationManagerConfigBuilder::new()
585 .set_name("test")
586 .add_source(0, source0.clone())
587 .add_source(1, source_boxed.clone())
588 .build();
589 let manager = DefaultConfigurationManager::new(config);
590
591 let value_converter = new_value_converter();
592 let config = new_property_config(&value_converter);
593 let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
594 assert_eq!(Some(Value::to_boxed(5)), property.get_raw_value());
595 assert_eq!(Some(source_boxed.clone()), property.get_source());
596 let config2 = new_property_config2(&value_converter);
597 let property2 = manager.get_property(RawPropertyConfig::as_trait_ref(config2.as_ref()));
598 assert_eq!(None, property2.get_raw_value());
599 assert_eq!(None, property2.get_source());
600
601 let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
602 assert_eq!(Some(Value::to_boxed(5)), value);
603 let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
604 assert_eq!(None, value2);
605
606 memory_map
607 .write()
608 .unwrap()
609 .insert("key_ok".to_string(), "11".to_string());
610 source.raise_change_event();
611 assert_eq!(Some(Value::to_boxed(11)), property.get_raw_value());
612 let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
613 assert_eq!(None, value2);
614
615 let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
616 assert_eq!(Some(Value::to_boxed(11)), value);
617 let value2 = manager.get_property_value(RawPropertyConfig::as_trait_ref(config2.as_ref()));
618 assert_eq!(None, value2);
619
620 let property = DefaultProperty::<String, i32>::from_raw(property.as_ref());
621 let changed = Arc::new(AtomicBool::new(false));
622 let changed_clone = changed.clone();
623 property.add_change_listener(Arc::new(Box::new(move |e| {
624 println!("changed: {:?}", e);
625 changed_clone.swap(true, Ordering::Relaxed);
626 })));
627 memory_map
628 .write()
629 .unwrap()
630 .insert("key_ok".to_string(), "12".to_string());
631 source.raise_change_event();
632 assert_eq!(Some(Box::new(12)), property.get_value());
633 assert_eq!(Some(source_boxed.clone()), property.get_source());
634 assert_eq!(Some(Value::to_boxed(12)), property.get_raw_value());
635 let value = manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
636 assert_eq!(Some(Value::to_boxed(12)), value);
637 assert!(changed.fetch_and(true, Ordering::Relaxed));
638
639 memory_map.write().unwrap().remove(&"key_ok".to_string());
640 source.raise_change_event();
641 assert_eq!(Some(Box::new(20)), property.get_value());
642 assert_eq!(Some(source0.clone()), property.get_source());
643 memory_map
644 .write()
645 .unwrap()
646 .insert("key_error".to_string(), "1".to_string());
647 source.raise_change_event();
648 assert_eq!(Some(Value::to_boxed(1)), property2.get_raw_value());
649 }
650
651 #[test]
652 fn required_property() {
653 init_log();
654
655 let source = new_source();
656 let config = DefaultConfigurationManagerConfigBuilder::new()
657 .set_name("test")
658 .add_source(1, Box::new(source))
659 .build();
660 let manager = DefaultConfigurationManager::new(config);
661
662 let value_converter = new_value_converter();
663 let config = new_property_config3("key_ok", &value_converter);
664 manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
665 manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
666 }
667
668 #[should_panic]
669 #[test]
670 fn required_property2() {
671 init_log();
672
673 let source = new_source();
674 let config = DefaultConfigurationManagerConfigBuilder::new()
675 .set_name("test")
676 .add_source(1, Box::new(source))
677 .build();
678 let manager = DefaultConfigurationManager::new(config);
679
680 let value_converter = new_value_converter();
681 let config = new_property_config3("key_none", &value_converter);
682 manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
683 }
684
685 #[should_panic]
686 #[test]
687 fn required_property3() {
688 init_log();
689
690 let source = new_source();
691 let config = DefaultConfigurationManagerConfigBuilder::new()
692 .set_name("test")
693 .add_source(1, Box::new(source))
694 .build();
695 let manager = DefaultConfigurationManager::new(config);
696
697 let value_converter = new_value_converter();
698 let config = new_property_config3("key_none", &value_converter);
699 manager.get_property_value(RawPropertyConfig::as_trait_ref(config.as_ref()));
700 }
701
702 #[test]
703 fn required_property_dynamic() {
704 init_log();
705
706 let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
707 memory_map
708 .write()
709 .unwrap()
710 .insert("key_ok".to_string(), "20".to_string());
711 memory_map
712 .write()
713 .unwrap()
714 .insert("key_required".to_string(), "30".to_string());
715 let memory_map2 = memory_map.clone();
716 let source = DefaultConfigurationSource::new(
717 DefaultConfigurationSourceConfigBuilder::new()
718 .set_name("test")
719 .build(),
720 Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
721 match o.as_any_ref().downcast_ref::<String>() {
722 Some(k) => memory_map2
723 .read()
724 .unwrap()
725 .get(k)
726 .map(|v| Value::clone_boxed(v)),
727 None => None,
728 }
729 })),
730 );
731 let config = DefaultConfigurationManagerConfigBuilder::new()
732 .set_name("test")
733 .add_source(1, Box::new(source.clone()))
734 .build();
735 let manager = DefaultConfigurationManager::new(config);
736
737 let value_converter = new_value_converter();
738 let config = new_property_config(&value_converter);
739 let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
740 assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
741
742 memory_map.write().unwrap().remove(&"key_ok".to_string());
743 source.raise_change_event();
744 assert_eq!(None, property.get_raw_value());
745
746 let config = new_property_config3("key_required", &value_converter);
747 let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
748 assert_eq!(Some(Value::to_boxed(30)), property.get_raw_value());
749
750 memory_map
751 .write()
752 .unwrap()
753 .remove(&"key_required".to_string());
754 source.raise_change_event();
755 assert_eq!(Some(Value::to_boxed(30)), property.get_raw_value());
756 }
757
758 #[test]
759 fn static_property() {
760 init_log();
761
762 let memory_map = Arc::new(RwLock::new(HashMap::<String, String>::new()));
763 memory_map
764 .write()
765 .unwrap()
766 .insert("key_ok".to_string(), "20".to_string());
767 let memory_map2 = memory_map.clone();
768 let source = DefaultConfigurationSource::new(
769 DefaultConfigurationSourceConfigBuilder::new()
770 .set_name("test")
771 .build(),
772 Arc::new(Box::new(move |o| -> Option<Box<dyn Value>> {
773 match o.as_any_ref().downcast_ref::<String>() {
774 Some(k) => memory_map2
775 .read()
776 .unwrap()
777 .get(k)
778 .map(|v| Value::clone_boxed(v)),
779 None => None,
780 }
781 })),
782 );
783 let config = DefaultConfigurationManagerConfigBuilder::new()
784 .set_name("test")
785 .add_source(1, Box::new(source.clone()))
786 .build();
787 let manager = DefaultConfigurationManager::new(config);
788
789 let value_converter = new_value_converter();
790 let config = new_property_config4("key_ok", &value_converter);
791 let property = manager.get_property(RawPropertyConfig::as_trait_ref(config.as_ref()));
792 assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
793
794 memory_map
795 .write()
796 .unwrap()
797 .insert("key_ok".to_string(), "30".to_string());
798 source.raise_change_event();
799 assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
800
801 memory_map.write().unwrap().remove(&"key_ok".to_string());
802 source.raise_change_event();
803 assert_eq!(Some(Value::to_boxed(20)), property.get_raw_value());
804 }
805}