1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.morph.context.contexts;
17
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Set;
24
25 import net.sf.composite.util.ObjectUtils;
26 import net.sf.morph.Defaults;
27 import net.sf.morph.context.Context;
28 import net.sf.morph.context.ContextException;
29 import net.sf.morph.context.DecoratedContext;
30 import net.sf.morph.context.support.ContextMapBridge;
31 import net.sf.morph.lang.Language;
32 import net.sf.morph.transform.Converter;
33 import net.sf.morph.util.ContainerUtils;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38 /**
39 * <p>
40 * Convenient base class for Contexts. Validates arguments and takes care of
41 * logging and exception handling. Also implements the {@link java.util.Map}
42 * interface.
43 * </p>
44 *
45 * <p>
46 * As a Map, this class only supports non-null Strings for keys (i.e. - calling
47 * <code>Map.put(new Object(), new Object())</code> will throw a
48 * {@link net.sf.morph.context.ContextException}).
49 * </p>
50 *
51 * @author Matt Sgarlata
52 * @since Nov 19, 2004
53 */
54 public abstract class BaseContext implements Context, Map, DecoratedContext {
55
56 private static final ContextMapBridge DEFAULT_CONTEXT_MAP_BRIDGE = new ContextMapBridge();
57
58 private transient Log log = LogFactory.getLog(getClass());
59
60 private ContextMapBridge contextMapBridge;
61 private Converter converter;
62 private Language language;
63
64 /**
65 * Create a new BaseContext.
66 */
67 public BaseContext() {
68 super();
69 setContextMapBridge(DEFAULT_CONTEXT_MAP_BRIDGE);
70 setConverter(Defaults.createConverter());
71 setLanguage(Defaults.createLanguage());
72 }
73
74 /**
75 * Implement getPropertyNames()
76 * @return String[] of property names
77 * @throws Exception if errors occur
78 */
79 protected abstract String[] getPropertyNamesImpl() throws Exception;
80
81 /**
82 * Implement <code>get(propertyName)</code>.
83 * @param propertyName to get
84 * @return Object value
85 * @throws Exception in case of errors
86 */
87 protected abstract Object getImpl(String propertyName)
88 throws Exception;
89
90 /**
91 * Implement <code>set(propertyName, propertyValue)</code>.
92 * @param propertyName to set
93 * @param propertyValue to set
94 * @throws Exception in case of errors
95 */
96 protected abstract void setImpl(String propertyName, Object propertyValue)
97 throws Exception;
98
99 /**
100 * {@inheritDoc}
101 */
102 public final String[] getPropertyNames() throws ContextException {
103 try {
104
105 String[] cachedPropertyNames = getPropertyNamesImpl();
106 Set propertyNames = ContainerUtils.createOrderedSet();
107 if (!ObjectUtils.isEmpty(cachedPropertyNames)) {
108 propertyNames.addAll(Arrays.asList(cachedPropertyNames));
109 }
110
111
112
113
114
115
116
117
118
119 Iterator iterator = propertyNames.iterator();
120 while (iterator.hasNext()) {
121 String propertyName = (String) iterator.next();
122 if (!getLanguage().isProperty(propertyName)) {
123 iterator.remove();
124 }
125 }
126 return (String[]) propertyNames.toArray(new String[propertyNames.size()]);
127 }
128 catch (ContextException e) {
129 throw e;
130 }
131 catch (Exception e) {
132 throw new ContextException("Unable to retrieve property names", e);
133 }
134 }
135
136 /**
137 * {@inheritDoc}
138 */
139 public final Object get(String expression) throws ContextException {
140 if (getLanguage().isProperty(expression)) {
141
142 if (ObjectUtils.isEmpty(expression)) {
143 throw new ContextException("You must specify a propertyName to retrieve");
144 }
145
146 String[] propertyNames = getPropertyNames();
147 if (!(ContainerUtils.contains(propertyNames, expression))) {
148 return null;
149 }
150 try {
151
152
153
154
155
156
157 return getImpl(expression);
158 }
159 catch (ContextException e) {
160 throw e;
161 }
162 catch (Exception e) {
163 throw new ContextException("Could not retrieve property '" + expression + "' from this context", e);
164 }
165 }
166 return getLanguage().get(this, expression);
167 }
168
169 /**
170 * {@inheritDoc}
171 */
172 public final void set(String expression, Object value) throws ContextException {
173 if (getLanguage().isProperty(expression)) {
174
175 if (ObjectUtils.isEmpty(expression)) {
176 throw new ContextException("You must specify an expression to set");
177 }
178
179
180
181
182
183 try {
184 setImpl(expression, value);
185 }
186 catch (ContextException e) {
187 throw e;
188 }
189 catch (Exception e) {
190 throw new ContextException("Could not set property '" + expression + "' in context " + ObjectUtils.getObjectDescription(this), e);
191 }
192 }
193 else {
194 getLanguage().set(this, expression, value);
195 }
196 }
197
198 /**
199 * {@inheritDoc}
200 */
201 public final Object get(String expression, Class destinationClass)
202 throws ContextException {
203 return get(expression, destinationClass, Locale.getDefault());
204 }
205
206 /**
207 * {@inheritDoc}
208 */
209 public final Object get(String expression, Class destinationClass, Locale locale)
210 throws ContextException {
211 try {
212 Object object = get(expression);
213 return getConverter().convert(destinationClass, object, locale);
214 }
215 catch (Exception e) {
216 throw new ContextException("Unable to retrieve value for expression '" + expression + "' as destination " + ObjectUtils.getObjectDescription(destinationClass), e);
217 }
218 }
219
220 /**
221 * {@inheritDoc}
222 */
223 public final Object get(String expression, Locale locale, Class destinationClass)
224 throws ContextException {
225 return get(expression, destinationClass, locale);
226 }
227
228 /**
229 * {@inheritDoc}
230 */
231 public final void set(String expression, Object value, Locale locale)
232 throws ContextException {
233 if (ObjectUtils.isEmpty(expression)) {
234 throw new ContextException("You must specify a propertyName to set");
235 }
236
237 try {
238 setImpl(expression, value);
239 }
240 catch (ContextException e) {
241 throw e;
242 }
243 catch (Exception e) {
244 throw new ContextException("Could not set '" + expression + "' to " + ObjectUtils.getObjectDescription(value), e);
245 }
246 }
247
248 /**
249 * {@inheritDoc}
250 */
251 public void clear() {
252 getContextMapBridge().clear(this);
253 }
254
255 /**
256 * The implementation of this method has O(n) time complexity.
257 * @see java.util.Map#containsKey(java.lang.Object)
258 */
259 public boolean containsKey(Object key) {
260 return getContextMapBridge().containsKey(this, key);
261 }
262
263 /**
264 * {@inheritDoc}
265 */
266 public boolean containsValue(Object value) {
267 return getContextMapBridge().containsValue(this, value);
268 }
269
270 /**
271 * {@inheritDoc}
272 */
273 public Set entrySet() {
274 return getContextMapBridge().entrySet(this);
275 }
276
277 /**
278 * {@inheritDoc}
279 */
280 public Object get(Object key) {
281 return getContextMapBridge().get(this, key);
282 }
283
284 /**
285 * {@inheritDoc}
286 */
287 public boolean isEmpty() {
288 return getContextMapBridge().isEmpty(this);
289 }
290
291 /**
292 * {@inheritDoc}
293 */
294 public Set keySet() {
295 return getContextMapBridge().keySet(this);
296 }
297
298 /**
299 * {@inheritDoc}
300 */
301 public Object put(Object key, Object value) {
302 return getContextMapBridge().put(this, key, value);
303 }
304
305 /**
306 * {@inheritDoc}
307 */
308 public void putAll(Map t) {
309 getContextMapBridge().putAll(this, t);
310 }
311
312 /**
313 * {@inheritDoc}
314 */
315 public Object remove(Object key) {
316 return getContextMapBridge().remove(this, key);
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 public int size() {
323 return getContextMapBridge().size(this);
324 }
325
326 /**
327 * {@inheritDoc}
328 */
329 public Collection values() {
330 return getContextMapBridge().values(this);
331 }
332
333 /**
334 * Get the converter.
335 * @return Returns the converter.
336 */
337 public Converter getConverter() {
338 if (converter == null) {
339 setConverter(Defaults.createConverter());
340 }
341 return converter;
342 }
343
344 /**
345 * Set the converter.
346 * @param converter The converter to set.
347 */
348 public void setConverter(Converter converter) {
349 this.converter = converter;
350 }
351
352 /**
353 * Get the Language.
354 * @return Returns the language.
355 */
356 public Language getLanguage() {
357 if (language == null) {
358 setLanguage(Defaults.createLanguage());
359 }
360 return language;
361 }
362
363 /**
364 * Set the Language.
365 * @param language The language to set.
366 */
367 public void setLanguage(Language language) {
368 this.language = language;
369 }
370
371 /**
372 * Set the ContextMapBridge.
373 * @param contextMapBridge to set
374 */
375 public void setContextMapBridge(ContextMapBridge contextMapBridge) {
376 this.contextMapBridge = contextMapBridge;
377 }
378
379 /**
380 * Get the ContextMapBridge.
381 * @return ContextMapBridge
382 */
383 public ContextMapBridge getContextMapBridge() {
384 return contextMapBridge == null ? DEFAULT_CONTEXT_MAP_BRIDGE : contextMapBridge;
385 }
386
387 /**
388 * Get the log.
389 * @return Log
390 */
391 protected Log getLog() {
392 return log;
393 }
394
395 /**
396 * Set the Log.
397 * @param log to set
398 */
399 protected void setLog(Log log) {
400 this.log = log;
401 }
402
403
404
405
406
407
408 }