1 11 package org.apache.catalina.ssi; 12 13 14 import java.text.ParseException ; 15 import java.util.LinkedList ; 16 import java.util.List ; 17 23 public class ExpressionParseTree { 24 28 private LinkedList nodeStack = new LinkedList (); 29 33 private LinkedList oppStack = new LinkedList (); 34 37 private Node root; 38 41 private SSIMediator ssiMediator; 42 43 44 47 public ExpressionParseTree(String expr, SSIMediator ssiMediator) 48 throws ParseException { 49 this.ssiMediator = ssiMediator; 50 parseExpression(expr); 51 } 52 53 54 58 public boolean evaluateTree() { 59 return root.evaluate(); 60 } 61 62 63 67 private void pushOpp(OppNode node) { 68 if (node == null) { 70 oppStack.add(0, node); 71 return; 72 } 73 while (true) { 74 if (oppStack.size() == 0) break; 75 OppNode top = (OppNode)oppStack.get(0); 76 if (top == null) break; 79 if (top.getPrecedence() < node.getPrecedence()) break; 82 oppStack.remove(0); 84 top.popValues(nodeStack); 86 nodeStack.add(0, top); 88 } 89 oppStack.add(0, node); 91 } 92 93 94 98 private void resolveGroup() { 99 OppNode top = null; 100 while ((top = (OppNode)oppStack.remove(0)) != null) { 101 top.popValues(nodeStack); 103 nodeStack.add(0, top); 105 } 106 } 107 108 109 112 private void parseExpression(String expr) throws ParseException { 113 StringNode currStringNode = null; 114 pushOpp(null); 117 ExpressionTokenizer et = new ExpressionTokenizer(expr); 118 while (et.hasMoreTokens()) { 119 int token = et.nextToken(); 120 if (token != ExpressionTokenizer.TOKEN_STRING) 121 currStringNode = null; 122 switch (token) { 123 case ExpressionTokenizer.TOKEN_STRING : 124 if (currStringNode == null) { 125 currStringNode = new StringNode(et.getTokenValue()); 126 nodeStack.add(0, currStringNode); 127 } else { 128 currStringNode.value.append(" "); 130 currStringNode.value.append(et.getTokenValue()); 131 } 132 break; 133 case ExpressionTokenizer.TOKEN_AND : 134 pushOpp(new AndNode()); 135 break; 136 case ExpressionTokenizer.TOKEN_OR : 137 pushOpp(new OrNode()); 138 break; 139 case ExpressionTokenizer.TOKEN_NOT : 140 pushOpp(new NotNode()); 141 break; 142 case ExpressionTokenizer.TOKEN_EQ : 143 pushOpp(new EqualNode()); 144 break; 145 case ExpressionTokenizer.TOKEN_NOT_EQ : 146 pushOpp(new NotNode()); 147 oppStack.add(0, new EqualNode()); 150 break; 151 case ExpressionTokenizer.TOKEN_RBRACE : 152 resolveGroup(); 154 break; 155 case ExpressionTokenizer.TOKEN_LBRACE : 156 pushOpp(null); 158 break; 159 case ExpressionTokenizer.TOKEN_GE : 160 pushOpp(new NotNode()); 161 oppStack.add(0, new LessThanNode()); 164 break; 165 case ExpressionTokenizer.TOKEN_LE : 166 pushOpp(new NotNode()); 167 oppStack.add(0, new GreaterThanNode()); 170 break; 171 case ExpressionTokenizer.TOKEN_GT : 172 pushOpp(new GreaterThanNode()); 173 break; 174 case ExpressionTokenizer.TOKEN_LT : 175 pushOpp(new LessThanNode()); 176 break; 177 case ExpressionTokenizer.TOKEN_END : 178 break; 179 } 180 } 181 resolveGroup(); 183 if (nodeStack.size() == 0) { 184 throw new ParseException ("No nodes created.", et.getIndex()); 185 } 186 if (nodeStack.size() > 1) { 187 throw new ParseException ("Extra nodes created.", et.getIndex()); 188 } 189 if (oppStack.size() != 0) { 190 throw new ParseException ("Unused opp nodes exist.", et.getIndex()); 191 } 192 root = (Node)nodeStack.get(0); 193 } 194 195 198 private abstract class Node { 199 202 public abstract boolean evaluate(); 203 } 204 207 private class StringNode extends Node { 208 StringBuffer value; 209 String resolved = null; 210 211 212 public StringNode(String value) { 213 this.value = new StringBuffer (value); 214 } 215 216 217 220 public String getValue() { 221 if (resolved == null) 222 resolved = ssiMediator.substituteVariables(value.toString()); 223 return resolved; 224 } 225 226 227 230 public boolean evaluate() { 231 return !(getValue().length() == 0); 232 } 233 234 235 public String toString() { 236 return value.toString(); 237 } 238 } 239 240 private static final int PRECEDENCE_NOT = 5; 241 private static final int PRECEDENCE_COMPARE = 4; 242 private static final int PRECEDENCE_LOGICAL = 1; 243 244 247 private abstract class OppNode extends Node { 248 251 Node left; 252 255 Node right; 256 257 258 262 public abstract int getPrecedence(); 263 264 265 269 public void popValues(List values) { 270 right = (Node)values.remove(0); 271 left = (Node)values.remove(0); 272 } 273 } 274 private final class NotNode extends OppNode { 275 public boolean evaluate() { 276 return !left.evaluate(); 277 } 278 279 280 public int getPrecedence() { 281 return PRECEDENCE_NOT; 282 } 283 284 285 288 public void popValues(List values) { 289 left = (Node)values.remove(0); 290 } 291 292 293 public String toString() { 294 return left + " NOT"; 295 } 296 } 297 private final class AndNode extends OppNode { 298 public boolean evaluate() { 299 if (!left.evaluate()) return false; 301 return right.evaluate(); 302 } 303 304 305 public int getPrecedence() { 306 return PRECEDENCE_LOGICAL; 307 } 308 309 310 public String toString() { 311 return left + " " + right + " AND"; 312 } 313 } 314 private final class OrNode extends OppNode { 315 public boolean evaluate() { 316 if (left.evaluate()) return true; 318 return right.evaluate(); 319 } 320 321 322 public int getPrecedence() { 323 return PRECEDENCE_LOGICAL; 324 } 325 326 327 public String toString() { 328 return left + " " + right + " OR"; 329 } 330 } 331 private abstract class CompareNode extends OppNode { 332 protected int compareBranches() { 333 String val1 = ((StringNode)left).getValue(); 334 String val2 = ((StringNode)right).getValue(); 335 return val1.compareTo(val2); 336 } 337 } 338 private final class EqualNode extends CompareNode { 339 public boolean evaluate() { 340 return (compareBranches() == 0); 341 } 342 343 344 public int getPrecedence() { 345 return PRECEDENCE_COMPARE; 346 } 347 348 349 public String toString() { 350 return left + " " + right + " EQ"; 351 } 352 } 353 private final class GreaterThanNode extends CompareNode { 354 public boolean evaluate() { 355 return (compareBranches() > 0); 356 } 357 358 359 public int getPrecedence() { 360 return PRECEDENCE_COMPARE; 361 } 362 363 364 public String toString() { 365 return left + " " + right + " GT"; 366 } 367 } 368 private final class LessThanNode extends CompareNode { 369 public boolean evaluate() { 370 return (compareBranches() < 0); 371 } 372 373 374 public int getPrecedence() { 375 return PRECEDENCE_COMPARE; 376 } 377 378 379 public String toString() { 380 return left + " " + right + " LT"; 381 } 382 } 383 } | Popular Tags |