001 package org.apache.commons.ognl; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 /** 023 * An <code>Evaluation</code> is and object that holds a node being evaluated and the source from which that node will 024 * take extract its value. It refers to child evaluations that occur as a result of the nodes' evaluation. 025 */ 026 public class Evaluation 027 { 028 private SimpleNode node; 029 030 private Object source; 031 032 private boolean setOperation; 033 034 private Object result; 035 036 private Throwable exception; 037 038 private Evaluation parent; 039 040 private Evaluation next; 041 042 private Evaluation previous; 043 044 private Evaluation firstChild; 045 046 private Evaluation lastChild; 047 048 /** 049 * Constructs a new "get" <code>Evaluation</code> from the node and source given. 050 */ 051 public Evaluation( SimpleNode node, Object source ) 052 { 053 super(); 054 this.node = node; 055 this.source = source; 056 } 057 058 /** 059 * Constructs a new <code>Evaluation</code> from the node and source given. If <code>setOperation</code> is true 060 * this <code>Evaluation</code> represents a "set" as opposed to a "get". 061 */ 062 public Evaluation( SimpleNode node, Object source, boolean setOperation ) 063 { 064 this( node, source ); 065 this.setOperation = setOperation; 066 } 067 068 /** 069 * Returns the <code>SimpleNode</code> for this <code>Evaluation</code> 070 */ 071 public SimpleNode getNode() 072 { 073 return node; 074 } 075 076 /** 077 * Sets the node of the evaluation. Normally applications do not need to set this. Notable exceptions to this rule 078 * are custom evaluators that choose between navigable objects (as in a multi-root evaluator where the navigable 079 * node is chosen at runtime). 080 */ 081 public void setNode( SimpleNode value ) 082 { 083 node = value; 084 } 085 086 /** 087 * Returns the source object on which this Evaluation operated. 088 */ 089 public Object getSource() 090 { 091 return source; 092 } 093 094 /** 095 * Sets the source of the evaluation. Normally applications do not need to set this. Notable exceptions to this rule 096 * are custom evaluators that choose between navigable objects (as in a multi-root evaluator where the navigable 097 * node is chosen at runtime). 098 */ 099 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 }