1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.spi.config.support;
17
18 import java.beans.PropertyChangeListener;
19 import java.beans.PropertyChangeSupport;
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22
23 import javax.annotation.concurrent.ThreadSafe;
24
25 import de.smartics.properties.api.config.domain.ConfigurationProperties;
26 import de.smartics.properties.api.config.domain.ConfigurationValidationException;
27 import de.smartics.properties.api.config.domain.Property;
28 import de.smartics.properties.api.config.domain.ResolvedProperty;
29 import de.smartics.properties.api.config.domain.SerializableConfigurationProperties;
30 import de.smartics.properties.api.config.domain.UnknownPropertyException;
31 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
32 import de.smartics.properties.api.core.domain.PropertiesContext;
33 import de.smartics.properties.api.core.domain.PropertyContext;
34 import de.smartics.properties.api.core.domain.PropertyDescriptor;
35 import de.smartics.properties.api.core.domain.PropertyDescriptorRegistry;
36 import de.smartics.properties.api.core.domain.PropertyExpression;
37 import de.smartics.properties.api.core.domain.PropertyKey;
38 import de.smartics.properties.api.core.domain.PropertyValidationException;
39 import de.smartics.properties.api.core.domain.PropertyValueConversionException;
40 import de.smartics.properties.api.core.domain.PropertyValueResolveException;
41 import de.smartics.properties.spi.config.proxy.PropertyConfigurationObjectBuilder;
42 import de.smartics.properties.spi.config.resolve.PropertyValueResolver;
43 import de.smartics.properties.spi.config.resolve.ResolveConfigurationException;
44 import de.smartics.properties.spi.config.resolve.SimplePropertyValueResolver;
45 import de.smartics.properties.spi.core.context.MandatoryPropertyContext;
46 import de.smartics.properties.spi.core.convert.BeanUtilsPropertyValueConverter;
47 import de.smartics.properties.spi.core.convert.PropertyValueConverter;
48 import de.smartics.properties.spi.core.validate.PropertyValidator;
49 import de.smartics.util.lang.Arguments;
50 import de.smartics.util.lang.BlankArgumentException;
51 import de.smartics.util.lang.NullArgumentException;
52
53
54
55
56
57
58 @ThreadSafe
59 public abstract class AbstractConfigurationProperties implements
60 ConfigurationProperties, ConfigurationPropertiesSpi
61 {
62
63
64
65
66
67
68
69
70
71
72
73 private final ConfigurationKey key;
74
75
76
77
78
79
80 private final PropertyDescriptorRegistry registry;
81
82
83
84
85
86
87 private final PropertyValidator validator = new PropertyValidator();
88
89
90
91
92
93
94 private final PropertyValueConverter converter =
95 new BeanUtilsPropertyValueConverter();
96
97
98
99
100 private transient PropertyValueResolver resolver;
101
102
103
104
105
106
107 private final PropertyChangeSupport support = new PropertyChangeSupport(this);
108
109
110
111
112
113
114
115
116 protected AbstractConfigurationProperties()
117 {
118 this.key = null;
119 this.registry = null;
120 this.resolver = null;
121 }
122
123
124
125
126
127
128
129
130
131 protected AbstractConfigurationProperties(final ConfigurationKey key,
132 final PropertyDescriptorRegistry registry) throws NullArgumentException
133 {
134 Arguments.checkNotNull("key", key);
135 Arguments.checkNotNull("registry", registry);
136
137 this.key = key;
138 this.registry = registry;
139 this.resolver = createResolver();
140 }
141
142
143
144
145
146
147
148 private SimplePropertyValueResolver createResolver()
149 {
150 return new SimplePropertyValueResolver(registry, this);
151 }
152
153
154
155 @Override
156 public final ConfigurationKey getKey()
157 {
158 return key;
159 }
160
161 @Override
162 public final PropertyContext getContext(final PropertyDescriptor descriptor)
163 throws NullPointerException
164 {
165 Arguments.checkNotNull("descriptor", descriptor);
166 return new MandatoryPropertyContext(registry.getContext(descriptor),
167 descriptor);
168 }
169
170 @Override
171 public final PropertiesContext getContext(final Class<?> declaringType)
172 throws NullPointerException
173 {
174 Arguments.checkNotNull("declaringType", declaringType);
175 return registry.getContext(declaringType);
176 }
177
178
179
180
181
182
183 public final PropertyDescriptorRegistry getRegistry()
184 {
185 return registry;
186 }
187
188
189
190 @Override
191 public final Property getProperty(final String key)
192 throws IllegalArgumentException, UnknownPropertyException
193 {
194 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
195 return getProperty(descriptor);
196 }
197
198 @Override
199 public Property getProperty(final String key, final Object defaultValue)
200 throws IllegalArgumentException, UnknownPropertyException
201 {
202 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
203 return getProperty(descriptor, defaultValue);
204 }
205
206 @Override
207 public final Property getProperty(final PropertyKey key)
208 throws IllegalArgumentException, UnknownPropertyException
209 {
210 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
211 return getProperty(descriptor);
212 }
213
214 @Override
215 public final Property getProperty(final PropertyDescriptor descriptor)
216 throws IllegalArgumentException, UnknownPropertyException
217 {
218 return getProperty(descriptor, null);
219 }
220
221 @Override
222 public final <T> T getProperties(final Class<T> propertiesInterface)
223 {
224 return getProperties(propertiesInterface, toSerializable());
225 }
226
227 @Override
228 public final <T> T getProperties(final Class<T> propertiesInterface,
229 final SerializableConfigurationProperties configuration)
230 {
231 final PropertyConfigurationObjectBuilder builder =
232 new PropertyConfigurationObjectBuilder();
233 return builder.build(propertiesInterface, configuration);
234 }
235
236 @Override
237 public final Object getPropertyValue(final String key)
238 throws IllegalArgumentException, UnknownPropertyException,
239 PropertyValidationException
240 {
241 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
242 return getPropertyValue(descriptor, null);
243 }
244
245 @Override
246 public final Object getPropertyValue(final PropertyKey key)
247 throws IllegalArgumentException, UnknownPropertyException,
248 PropertyValidationException
249 {
250 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
251 return getPropertyValue(descriptor, null);
252 }
253
254 @Override
255 public final Object getPropertyValue(final String key,
256 final Object defaultValue) throws NullArgumentException,
257 PropertyValidationException
258 {
259 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
260 return getPropertyValue(descriptor, defaultValue);
261 }
262
263 @Override
264 public final String getPropertyValueAsString(final String key)
265 throws NullArgumentException, PropertyValidationException
266 {
267 return getPropertyValue(key).toString();
268 }
269
270 @Override
271 public final Object getPropertyValue(final PropertyDescriptor descriptor,
272 final Object defaultValue) throws NullPointerException,
273 PropertyValueConversionException, PropertyValidationException,
274 UnknownPropertyException
275 {
276 return getResolvedProperty(descriptor, defaultValue).getResolvedValue();
277 }
278
279 @Override
280 public final String getPropertyValueAsString(final String key,
281 final Object defaultValue) throws NullArgumentException,
282 PropertyValidationException
283 {
284 return getPropertyValue(key, defaultValue).toString();
285 }
286
287 @Override
288 public final Object getPropertyValue(final PropertyDescriptor descriptor)
289 throws NullArgumentException, PropertyValidationException
290 {
291 return getPropertyValue(descriptor, null);
292 }
293
294 @Override
295 public final String getPropertyValueAsString(
296 final PropertyDescriptor descriptor) throws NullArgumentException,
297 PropertyValidationException
298 {
299 return getPropertyValue(descriptor, null).toString();
300 }
301
302 @Override
303 public final String getPropertyValueAsString(
304 final PropertyDescriptor descriptor, final Object defaultValue)
305 throws NullArgumentException, PropertyValidationException
306 {
307 return getPropertyValue(descriptor, defaultValue).toString();
308 }
309
310 @Override
311 public final ResolvedProperty getResolvedProperty(final PropertyKey key,
312 final Object defaultValue) throws IllegalArgumentException,
313 UnknownPropertyException, PropertyValidationException
314 {
315 final PropertyDescriptor descriptor = getPropertyDescriptor(key.toString());
316 return getResolvedProperty(descriptor, defaultValue);
317 }
318
319 @Override
320 public final ResolvedProperty getResolvedProperty(final String key,
321 final Object defaultValue) throws IllegalArgumentException,
322 UnknownPropertyException, PropertyValidationException
323 {
324 final PropertyDescriptor descriptor = getPropertyDescriptor(key);
325 return getResolvedProperty(descriptor, defaultValue);
326 }
327
328
329
330
331
332
333
334
335
336 protected final PropertyDescriptor getPropertyDescriptor(final String key)
337 throws BlankArgumentException, PropertyValidationException
338 {
339 Arguments.checkNotBlank("key", key);
340
341 final PropertyDescriptor descriptor = registry.get(key);
342 if (descriptor == null)
343 {
344 throw new UnknownPropertyException(getKey(), key);
345 }
346 return descriptor;
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360
361 protected final Object resolveAndConvert(final PropertyDescriptor descriptor,
362 final Object defaultValue, final Object value)
363 throws PropertyValueConversionException, PropertyValidationException
364 {
365 Object currentValue = value;
366 if (currentValue == null)
367 {
368 currentValue = descriptor.getDefaultExpression();
369 if (currentValue == null)
370 {
371 currentValue = defaultValue;
372 }
373 }
374
375 if (currentValue instanceof PropertyExpression)
376 {
377 final PropertyExpression expression = (PropertyExpression) currentValue;
378 currentValue = expression.getExpression();
379 }
380
381 if (currentValue instanceof String)
382 {
383 currentValue = resolveValue(descriptor, currentValue);
384 }
385
386 final Object convertedValue = convert(descriptor, currentValue);
387 validator.validate(descriptor, convertedValue);
388
389 return convertedValue;
390 }
391
392 private Object resolveValue(final PropertyDescriptor descriptor,
393 final Object value)
394 {
395 try
396 {
397 final Object resolvedValue = resolver.resolve((String) value);
398 return resolvedValue;
399 }
400 catch (final ResolveConfigurationException e)
401 {
402 throw new PropertyValueResolveException(e, descriptor, e.getExpression());
403 }
404 }
405
406 private Object convert(final PropertyDescriptor descriptor,
407 final Object currentValue)
408 {
409 if (currentValue == null)
410 {
411 return null;
412 }
413
414 return converter.convert(descriptor, currentValue);
415 }
416
417 @Override
418 public final void validate() throws ConfigurationValidationException
419 {
420 validate(false);
421 }
422
423
424
425 @Override
426 public final void addPropertyChangeListener(final PropertyKey name,
427 final PropertyChangeListener listener) throws NullPointerException
428 {
429 support.addPropertyChangeListener(name.toString(), listener);
430 }
431
432 @Override
433 public final void removePropertyChangeListener(final PropertyKey name,
434 final PropertyChangeListener listener) throws NullPointerException
435 {
436 support.removePropertyChangeListener(name.toString(), listener);
437 }
438
439 @Override
440 public final void addPropertyChangeListener(
441 final PropertyChangeListener listener) throws NullPointerException
442 {
443 support.addPropertyChangeListener(listener);
444 }
445
446 @Override
447 public final void removePropertyChangeListener(
448 final PropertyChangeListener listener) throws NullPointerException
449 {
450 support.removePropertyChangeListener(listener);
451 }
452
453
454
455
456
457
458
459
460 protected final void firePropertyChange(final String name,
461 final String oldValue, final String newValue)
462 {
463 support.firePropertyChange(name, oldValue, newValue);
464 }
465
466
467
468
469
470
471
472
473
474
475 private void readObject(final ObjectInputStream in) throws IOException,
476 ClassNotFoundException
477 {
478 in.defaultReadObject();
479
480 this.resolver = createResolver();
481 }
482
483
484
485
486
487
488 @Override
489 public String toString()
490 {
491 final StringBuilder buffer = new StringBuilder();
492
493 buffer.append(key).append(":\n").append("Registry:\n").append(registry);
494
495 return buffer.toString();
496 }
497 }