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.List;
19 import java.util.Map.Entry;
20 import java.util.Properties;
21
22 import javax.annotation.concurrent.ThreadSafe;
23
24 import org.apache.commons.lang.ObjectUtils;
25 import org.apache.commons.lang.StringUtils;
26
27 import de.smartics.properties.api.config.domain.ConfigurationPropertiesManagement;
28 import de.smartics.properties.api.config.domain.ConfigurationValidationException;
29 import de.smartics.properties.api.config.domain.Property;
30 import de.smartics.properties.api.config.domain.PropertyCollection;
31 import de.smartics.properties.api.config.domain.PropertyLocation;
32 import de.smartics.properties.api.config.domain.PropertyValidationWithSourceException;
33 import de.smartics.properties.api.config.domain.PropertyValueConversionWithSourceException;
34 import de.smartics.properties.api.config.domain.PropertyValueResolveWithSourceException;
35 import de.smartics.properties.api.config.domain.ResolvedProperty;
36 import de.smartics.properties.api.config.domain.UnknownPropertyException;
37 import de.smartics.properties.api.config.domain.key.ConfigurationKey;
38 import de.smartics.properties.api.core.domain.DuplicatePropertyDeclarationsException;
39 import de.smartics.properties.api.core.domain.PropertyDescriptor;
40 import de.smartics.properties.api.core.domain.PropertyDescriptorRegistry;
41 import de.smartics.properties.api.core.domain.PropertyExpression;
42 import de.smartics.properties.api.core.domain.PropertyKey;
43 import de.smartics.properties.api.core.domain.PropertyValidationException;
44 import de.smartics.properties.api.core.domain.PropertyValueConversionException;
45 import de.smartics.properties.api.core.domain.PropertyValueResolveException;
46 import de.smartics.properties.api.core.domain.ReadOnlyPropertyException;
47 import de.smartics.properties.spi.config.validation.ConfigurationValidator;
48 import de.smartics.util.lang.Arguments;
49 import de.smartics.util.lang.NullArgumentException;
50
51
52
53
54
55
56 @ThreadSafe
57 public abstract class AbstractConfigurationPropertiesManagement extends
58 AbstractConfigurationProperties implements
59 ConfigurationPropertiesManagement, ConfigurationPropertiesManagementSpi
60 {
61
62
63
64
65
66
67
68
69
70
71
72
73
74 protected AbstractConfigurationPropertiesManagement()
75 {
76 super();
77 }
78
79
80
81
82
83
84
85
86
87 protected AbstractConfigurationPropertiesManagement(
88 final ConfigurationKey key, final PropertyDescriptorRegistry registry)
89 throws NullArgumentException
90 {
91 super(key, registry);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106 @Override
107 public final PropertyDescriptor getDescriptor(final String key)
108 throws UnknownPropertyException
109 {
110 final PropertyDescriptor descriptor = getRegistry().get(key);
111
112 if (descriptor == null)
113 {
114 throw new UnknownPropertyException(getKey(), key);
115 }
116
117 return descriptor;
118 }
119
120 @Override
121 public final PropertyDescriptor getDescriptor(final PropertyKey key)
122 throws UnknownPropertyException
123 {
124 return getDescriptor(key.toString());
125 }
126
127 @Override
128 public final void addDescriptors(final Class<?> propertySetType)
129 throws DuplicatePropertyDeclarationsException
130 {
131 getRegistry().addDescriptors(propertySetType);
132 }
133
134 @Override
135 public final List<PropertyDescriptor> getMandatoryPropertyDescriptors()
136 {
137 return getRegistry().createMandatoryProperties();
138 }
139
140 @Override
141 public final ConfigurationPropertiesManagement addDefinitions(
142 final Properties properties) throws NullPointerException
143 {
144 for (final Entry<Object, Object> entry : properties.entrySet())
145 {
146 final String name = ObjectUtils.toString(entry.getKey(), null);
147 if (StringUtils.isNotBlank(name))
148 {
149 final String stringValue = unwrapValue(entry.getValue());
150 setPropertyToStore(name, stringValue);
151 }
152 }
153 return this;
154 }
155
156
157
158 @Override
159 public final Property getProperty(final String key, final Object defaultValue)
160 throws IllegalArgumentException, UnknownPropertyException
161 {
162 final PropertyDescriptor descriptor = getDescriptor(key);
163 return getProperty(descriptor, defaultValue);
164 }
165
166 @Override
167 public final Property getProperty(final PropertyDescriptor descriptor,
168 final Object defaultValue) throws IllegalArgumentException,
169 UnknownPropertyException
170 {
171 final String name = descriptor.getKey().toString();
172 final Property property = getPropertyFromStore(name);
173 final Object plainValue = property.getValue();
174
175 if (plainValue == null && defaultValue == null && descriptor.isMandatory())
176 {
177
178
179
180
181
182
183
184 throw new UnknownPropertyException(getKey(), name);
185 }
186
187 return property;
188 }
189
190 @Override
191 public final ResolvedProperty getResolvedProperty(
192 final PropertyDescriptor descriptor, final Object defaultValue)
193 throws IllegalArgumentException, UnknownPropertyException,
194 PropertyValidationException
195 {
196 final Property property = getProperty(descriptor, defaultValue);
197
198 final Object plainValue = property.getValue();
199 try
200 {
201 final Object resolvedValue =
202 resolveAndConvert(descriptor, defaultValue, plainValue);
203 return new ResolvedProperty(property, getExpression(descriptor),
204 resolvedValue);
205 }
206 catch (final PropertyValueResolveException e)
207 {
208 throw wrapWithPropertyValueSourceInformation(e, descriptor, property);
209 }
210 catch (final PropertyValueConversionException e)
211 {
212 throw wrapWithPropertyValueSourceInformation(e, property);
213 }
214 catch (final PropertyValidationException e)
215 {
216 throw wrapWithPropertyValueSourceInformation(e, property);
217 }
218 }
219
220 private static String getExpression(final PropertyDescriptor descriptor)
221 {
222 final PropertyExpression expression = descriptor.getDefaultExpression();
223 return expression != null ? expression.getExpression() : null;
224 }
225
226 @Override
227 public final Property setProperty(final PropertyKey key, final String value)
228 throws NullPointerException, PropertyValidationException,
229 ReadOnlyPropertyException
230 {
231 Arguments.checkNotNull("key", key);
232 checkWritable(key, value);
233
234 final String name = key.toString();
235 return setPropertyAndFireEvent(name, value);
236 }
237
238 private Property setPropertyAndFireEvent(final String name, final String value)
239 throws NullPointerException, PropertyValidationException,
240 ReadOnlyPropertyException
241 {
242 final Property oldProperty = setPropertyToStore(name, value);
243 firePropertyChange(name, oldProperty != null ? oldProperty.getValue()
244 : null, value);
245 return oldProperty;
246 }
247
248 @Override
249 public final Property unsetProperty(final PropertyKey key)
250 throws NullPointerException, ReadOnlyPropertyException
251 {
252 Arguments.checkNotNull("key", key);
253 checkWritable(key, null);
254
255 final String name = key.toString();
256 final Property oldProperty = deletePropertyInStore(name);
257 firePropertyChange(name, oldProperty.getValue(), null);
258 return oldProperty;
259 }
260
261 @Override
262 public final void validate(final boolean lenient)
263 throws ConfigurationValidationException
264 {
265 final ConfigurationValidator validator =
266 new ConfigurationValidator(this, lenient);
267 final PropertyCollection propertyCollection =
268 getPropertyCollectionFromStore();
269 validator.validate(propertyCollection);
270 }
271
272
273
274
275
276
277
278
279
280
281 @Override
282 public void flush()
283 {
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 protected abstract Property setPropertyToStore(final String name,
300 final String value) throws NullPointerException;
301
302
303
304
305
306
307
308
309 protected abstract PropertyCollection getPropertyCollectionFromStore();
310
311
312
313
314
315
316
317
318
319 protected abstract Property deletePropertyInStore(final String name);
320
321
322
323
324
325
326
327
328
329
330 protected abstract Property getPropertyFromStore(final String name);
331
332
333
334
335
336
337
338
339
340
341
342
343 private void checkWritable(final PropertyKey key, final Object value)
344 throws ReadOnlyPropertyException, UnknownPropertyException
345 {
346 final PropertyDescriptor descriptor = getDescriptor(key);
347
348 if (!descriptor.isRuntimeMutable())
349 {
350 final String currentValue = getPropertyValueAsString(descriptor);
351 throw new ReadOnlyPropertyException(descriptor, currentValue, value);
352 }
353 }
354
355
356
357
358
359
360
361
362
363 private String unwrapValue(final Object value)
364 {
365 if (value instanceof Property)
366 {
367 return ((Property) value).getValue();
368 }
369 return ObjectUtils.toString(value, null);
370 }
371
372 private static PropertyValueResolveException wrapWithPropertyValueSourceInformation(
373 final PropertyValueResolveException e,
374 final PropertyDescriptor descriptor, final Property property)
375 {
376 final PropertyValueResolveException cause =
377 isResolvementFailureOfPlaceholder(e, property)
378 ? new PropertyValueResolveException(e, descriptor,
379 property.getValue()) : e;
380
381 if (!(cause instanceof PropertyValueResolveWithSourceException))
382 {
383 final PropertyLocation source = property.getSource();
384 return new PropertyValueResolveWithSourceException(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().getName());
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(e, source);
401 }
402
403 private static PropertyValidationException wrapWithPropertyValueSourceInformation(
404 final PropertyValidationException e, final Property property)
405 {
406 final PropertyLocation source = property.getSource();
407 return new PropertyValidationWithSourceException(e, source);
408 }
409
410
411
412 }