1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.betwixt.expression;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import org.apache.commons.betwixt.BindingConfiguration;
22 import org.apache.commons.betwixt.strategy.ObjectStringConverter;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 /*** <p><code>Context</code> describes the context used to evaluate
27 * bean expressions.
28 * This is mostly a bean together with a number of context variables.
29 * Context variables are named objects.
30 * In other words,
31 * a context variable associates an object with a string.</p>
32 *
33 * <p> Logging during expression evaluation is done through the logging
34 * instance held by this class.
35 * The object initiating the evaluation should control this logging
36 * and so passing a <code>Log</code> instance is enforced by the constructors.</p>
37 *
38 * <p><code>Context</code> is a natural place to include shared evaluation code.
39 * One of the problems that you get with object graphs is that they can be cyclic.
40 * Xml cannot (directly) include cycles.
41 * Therefore <code>betwixt</code> needs to find and deal properly with cycles.
42 * The algorithm used is to check the parentage of a new child.
43 * If the child is a parent then that operation fails. </p>
44 *
45 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
46 */
47 public class Context {
48
49 /*** Evaluate this bean */
50 private Object bean;
51 /*** Variables map */
52 private Map variables;
53 /***
54 * Logging uses commons-logging <code>Log</code>
55 * named <code>org.apache.commons.betwixt</code>
56 */
57 private Log log;
58 /*** Configuration for dynamic binding properties */
59 private BindingConfiguration bindingConfiguration;
60
61 /***
62 * Construct context with default log
63 */
64 public Context() {
65 this( null, LogFactory.getLog( Context.class ) );
66 }
67
68 /*** Convenience constructor sets evaluted bean and log.
69 *
70 * @param bean evaluate expressions against this bean
71 * @param log log to this logger
72 * @deprecated 0.5 use constructor which takes a BindingConfiguration
73 */
74 public Context(Object bean, Log log) {
75 this( bean, log, new BindingConfiguration() );
76 }
77
78
79 /*** Convenience constructor sets evaluted bean and log.
80 *
81 * @param bean evaluate expressions against this bean
82 * @param log log to this logger
83 * @param bindingConfiguration not null
84 */
85 public Context(Object bean, Log log, BindingConfiguration bindingConfiguration) {
86 this( bean, new HashMap(), log, bindingConfiguration );
87 }
88
89 /***
90 * Construct a cloned context.
91 * The constructed context should share bean, variables, log and binding configuration.
92 * @param context duplicate the attributes of this bean
93 */
94 public Context( Context context ) {
95 this(context.bean, context.variables, context.log, context.bindingConfiguration);
96 }
97
98
99 /*** Convenience constructor sets evaluted bean, context variables and log.
100 *
101 * @param bean evaluate expressions against this bean
102 * @param variables context variables
103 * @param log log to this logger
104 * @deprecated 0.5 use constructor which takes a converter
105 */
106 public Context(Object bean, Map variables, Log log) {
107 this( bean, variables, log, new BindingConfiguration() );
108 }
109
110 /*** Convenience constructor sets evaluted bean, context variables and log.
111 *
112 * @param bean evaluate expressions against this bean
113 * @param variables context variables
114 * @param log log to this logger
115 * @param bindingConfiguration not null
116 */
117 public Context(Object bean, Map variables, Log log, BindingConfiguration bindingConfiguration) {
118 this.bean = bean;
119 this.variables = variables;
120 this.log = log;
121 this.bindingConfiguration = bindingConfiguration;
122 }
123
124 /*** Returns a new child context with the given bean but the same log and variables.
125 *
126 * @param newBean create a child context for this bean
127 * @return new Context with new bean but shared variables
128 */
129
130
131 public Context newContext(Object newBean) {
132 Context context = new Context(this);
133 context.setBean( newBean );
134 return context;
135 }
136
137 /***
138 * Gets the current bean.
139 * @return the bean against which expressions are evaluated
140 */
141 public Object getBean() {
142 return bean;
143 }
144
145 /***
146 * Set the current bean.
147 * @param bean the Object against which expressions will be evaluated
148 */
149 public void setBean(Object bean) {
150 this.bean = bean;
151 }
152
153 /***
154 * Gets context variables.
155 * @return map containing variable values keyed by variable name
156 */
157 public Map getVariables() {
158 return variables;
159 }
160
161 /***
162 * Sets context variables.
163 * @param variables map containing variable values indexed by varibable name Strings
164 */
165 public void setVariables(Map variables) {
166 this.variables = variables;
167 }
168
169 /***
170 * Gets the value of a particular context variable.
171 * @param name the name of the variable whose value is to be returned
172 * @return the variable value or null if the variable isn't set
173 */
174 public Object getVariable(String name) {
175 return variables.get( name );
176 }
177
178 /***
179 * Sets the value of a particular context variable.
180 * @param name the name of the variable
181 * @param value the value of the variable
182 */
183 public void setVariable(String name, Object value) {
184 variables.put( name, value );
185 }
186
187 /***
188 * Gets the current log.
189 *
190 * @return the implementation to which this class logs
191 */
192 public Log getLog() {
193 return log;
194 }
195
196 /***
197 * Set the log implementation to which this class logs
198 *
199 * @param log the implemetation that this class should log to
200 */
201 public void setLog(Log log) {
202 this.log = log;
203 }
204
205 /***
206 * Gets object <-> string converter.
207 * @return the Converter to be used for conversions, not null
208 * @since 0.5
209 */
210 public ObjectStringConverter getObjectStringConverter() {
211 return bindingConfiguration.getObjectStringConverter();
212 }
213
214 /***
215 * Should <code>ID</code>'s and <code>IDREF</code> attributes
216 * be used to cross-reference matching objects?
217 *
218 * @return true if <code>ID</code> and <code>IDREF</code>
219 * attributes should be used to cross-reference instances
220 * @since 0.5
221 */
222 public boolean getMapIDs() {
223 return bindingConfiguration.getMapIDs();
224 }
225
226 /***
227 * The name of the attribute which can be specified in the XML to override the
228 * type of a bean used at a certain point in the schema.
229 *
230 * <p>The default value is 'className'.</p>
231 *
232 * @return The name of the attribute used to overload the class name of a bean
233 * @since 0.5
234 */
235 public String getClassNameAttribute() {
236 return bindingConfiguration.getClassNameAttribute();
237 }
238
239 /***
240 * Sets the name of the attribute which can be specified in
241 * the XML to override the type of a bean used at a certain
242 * point in the schema.
243 *
244 * <p>The default value is 'className'.</p>
245 *
246 * @param classNameAttribute The name of the attribute used to overload the class name of a bean
247 * @since 0.5
248 */
249 public void setClassNameAttribute(String classNameAttribute) {
250 bindingConfiguration.setClassNameAttribute( classNameAttribute );
251 }
252 }