scf_core/source/default/
mod.rs

1use std::sync::{ Arc, RwLock };
2use std::fmt;
3use std::time::*;
4
5use super::*;
6
7pub type PropertyProvider = FunctionRef<dyn Key, Option<Box<dyn Value>>>;
8
9#[derive(PartialEq, Eq, Debug, Clone)]
10pub struct DefaultConfiguratonSourceConfig {
11    name: String
12}
13
14impl ConfigurationSourceConfig for DefaultConfiguratonSourceConfig {
15    fn get_name(&self) -> &str {
16        self.name.as_str()
17    }
18
19as_boxed!(impl ConfigurationSourceConfig);
20}
21
22pub struct DefaultConfigurationSourceConfigBuilder {
23    name: Option<String>
24}
25
26impl DefaultConfigurationSourceConfigBuilder {
27    pub fn new() -> Self {
28        Self {
29            name: None
30        }
31    }
32}
33
34impl ConfigurationSourceConfigBuilder for DefaultConfigurationSourceConfigBuilder {
35    fn set_name(&mut self, name: &str) -> &mut dyn ConfigurationSourceConfigBuilder {
36        self.name = Some(name.to_owned());
37        self
38    }
39
40    fn build(&self) -> Box<dyn ConfigurationSourceConfig> {
41        Box::new(DefaultConfiguratonSourceConfig {
42            name: self.name.as_ref().unwrap().to_owned()
43        })
44    }
45}
46
47#[derive(Clone)]
48pub struct DefaultConfigurationSource {
49    config: Arc<Box<dyn ConfigurationSourceConfig>>,
50    property_provider: Arc<RwLock<PropertyProvider>>,
51    listeners: Arc<RwLock<Vec<ConfigurationSourceChangeListener>>>
52}
53
54impl DefaultConfigurationSource {
55    pub fn new(config: Box<dyn ConfigurationSourceConfig>, property_provider: PropertyProvider)
56        -> DefaultConfigurationSource {
57        DefaultConfigurationSource {
58            config: Arc::new(config),
59            property_provider: Arc::new(RwLock::new(property_provider)),
60            listeners: Arc::new(RwLock::new(Vec::new()))
61        }
62    }
63
64    pub fn raise_change_event(&self) {
65        let event = DefaultConfigurationSourceChangeEvent::new(self,
66            SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis());
67        let lock = self.listeners.read().unwrap();
68        for listener in lock.iter() {
69            listener(&event);
70        }
71    }
72}
73
74impl PartialEq for DefaultConfigurationSource {
75    fn eq(&self, other: &Self) -> bool {
76        self.property_provider.as_ref().reference_equals(other.property_provider.as_ref())
77    }
78}
79
80impl Eq for DefaultConfigurationSource {
81
82}
83
84impl fmt::Debug for DefaultConfigurationSource {
85    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86        write!(f, "{} {{\n\tconfig: {:?}\n}}", self.type_name(), self.config)
87    }
88}
89
90unsafe impl Sync for DefaultConfigurationSource { }
91unsafe impl Send for DefaultConfigurationSource { }
92
93impl ConfigurationSource for DefaultConfigurationSource {
94    fn get_config(&self) -> &dyn ConfigurationSourceConfig {
95        self.config.as_ref().as_ref()
96    }
97
98    fn get_property_value(&self, config: &dyn RawPropertyConfig) -> Option<Box<dyn Value>> {
99        let lock = self.property_provider.read().unwrap();
100        match lock(config.get_raw_key().as_ref()) {
101            Some(v) => {
102                let type_id = v.as_ref().type_id();
103                if type_id == config.get_value_type() {
104                    return Some(v);
105                } else {
106                    for value_converter in config.get_value_converters() {
107                        match value_converter.convert_raw(v.as_ref()) {
108                            Ok(v_t) => {
109                                debug!("property value converted by converter, from {:?} to {:?},\n\t\
110                                    property: {:?},\n\tconverter: {:?}", v.as_ref(), v_t.as_ref(),
111                                    config, value_converter);
112                                return Some(v_t);
113                            },
114                            Err(error) => {
115                                debug!("property value cannot be converted by converter,\n\tvalue: {:?},\n\t\
116                                    property: {:?},\n\tconverter: {:?},\n\tconvert error: {:?}",
117                                    v.as_ref(), config, value_converter, error);
118                            }
119                        } 
120                    }
121                }
122                None
123            },
124            None => None
125        }
126    }
127
128    fn add_change_listener(&self, listener: ConfigurationSourceChangeListener) {
129        let mut lock = self.listeners.write().unwrap();
130        lock.push(listener);
131    }
132
133as_boxed!(impl ConfigurationSource);
134}
135
136#[derive(Eq, Debug, Clone)]
137pub struct DefaultConfigurationSourceChangeEvent {
138    source: Box<dyn ConfigurationSource>,
139    change_time: u128
140}
141
142impl DefaultConfigurationSourceChangeEvent {
143    pub fn new(source: &dyn ConfigurationSource, change_time: u128) -> Self {
144        DefaultConfigurationSourceChangeEvent {
145            source: ConfigurationSource::clone_boxed(source),
146            change_time
147        }
148    }
149}
150
151impl PartialEq for DefaultConfigurationSourceChangeEvent {
152    fn eq(&self, other: &Self) -> bool {
153        self.source.eq(&other.source) && self.change_time == other.change_time
154    }
155}
156
157unsafe impl Sync for DefaultConfigurationSourceChangeEvent { }
158unsafe impl Send for DefaultConfigurationSourceChangeEvent { }
159
160impl ConfigurationSourceChangeEvent for DefaultConfigurationSourceChangeEvent {
161
162    fn get_source(&self) -> &dyn ConfigurationSource {
163        self.source.as_ref()
164    }
165
166    fn get_change_time(&self) -> u128 {
167        self.change_time
168    }
169
170as_boxed!(impl ConfigurationSourceChangeEvent);
171}
172
173#[cfg(test)]
174mod tests {
175    use super::*;
176    use crate::property::default::*;
177    use std::sync::atomic::*;
178    use crate::tests::init_log;
179    use lang_extension::convert::*;
180
181    #[test]
182    fn source_config_test() {
183        let mut builder = DefaultConfigurationSourceConfigBuilder::new();
184        let config = builder.set_name("test").build();
185        println!("config: {:?}", config);
186        assert_eq!("test", config.get_name());
187        assert_eq!(&config, &config.clone());
188    }
189
190    #[test]
191    fn source_test() {
192        init_log();
193
194        let property_provider: PropertyProvider = Arc::new(Box::new(|k|{
195            if k.equals("10".to_string().as_any_ref()) {
196                Some(Value::to_boxed(10))
197            } else if k.equals("11".to_string().as_any_ref()) {
198                Some(Value::to_boxed("11".to_string()))
199            } else if k.equals("xx".to_string().as_any_ref()) {
200                Some(Value::to_boxed("xx"))
201            } else {
202                None
203            }
204        }));
205        let mut builder = DefaultConfigurationSourceConfigBuilder::new();
206        let config = builder.set_name("test").build();
207        let source = DefaultConfigurationSource::new(config.clone(), property_provider);
208        println!("config source: {:?}", source);
209        assert_eq!(&config, &ConfigurationSourceConfig::clone_boxed(source.get_config()));
210
211        let value_converter = DefaultTypeConverter::<String, i32>::new(Box::new(|s|{
212            match s.parse::<i32>() {
213                Ok(v) => {
214                    println!("parse value: {}", v);
215                    Ok(Box::new(v))
216                },
217                Err(e) => {
218                    println!("parse error: {}", e);
219                    Err(Box::new(e.to_string()))
220                }
221            }
222        }));
223        let property_config = DefaultPropertyConfigBuilder::<String, i32>::new()
224            .set_key(Box::new("10".to_string())).build();
225        assert_eq!(Some(Value::to_boxed(10)), source.get_property_value(
226            RawPropertyConfig::as_trait_ref(property_config.as_ref())));
227        let property_config2 = DefaultPropertyConfigBuilder::<String, i32>::new()
228            .set_key(Box::new("1".to_string())).build();
229        assert_eq!(None, source.get_property_value(
230            RawPropertyConfig::as_trait_ref(property_config2.as_ref())));
231        let property_config3 = DefaultPropertyConfigBuilder::<i32, i32>::new()
232            .set_key(Box::new(1)).build();
233        assert_eq!(None, source.get_property_value(
234            RawPropertyConfig::as_trait_ref(property_config3.as_ref())));
235        let property_config4 = DefaultPropertyConfigBuilder::<String, i32>::new()
236            .set_key(Box::new("11".to_string()))
237            .add_value_converter(Box::new(value_converter.clone())).build();
238        assert_eq!(Some(Value::to_boxed(11)), source.get_property_value(
239            RawPropertyConfig::as_trait_ref(property_config4.as_ref())));
240        let property_config5 = DefaultPropertyConfigBuilder::<String, i32>::new()
241            .set_key(Box::new("xx".to_string()))
242            .add_value_converter(Box::new(value_converter.clone())).build();
243        assert_eq!(None, source.get_property_value(
244            RawPropertyConfig::as_trait_ref(property_config5.as_ref())));
245
246        let changed = Arc::new(AtomicBool::default());
247        let changed_clone = changed.clone();
248        source.add_change_listener(Arc::new(Box::new(move |e|{
249            println!("event: {:?}", e);
250            changed_clone.swap(true, Ordering::Relaxed);
251        })));
252
253        source.raise_change_event();
254        assert!(changed.fetch_and(true, Ordering::Relaxed));
255    }
256
257    #[test]
258    fn source_event_test() {
259        let property_provider: PropertyProvider = Arc::new(Box::new(|k|{
260            if k.equals("10".to_string().as_any_ref()) {
261                Some(Value::to_boxed(10))
262            } else {
263                None
264            }
265        }));
266        let mut builder = DefaultConfigurationSourceConfigBuilder::new();
267        let config = builder.set_name("test").build();
268        let source = DefaultConfigurationSource::new(config.clone(), property_provider);
269 
270        let start = SystemTime::now();
271        let since_the_epoch = start.duration_since(UNIX_EPOCH).unwrap();
272        let event = DefaultConfigurationSourceChangeEvent::new(&source, since_the_epoch.as_millis());
273        println!("source event: {:?}", event);
274
275        assert!(source.equals(event.get_source().as_any_ref()));
276        assert_eq!(since_the_epoch.as_millis(), event.get_change_time());
277    }
278}