scf_core/source/default/
mod.rs

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