1 package org.apache.commons.ognl;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 /**
23 * An <code>Evaluation</code> is and object that holds a node being evaluated and the source from which that node will
24 * take extract its value. It refers to child evaluations that occur as a result of the nodes' evaluation.
25 */
26 public class Evaluation
27 {
28 private SimpleNode node;
29
30 private Object source;
31
32 private boolean setOperation;
33
34 private Object result;
35
36 private Throwable exception;
37
38 private Evaluation parent;
39
40 private Evaluation next;
41
42 private Evaluation previous;
43
44 private Evaluation firstChild;
45
46 private Evaluation lastChild;
47
48 /**
49 * Constructs a new "get" <code>Evaluation</code> from the node and source given.
50 */
51 public Evaluation( SimpleNode node, Object source )
52 {
53 super();
54 this.node = node;
55 this.source = source;
56 }
57
58 /**
59 * Constructs a new <code>Evaluation</code> from the node and source given. If <code>setOperation</code> is true
60 * this <code>Evaluation</code> represents a "set" as opposed to a "get".
61 */
62 public Evaluation( SimpleNode node, Object source, boolean setOperation )
63 {
64 this( node, source );
65 this.setOperation = setOperation;
66 }
67
68 /**
69 * Returns the <code>SimpleNode</code> for this <code>Evaluation</code>
70 */
71 public SimpleNode getNode()
72 {
73 return node;
74 }
75
76 /**
77 * Sets the node of the evaluation. Normally applications do not need to set this. Notable exceptions to this rule
78 * are custom evaluators that choose between navigable objects (as in a multi-root evaluator where the navigable
79 * node is chosen at runtime).
80 */
81 public void setNode( SimpleNode value )
82 {
83 node = value;
84 }
85
86 /**
87 * Returns the source object on which this Evaluation operated.
88 */
89 public Object getSource()
90 {
91 return source;
92 }
93
94 /**
95 * Sets the source of the evaluation. Normally applications do not need to set this. Notable exceptions to this rule
96 * are custom evaluators that choose between navigable objects (as in a multi-root evaluator where the navigable
97 * node is chosen at runtime).
98 */
99 public void setSource( Object value )
100 {
101 source = value;
102 }
103
104 /**
105 * Returns true if this Evaluation represents a set operation.
106 */
107 public boolean isSetOperation()
108 {
109 return setOperation;
110 }
111
112 /**
113 * Marks the Evaluation as a set operation if the value is true, else marks it as a get operation.
114 */
115 public void setSetOperation( boolean value )
116 {
117 setOperation = value;
118 }
119
120 /**
121 * Returns the result of the Evaluation, or null if it was a set operation.
122 */
123 public Object getResult()
124 {
125 return result;
126 }
127
128 /**
129 * Sets the result of the Evaluation. This method is normally only used interally and should not be set without
130 * knowledge of what you are doing.
131 */
132 public void setResult( Object value )
133 {
134 result = value;
135 }
136
137 /**
138 * Returns the exception that occurred as a result of evaluating the Evaluation, or null if no exception occurred.
139 */
140 public Throwable getException()
141 {
142 return exception;
143 }
144
145 /**
146 * Sets the exception that occurred as a result of evaluating the Evaluation. This method is normally only used
147 * interally and should not be set without knowledge of what you are doing.
148 */
149 public void setException( Throwable value )
150 {
151 exception = value;
152 }
153
154 /**
155 * Returns the parent evaluation of this evaluation. If this returns null then it is is the root evaluation of a
156 * tree.
157 */
158 public Evaluation getParent()
159 {
160 return parent;
161 }
162
163 /**
164 * Returns the next sibling of this evaluation. Returns null if this is the last in a chain of evaluations.
165 */
166 public Evaluation getNext()
167 {
168 return next;
169 }
170
171 /**
172 * Returns the previous sibling of this evaluation. Returns null if this is the first in a chain of evaluations.
173 */
174 public Evaluation getPrevious()
175 {
176 return previous;
177 }
178
179 /**
180 * Returns the first child of this evaluation. Returns null if there are no children.
181 */
182 public Evaluation getFirstChild()
183 {
184 return firstChild;
185 }
186
187 /**
188 * Returns the last child of this evaluation. Returns null if there are no children.
189 */
190 public Evaluation getLastChild()
191 {
192 return lastChild;
193 }
194
195 /**
196 * Gets the first descendent. In any Evaluation tree this will the Evaluation that was first executed.
197 */
198 public Evaluation getFirstDescendant()
199 {
200 if ( firstChild != null )
201 {
202 return firstChild.getFirstDescendant();
203 }
204 return this;
205 }
206
207 /**
208 * Gets the last descendent. In any Evaluation tree this will the Evaluation that was most recently executing.
209 */
210 public Evaluation getLastDescendant()
211 {
212 if ( lastChild != null )
213 {
214 return lastChild.getLastDescendant();
215 }
216 return this;
217 }
218
219 /**
220 * Adds a child to the list of children of this evaluation. The parent of the child is set to the receiver and the
221 * children references are modified in the receiver to reflect the new child. The lastChild of the receiver is set
222 * to the child, and the firstChild is set also if child is the first (or only) child.
223 */
224 public void addChild( Evaluation child )
225 {
226 if ( firstChild == null )
227 {
228 firstChild = child;
229 lastChild = child;
230 }
231 else
232 {
233 if ( firstChild == lastChild )
234 {
235 firstChild.next = child;
236 lastChild = child;
237 lastChild.previous = firstChild;
238 }
239 else
240 {
241 child.previous = lastChild;
242 lastChild.next = child;
243 lastChild = child;
244 }
245 }
246 child.parent = this;
247 }
248
249 /**
250 * Reinitializes this Evaluation to the parameters specified.
251 */
252 public void init( SimpleNode node, Object source, boolean setOperation )
253 {
254 this.node = node;
255 this.source = source;
256 this.setOperation = setOperation;
257 result = null;
258 exception = null;
259 parent = null;
260 next = null;
261 previous = null;
262 firstChild = null;
263 lastChild = null;
264 }
265
266 /**
267 * Resets this Evaluation to the initial state.
268 */
269 public void reset()
270 {
271 init( null, null, false );
272 }
273
274 /**
275 * Produces a String value for the Evaluation. If compact is true then a more compact form of the description only
276 * including the node type and unique identifier is shown, else a full description including source and result are
277 * shown. If showChildren is true the child evaluations are printed using the depth string given as a prefix.
278 */
279 public String toString( boolean compact, boolean showChildren, String depth )
280 {
281 String stringResult;
282
283 if ( compact )
284 {
285 stringResult = depth + "<" + node.getClass().getName() + " " + System.identityHashCode( this ) + ">";
286 }
287 else
288 {
289 String ss = ( source != null ) ? source.getClass().getName() : "null", rs =
290 ( result != null ) ? result.getClass().getName() : "null";
291
292 stringResult =
293 depth + "<" + node.getClass().getName() + ": [" + ( setOperation ? "set" : "get" ) + "] source = " + ss
294 + ", result = " + result + " [" + rs + "]>";
295 }
296 if ( showChildren )
297 {
298 Evaluation child = firstChild;
299
300 stringResult += "\n";
301 while ( child != null )
302 {
303 stringResult += child.toString( compact, depth + " " );
304 child = child.next;
305 }
306 }
307 return stringResult;
308 }
309
310 /**
311 * Produces a String value for the Evaluation. If compact is true then a more compact form of the description only
312 * including the node type and unique identifier is shown, else a full description including source and result are
313 * shown. Child evaluations are printed using the depth string given as a prefix.
314 */
315 public String toString( boolean compact, String depth )
316 {
317 return toString( compact, true, depth );
318 }
319
320 /**
321 * Returns a String description of the Evaluation.
322 */
323 @Override
324 public String toString()
325 {
326 return toString( false, "" );
327 }
328 }