1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.scxml2.env;
18
19 import java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.commons.scxml2.Context;
26 import org.apache.commons.scxml2.SCXMLSystemContext;
27
28 /**
29 * Simple Context wrapping a map of variables.
30 *
31 */
32 public class SimpleContext implements Context, Serializable {
33
34 /** Serial version UID. */
35 private static final long serialVersionUID = 1L;
36 /** Implementation independent log category. */
37 private static final Log DEFAULT_LOG = LogFactory.getLog(Context.class);
38 private Log log = DEFAULT_LOG;
39 /** The parent Context to this Context. */
40 private Context parent;
41 /** The Map of variables and their values in this Context. */
42 private Map<String, Object> vars;
43
44 protected final SCXMLSystemContext systemContext;
45
46 /**
47 * Constructor.
48 *
49 */
50 public SimpleContext() {
51 this(null, null);
52 }
53
54 /**
55 * Constructor.
56 *
57 * @param parent A parent Context, can be null
58 */
59 public SimpleContext(final Context parent) {
60 this(parent, null);
61 }
62
63 /**
64 * Constructor.
65 *
66 * @param parent A parent Context, can be null
67 * @param initialVars A pre-populated initial variables map
68 */
69 public SimpleContext(final Context parent, final Map<String, Object> initialVars) {
70 this.parent = parent;
71 this.systemContext = parent instanceof SCXMLSystemContext ?
72 (SCXMLSystemContext) parent : parent != null ? parent.getSystemContext() : null;
73 if (initialVars == null) {
74 setVars(new HashMap<String, Object>());
75 } else {
76 setVars(this.vars = initialVars);
77 }
78 }
79
80 /**
81 * Assigns a new value to an existing variable or creates a new one.
82 * The method searches the chain of parent Contexts for variable
83 * existence.
84 *
85 * @param name The variable name
86 * @param value The variable value
87 * @see org.apache.commons.scxml2.Context#set(String, Object)
88 */
89 public void set(final String name, final Object value) {
90 if (getVars().containsKey(name)) { //first try to override local
91 setLocal(name, value);
92 } else if (parent != null && parent.has(name)) { //then check for global
93 parent.set(name, value);
94 } else { //otherwise create a new local variable
95 setLocal(name, value);
96 }
97 }
98
99 /**
100 * Get the value of this variable; delegating to parent.
101 *
102 * @param name The variable name
103 * @return Object The variable value
104 * @see org.apache.commons.scxml2.Context#get(java.lang.String)
105 */
106 public Object get(final String name) {
107 Object localValue = getVars().get(name);
108 if (localValue != null) {
109 return localValue;
110 } else if (parent != null) {
111 return parent.get(name);
112 } else {
113 return null;
114 }
115 }
116
117 /**
118 * Check if this variable exists, delegating to parent.
119 *
120 * @param name The variable name
121 * @return boolean true if this variable exists
122 * @see org.apache.commons.scxml2.Context#has(java.lang.String)
123 */
124 public boolean has(final String name) {
125 return (hasLocal(name) || (parent != null && parent.has(name)));
126 }
127
128 /**
129 * Check if this variable exists, only checking this Context
130 *
131 * @param name The variable name
132 * @return boolean true if this variable exists
133 * @see org.apache.commons.scxml2.Context#hasLocal(java.lang.String)
134 */
135 public boolean hasLocal(final String name) {
136 return (getVars().containsKey(name));
137 }
138
139 /**
140 * Clear this Context.
141 *
142 * @see org.apache.commons.scxml2.Context#reset()
143 */
144 public void reset() {
145 getVars().clear();
146 }
147
148 /**
149 * Get the parent Context, may be null.
150 *
151 * @return Context The parent Context
152 * @see org.apache.commons.scxml2.Context#getParent()
153 */
154 public Context getParent() {
155 return parent;
156 }
157
158 /**
159 * Get the SCXMLSystemContext for this Context, should not be null unless this is the root Context
160 *
161 * @return The SCXMLSystemContext in a chained Context environment
162 */
163 public final SCXMLSystemContext getSystemContext() {
164 return systemContext;
165 }
166
167 /**
168 * Assigns a new value to an existing variable or creates a new one.
169 * The method allows to shaddow a variable of the same name up the
170 * Context chain.
171 *
172 * @param name The variable name
173 * @param value The variable value
174 * @see org.apache.commons.scxml2.Context#setLocal(String, Object)
175 */
176 public void setLocal(final String name, final Object value) {
177 getVars().put(name, value);
178 if (log.isDebugEnabled()) {
179 log.debug(name + " = " + String.valueOf(value));
180 }
181 }
182
183 /**
184 * Set the variables map.
185 *
186 * @param vars The new Map of variables.
187 */
188 protected void setVars(final Map<String, Object> vars) {
189 this.vars = vars;
190 }
191
192 /**
193 * Get the Map of all local variables in this Context.
194 *
195 * @return Returns the vars.
196 */
197 public Map<String, Object> getVars() {
198 return vars;
199 }
200
201 /**
202 * Set the log used by this <code>Context</code> instance.
203 *
204 * @param log The new log.
205 */
206 protected void setLog(final Log log) {
207 this.log = log;
208 }
209
210 /**
211 * Get the log used by this <code>Context</code> instance.
212 *
213 * @return Log The log being used.
214 */
215 protected Log getLog() {
216 return log;
217 }
218
219 }
220