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.Set;
20
21 import net.sf.composite.util.ObjectUtils;
22 import net.sf.morph.context.Context;
23 import net.sf.morph.context.ContextException;
24 import net.sf.morph.context.HierarchicalContext;
25 import net.sf.morph.util.ContainerUtils;
26
27 /**
28 * <p>
29 * Convenient base class for hierarchical Contexts. Validates arguments and
30 * takes care of logging and exception handling. Also implements the
31 * {@link java.util.Map} interface.
32 * </p>
33 *
34 * @author Matt Sgarlata
35 * @since Nov 29, 2004
36 * @see net.sf.morph.context.support.BaseContext
37 * @see net.sf.morph.context.HierarchicalContext
38 */
39 public abstract class BaseHierarchicalContext extends BaseContext implements
40 HierarchicalContext {
41
42 private Context parentContext;
43
44 /**
45 * Creates a new, empty context.
46 */
47 public BaseHierarchicalContext() {
48 super();
49 }
50
51 /**
52 * Creates a new, empty context with the specified parent.
53 */
54 public BaseHierarchicalContext(Context parentContext) {
55 super();
56 this.parentContext = parentContext;
57 }
58
59 protected abstract Object getHierarchicalImpl(String propertyName) throws Exception;
60
61 protected abstract String[] getPropertyNamesHierarchicalImpl() throws Exception;
62
63 protected abstract void setHierarchicalImpl(String propertyName, Object propertyValue) throws Exception;
64
65 protected final Object getImpl(String propertyName) throws Exception {
66 Object value = null;
67
68 if (getLog().isTraceEnabled()) {
69 getLog().trace("Getting property '" + propertyName + "' from context " + getClass().getName());
70 }
71
72 try {
73 value = this.getHierarchicalImpl(propertyName);
74 }
75 catch (ContextException e) {
76 if (getLog().isDebugEnabled()) {
77 getLog().debug("Unable to retrieve property '" + propertyName + "' from context " + getClass().getName() + "; attempting to read property from parent context");
78 }
79 }
80 if (value == null) {
81 Context parent = getParentContext();
82 if (parent != null) {
83 value = parent.get(propertyName);
84 }
85 }
86 return value;
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 }
103
104 protected final String[] getPropertyNamesImpl() throws Exception {
105 String[] currentPropertyNames = this.getPropertyNamesHierarchicalImpl();
106 int size = currentPropertyNames == null ? 0 : currentPropertyNames.length;
107 Set propertyNames = ContainerUtils.createOrderedSet();
108 if (!ObjectUtils.isEmpty(currentPropertyNames)) {
109 propertyNames.addAll(Arrays.asList(currentPropertyNames));
110 }
111 Context currentContext = parentContext;
112 while (currentContext != null &&
113 currentContext instanceof HierarchicalContext) {
114 currentPropertyNames = currentContext.getPropertyNames();
115 if (!ObjectUtils.isEmpty(currentPropertyNames)) {
116 propertyNames.addAll(
117 Arrays.asList(currentPropertyNames));
118 }
119 currentContext =
120 ((HierarchicalContext) currentContext).getParentContext();
121 }
122 return (String[])
123 propertyNames.toArray(new String[propertyNames.size()]);
124 }
125
126 protected final void setImpl(String propertyName, Object propertyValue)
127 throws Exception {
128
129 if (getLog().isTraceEnabled()) {
130 getLog().trace("Setting property '" + propertyName + "' to value " + ObjectUtils.getObjectDescription(propertyValue) + " for context " + ObjectUtils.getObjectDescription(this));
131 }
132
133 try {
134 setHierarchicalImpl(propertyName, propertyValue);
135 }
136 catch (Exception e) {
137 if (getLog().isDebugEnabled()) {
138 getLog().debug("Unable to retrieve property '" + propertyName + "' from context " + ObjectUtils.getObjectDescription(this) + "; attempting to read property from parent context");
139 }
140 if (getParentContext() == null) {
141 throw e;
142 }
143 getParentContext().set(propertyName, propertyValue);
144 }
145 }
146
147 /**
148 * Sets this context's parent context.
149 *
150 * @param parentContext
151 * this context's parent context
152 */
153 public void setParentContext(Context parentContext) {
154 this.parentContext = parentContext;
155 }
156 public Context getParentContext() {
157 return parentContext;
158 }
159
160 }