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.util.ArrayList;
19 import java.util.List;
20
21 import de.smartics.properties.api.config.domain.ConfigurationPropertiesManagement;
22 import de.smartics.properties.api.config.domain.ConfigurationValidationException;
23 import de.smartics.properties.api.config.domain.DescribedProperty;
24 import de.smartics.properties.api.config.domain.Property;
25 import de.smartics.properties.api.config.domain.PropertyCollection;
26 import de.smartics.properties.api.config.domain.PropertyExpressionWithSourceMessageBean;
27 import de.smartics.properties.api.config.domain.PropertyLocation;
28 import de.smartics.properties.api.config.domain.PropertyProvider;
29 import de.smartics.properties.api.config.domain.PropertyStoreAccessor;
30 import de.smartics.properties.api.config.domain.PropertyStoreCode;
31 import de.smartics.properties.api.config.domain.PropertyStoreException;
32 import de.smartics.properties.api.config.domain.PropertyStoreMessageBean;
33 import de.smartics.properties.api.config.domain.PropertyValidationWithSourceException;
34 import de.smartics.properties.api.config.domain.PropertyValidationWithSourceMessageBean;
35 import de.smartics.properties.api.config.domain.PropertyValueConversionWithSourceException;
36 import de.smartics.properties.api.config.domain.PropertyValueResolveWithSourceException;
37 import de.smartics.properties.api.config.domain.PropertyValueWithSourceMessageBean;
38 import de.smartics.properties.api.config.domain.SerializableConfigurationPropertiesManagement;
39 import de.smartics.properties.api.config.domain.UnknownPropertyException;
40 import de.smartics.properties.api.config.domain.ValidatedProperty;
41 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
42 import de.smartics.properties.api.core.app.PropertyRootException;
43 import de.smartics.properties.api.core.domain.DuplicatePropertyDeclarationsException;
44 import de.smartics.properties.api.core.domain.PropertyDescriptor;
45 import de.smartics.properties.api.core.domain.PropertyExpression;
46 import de.smartics.properties.api.core.domain.PropertyExpressionMessageBean;
47 import de.smartics.properties.api.core.domain.PropertyKey;
48 import de.smartics.properties.api.core.domain.PropertyValidationException;
49 import de.smartics.properties.api.core.domain.PropertyValidationMessageBean;
50 import de.smartics.properties.api.core.domain.PropertyValueConversionException;
51 import de.smartics.properties.api.core.domain.PropertyValueResolveException;
52 import de.smartics.properties.api.core.domain.ReadOnlyPropertyException;
53 import de.smartics.properties.api.core.security.SecurityException;
54 import de.smartics.properties.spi.config.validation.ConfigurationValidator;
55
56
57
58
59
60
61
62
63
64
65 public final class ConfigurationPropertiesManagementWithDefaults extends
66 AbstractConfigurationProperties implements
67 SerializableConfigurationPropertiesManagement
68 {
69
70
71
72
73
74
75
76
77
78 private static final long serialVersionUID = 1L;
79
80
81
82
83
84
85 private final List<SerializableConfigurationPropertiesManagement> configurationProperties;
86
87
88
89
90
91
92 private final PropertyStoreAccessor propertyStoreAccessor =
93 new MultiPropertyStoreAccessor();
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public ConfigurationPropertiesManagementWithDefaults(
108 final List<ConfigurationPropertiesManagement> configurationProperties)
109 throws IllegalArgumentException
110 {
111 super(getConfigurationKey(configurationProperties), configurationProperties
112 .get(0).getRegistry(), configurationProperties.get(0)
113 .getPropertyValueSecurity());
114
115 this.configurationProperties = toSerializable(configurationProperties);
116 }
117
118
119
120
121
122
123 private final class MultiPropertyStoreAccessor implements
124 PropertyStoreAccessor
125 {
126
127
128
129
130
131
132 private static final long serialVersionUID = 1L;
133
134 @Override
135 public Property getPropertyFromStore(final String name)
136 throws PropertyStoreException
137 {
138 for (final ConfigurationPropertiesManagement instance : configurationProperties)
139 {
140 final PropertyStoreAccessor accessor =
141 instance.getPropertyStoreAccessor();
142 final Property property = accessor.getPropertyFromStore(name);
143 if (property.getValue() != null)
144 {
145 return property;
146 }
147 }
148
149 throw new PropertyStoreException(
150 new PropertyStoreMessageBean(
151 PropertyStoreCode.CANNOT_GET_PROPERTY,
152 new IllegalStateException(
153 "The list of configuration properties is empty."
154 + " It is required that there is at least one element in it."),
155 getKey(), name));
156 }
157
158 @Override
159 public Property setPropertyToStore(final String name, final String value)
160 throws PropertyValidationException, ReadOnlyPropertyException
161 {
162 return representative().getPropertyStoreAccessor().setPropertyToStore(
163 name, value);
164 }
165
166 @Override
167 public Property deletePropertyInStore(final String name)
168 {
169 return representative().getPropertyStoreAccessor().deletePropertyInStore(
170 name);
171 }
172
173 @Override
174 public PropertyCollection getPropertyCollectionFromStore()
175 {
176 final MultiPropertyCollection collections = new MultiPropertyCollection();
177 for (final ConfigurationPropertiesManagement instance : configurationProperties)
178 {
179 final PropertyStoreAccessor accessor =
180 instance.getPropertyStoreAccessor();
181
182 final PropertyCollection collection =
183 accessor.getPropertyCollectionFromStore();
184 collections.add(collection);
185 }
186
187 return collections;
188 }
189 }
190
191
192
193
194
195 private static ConfigurationKey<?> getConfigurationKey(
196 final List<ConfigurationPropertiesManagement> configurationProperties)
197 {
198 if (configurationProperties == null || configurationProperties.isEmpty())
199 {
200 throw new IllegalArgumentException(
201 "The configurationProperties must not be empty.");
202 }
203 return configurationProperties.get(0).getKey();
204 }
205
206 private static List<SerializableConfigurationPropertiesManagement> toSerializable(
207 final List<ConfigurationPropertiesManagement> configurationProperties)
208 {
209 final List<SerializableConfigurationPropertiesManagement> list =
210 new ArrayList<SerializableConfigurationPropertiesManagement>();
211 for (final ConfigurationPropertiesManagement instance : configurationProperties)
212 {
213 final SerializableConfigurationPropertiesManagement serial =
214 instance.toSerializable();
215 list.add(serial);
216 }
217 return list;
218 }
219
220
221
222 @Override
223 public boolean isInAdminMode()
224 {
225 return representative().isInAdminMode();
226 }
227
228 @Override
229 public void setToAdminMode(final boolean newMode)
230 {
231 synchronized (configurationProperties)
232 {
233 for (final ConfigurationPropertiesManagement instance : configurationProperties)
234 {
235 instance.setToAdminMode(newMode);
236 }
237 }
238 }
239
240 @Override
241 public PropertyStoreAccessor getPropertyStoreAccessor()
242 {
243 return propertyStoreAccessor;
244 }
245
246
247
248 @Override
249 public DescribedProperty getProperty(final PropertyDescriptor descriptor,
250 final Object defaultValue) throws IllegalArgumentException,
251 UnknownPropertyException
252 {
253 DescribedProperty property = null;
254 for (final ConfigurationPropertiesManagement instance : configurationProperties)
255 {
256 try
257 {
258 property = instance.getProperty(descriptor, null);
259 if (property != null && property.getValue() != null)
260 {
261 break;
262 }
263 }
264 catch (final PropertyRootException e)
265 {
266
267 }
268 }
269
270 if (property == null || property.getValue() == null)
271 {
272 property = representative().getProperty(descriptor, defaultValue);
273 }
274
275 return property;
276 }
277
278 @Override
279 public DescribedProperty getProperty(final String key,
280 final Object defaultValue) throws IllegalArgumentException,
281 UnknownPropertyException
282 {
283 DescribedProperty property = null;
284 for (final ConfigurationPropertiesManagement instance : configurationProperties)
285 {
286 try
287 {
288 property = instance.getProperty(key, null);
289 if (property != null)
290 {
291 break;
292 }
293 }
294 catch (final PropertyRootException e)
295 {
296
297 }
298 }
299
300 if (property == null)
301 {
302 property = representative().getProperty(key, defaultValue);
303 }
304
305 return property;
306 }
307
308 @Override
309 public Object getPropertyAsType(final PropertyDescriptor descriptor)
310 throws IllegalArgumentException, UnknownPropertyException,
311 PropertyValueConversionException, SecurityException, PropertyRootException
312 {
313 final String plainValue = getPropertyValueAsString(descriptor);
314 final Object resolvedValue =
315 resolveAndConvert(descriptor, plainValue, null);
316 return resolvedValue;
317 }
318
319
320 @Override
321 public ValidatedProperty getValidatedProperty(
322 final PropertyDescriptor descriptor, final Object defaultValue)
323 throws IllegalArgumentException, UnknownPropertyException,
324 PropertyValidationException, SecurityException
325 {
326 final DescribedProperty property = getProperty(descriptor, defaultValue);
327
328 final Object plainValue = property.getValue();
329 if (plainValue == null && defaultValue == null && descriptor.isMandatory()
330 && !isInAdminMode())
331 {
332
333
334
335
336 final PropertyValidationMessageBean message =
337 new PropertyValidationMessageBean(descriptor,
338 descriptor.getConstraints(), plainValue);
339 throw new PropertyValidationException(message);
340 }
341
342 try
343 {
344 final Object resolvedValue =
345 resolveAndConvertAndValidate(descriptor, defaultValue, plainValue);
346
347 return new ValidatedProperty(property, getExpression(descriptor),
348 resolvedValue);
349 }
350 catch (final PropertyValueResolveException e)
351 {
352 throw wrapWithPropertyValueSourceInformation(e, descriptor, property);
353 }
354 catch (final PropertyValueConversionException e)
355 {
356 throw wrapWithPropertyValueSourceInformation(e, property);
357 }
358 catch (final PropertyValidationException e)
359 {
360 throw wrapWithPropertyValueSourceInformation(e, property);
361 }
362 }
363
364 private static String getExpression(final PropertyDescriptor descriptor)
365 {
366 final PropertyExpression expression = descriptor.getDefaultExpression();
367 return expression != null ? expression.getExpression() : null;
368 }
369
370 private static PropertyValueResolveException wrapWithPropertyValueSourceInformation(
371 final PropertyValueResolveException e,
372 final PropertyDescriptor descriptor, final Property property)
373 {
374 final PropertyValueResolveException cause =
375 isResolvementFailureOfPlaceholder(e, property)
376 ? new PropertyValueResolveException(
377 new PropertyExpressionMessageBean(e, descriptor,
378 property.getValue())) : e;
379
380 if (!(cause instanceof PropertyValueResolveWithSourceException))
381 {
382 final PropertyLocation source = property.getSource();
383 return new PropertyValueResolveWithSourceException(
384 new PropertyExpressionWithSourceMessageBean(cause, source));
385 }
386
387 return e;
388 }
389
390 private static boolean isResolvementFailureOfPlaceholder(
391 final PropertyValueResolveException e, final Property property)
392 {
393 return !property.getName().equals(e.getPropertyKey().toString());
394 }
395
396 private static PropertyValueConversionException wrapWithPropertyValueSourceInformation(
397 final PropertyValueConversionException e, final Property property)
398 {
399 final PropertyLocation source = property.getSource();
400 return new PropertyValueConversionWithSourceException(
401 new PropertyValueWithSourceMessageBean(e, source));
402 }
403
404 private static PropertyValidationException wrapWithPropertyValueSourceInformation(
405 final PropertyValidationException e, final Property property)
406 {
407 final PropertyLocation source = property.getSource();
408 return new PropertyValidationWithSourceException(
409 new PropertyValidationWithSourceMessageBean(e, source));
410 }
411
412 @Override
413 public void validate(final boolean lenient, final Class<?>... groups)
414 throws ConfigurationValidationException
415 {
416 synchronized (configurationProperties)
417 {
418 final ConfigurationValidator validator =
419 new ConfigurationValidator(this, lenient);
420 final PropertyCollection propertyCollection =
421 getPropertyStoreAccessor().getPropertyCollectionFromStore();
422 validator.validate(propertyCollection, groups);
423 }
424 }
425
426 @Override
427 public void validate(final PropertyDescriptor descriptor,
428 final Class<?>... groups) throws ConfigurationValidationException
429 {
430 final Object value = getPropertyValue(descriptor);
431 validate(descriptor, value, groups);
432 }
433
434 @Override
435 public void validate(final PropertyDescriptor descriptor, final String value,
436 final Class<?>... groups) throws ConfigurationValidationException
437 {
438 final ConfigurationValidator validator =
439 new ConfigurationValidator(this, false);
440 final Object resolvedValue = resolveAndConvert(descriptor, value, null);
441 validator.validate(descriptor, resolvedValue, groups);
442 }
443
444 @Override
445 public void flush()
446 {
447 for (final ConfigurationPropertiesManagement instance : configurationProperties)
448 {
449 instance.flush();
450 }
451 }
452
453 @Override
454 public ConfigurationPropertiesManagement toRepresentative()
455 {
456 return representative();
457 }
458
459 @Override
460 public SerializableConfigurationPropertiesManagement toSerializable()
461 {
462 return this;
463 }
464
465
466
467 private ConfigurationPropertiesManagement representative()
468 {
469 return configurationProperties.get(0);
470 }
471
472 @Override
473 public ConfigurationPropertiesManagement addDefinitions(
474 final PropertyProvider properties) throws NullPointerException
475 {
476 return representative().addDefinitions(properties);
477 }
478
479
480
481
482
483
484
485
486
487
488 @Override
489 public Property setProperty(final PropertyKey key, final String value)
490 throws NullPointerException, PropertyValidationException,
491 ReadOnlyPropertyException
492 {
493 return representative().setProperty(key, value);
494 }
495
496
497
498
499
500
501
502
503
504
505 @Override
506 public Property unsetProperty(final PropertyKey key)
507 throws NullPointerException, ReadOnlyPropertyException
508 {
509 return representative().unsetProperty(key);
510 }
511
512 @Override
513 public void addDescriptors(final Class<?> declaringType)
514 throws DuplicatePropertyDeclarationsException
515 {
516 representative().addDescriptors(declaringType);
517 }
518
519 @Override
520 public PropertyDescriptor getDescriptor(final String key)
521 throws UnknownPropertyException
522 {
523 return representative().getDescriptor(key);
524 }
525
526 @Override
527 public PropertyDescriptor getDescriptor(final PropertyKey key)
528 throws UnknownPropertyException
529 {
530 return representative().getDescriptor(key);
531 }
532
533 @Override
534 public List<PropertyDescriptor> getMandatoryPropertyDescriptors()
535 {
536 return representative().getMandatoryPropertyDescriptors();
537 }
538
539
540
541
542
543
544
545
546 @Override
547 public String toString()
548 {
549 final StringBuilder buffer = new StringBuilder();
550
551 for (final SerializableConfigurationPropertiesManagement instance : configurationProperties)
552 {
553 buffer.append(instance).append("\n======================\n");
554 }
555
556 return buffer.toString();
557 }
558 }