1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.util.StringTokenizer ; 23 import java.util.Vector ; 24 25 import org.apache.bcel.generic.ALOAD; 26 import org.apache.bcel.generic.BranchHandle; 27 import org.apache.bcel.generic.ConstantPoolGen; 28 import org.apache.bcel.generic.IF_ICMPEQ; 29 import org.apache.bcel.generic.ILOAD; 30 import org.apache.bcel.generic.INVOKEINTERFACE; 31 import org.apache.bcel.generic.INVOKEVIRTUAL; 32 import org.apache.bcel.generic.InstructionHandle; 33 import org.apache.bcel.generic.InstructionList; 34 import org.apache.bcel.generic.PUSH; 35 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 36 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 37 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 38 import org.apache.xalan.xsltc.compiler.util.Type; 39 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 40 import org.apache.xalan.xsltc.compiler.util.Util; 41 42 45 final class Whitespace extends TopLevelElement { 46 public static final int USE_PREDICATE = 0; 48 public static final int STRIP_SPACE = 1; 49 public static final int PRESERVE_SPACE = 2; 50 51 public static final int RULE_NONE = 0; 53 public static final int RULE_ELEMENT = 1; public static final int RULE_NAMESPACE = 2; public static final int RULE_ALL = 3; 57 private String _elementList; 58 private int _action; 59 private int _importPrecedence; 60 61 64 private final static class WhitespaceRule { 65 private final int _action; 66 private String _namespace; private String _element; private int _type; 69 private int _priority; 70 71 74 public WhitespaceRule(int action, String element, int precedence) { 75 _action = action; 77 78 final int colon = element.indexOf(':'); 80 if (colon >= 0) { 81 _namespace = element.substring(0,colon); 82 _element = element.substring(colon+1,element.length()); 83 } 84 else { 85 _namespace = Constants.EMPTYSTRING; 86 _element = element; 87 } 88 89 _priority = precedence << 2; 91 92 if (_element.equals("*")) { 94 if (_namespace == Constants.EMPTYSTRING) { 95 _type = RULE_ALL; _priority += 2; } 98 else { 99 _type = RULE_NAMESPACE; _priority += 1; } 102 } 103 else { 104 _type = RULE_ELEMENT; } 106 } 107 108 111 public int compareTo(WhitespaceRule other) { 112 return _priority < other._priority 113 ? -1 114 : _priority > other._priority ? 1 : 0; 115 } 116 117 public int getAction() { return _action; } 118 public int getStrength() { return _type; } 119 public int getPriority() { return _priority; } 120 public String getElement() { return _element; } 121 public String getNamespace() { return _namespace; } 122 } 123 124 128 public void parseContents(Parser parser) { 129 _action = _qname.getLocalPart().endsWith("strip-space") 131 ? STRIP_SPACE : PRESERVE_SPACE; 132 133 _importPrecedence = parser.getCurrentImportPrecedence(); 135 136 _elementList = getAttribute("elements"); 138 if (_elementList == null || _elementList.length() == 0) { 139 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "elements"); 140 return; 141 } 142 143 final SymbolTable stable = parser.getSymbolTable(); 144 StringTokenizer list = new StringTokenizer (_elementList); 145 StringBuffer elements = new StringBuffer (Constants.EMPTYSTRING); 146 147 while (list.hasMoreElements()) { 148 String token = list.nextToken(); 149 String prefix; 150 String namespace; 151 int col; 152 153 if ((col = token.indexOf(':')) != -1) { 154 prefix = token.substring(0,col); 155 } 156 else { 157 prefix = Constants.EMPTYSTRING; 158 } 159 160 namespace = lookupNamespace(prefix); 161 if (namespace != null) 162 elements.append(namespace+":"+ 163 token.substring(col+1,token.length())); 164 else 165 elements.append(token); 166 167 if (list.hasMoreElements()) 168 elements.append(" "); 169 } 170 _elementList = elements.toString(); 171 } 172 173 174 178 public Vector getRules() { 179 final Vector rules = new Vector (); 180 final StringTokenizer list = new StringTokenizer (_elementList); 182 while (list.hasMoreElements()) { 183 rules.add(new WhitespaceRule(_action, 184 list.nextToken(), 185 _importPrecedence)); 186 } 187 return rules; 188 } 189 190 191 195 private static WhitespaceRule findContradictingRule(Vector rules, 196 WhitespaceRule rule) { 197 for (int i = 0; i < rules.size(); i++) { 198 WhitespaceRule currentRule = (WhitespaceRule)rules.elementAt(i); 200 if (currentRule == rule) { 202 return null; 203 } 204 205 210 switch (currentRule.getStrength()) { 211 case RULE_ALL: 212 return currentRule; 213 214 case RULE_ELEMENT: 215 if (!rule.getElement().equals(currentRule.getElement())) { 216 break; 217 } 218 case RULE_NAMESPACE: 220 if (rule.getNamespace().equals(currentRule.getNamespace())) { 221 return currentRule; 222 } 223 break; 224 } 225 } 226 return null; 227 } 228 229 230 234 private static int prioritizeRules(Vector rules) { 235 WhitespaceRule currentRule; 236 int defaultAction = PRESERVE_SPACE; 237 238 quicksort(rules, 0, rules.size()-1); 240 241 boolean strip = false; 245 for (int i = 0; i < rules.size(); i++) { 246 currentRule = (WhitespaceRule)rules.elementAt(i); 247 if (currentRule.getAction() == STRIP_SPACE) { 248 strip = true; 249 } 250 } 251 if (!strip) { 253 rules.removeAllElements(); 254 return PRESERVE_SPACE; 255 } 256 257 for (int idx = 0; idx < rules.size(); ) { 259 currentRule = (WhitespaceRule)rules.elementAt(idx); 260 261 if (findContradictingRule(rules,currentRule) != null) { 263 rules.remove(idx); 264 } 265 else { 266 if (currentRule.getStrength() == RULE_ALL) { 268 defaultAction = currentRule.getAction(); 269 for (int i = idx; i < rules.size(); i++) { 270 rules.removeElementAt(i); 271 } 272 } 273 idx++; 275 } 276 } 277 278 if (rules.size() == 0) { 280 return defaultAction; 281 } 282 283 do { 286 currentRule = (WhitespaceRule)rules.lastElement(); 287 if (currentRule.getAction() == defaultAction) { 288 rules.removeElementAt(rules.size() - 1); 289 } 290 else { 291 break; 292 } 293 } while (rules.size() > 0); 294 295 return defaultAction; 297 } 298 299 public static void compileStripSpace(BranchHandle strip[], 300 int sCount, 301 InstructionList il) { 302 final InstructionHandle target = il.append(ICONST_1); 303 il.append(IRETURN); 304 for (int i = 0; i < sCount; i++) { 305 strip[i].setTarget(target); 306 } 307 } 308 309 public static void compilePreserveSpace(BranchHandle preserve[], 310 int pCount, 311 InstructionList il) { 312 final InstructionHandle target = il.append(ICONST_0); 313 il.append(IRETURN); 314 for (int i = 0; i < pCount; i++) { 315 preserve[i].setTarget(target); 316 } 317 } 318 319 330 331 334 private static void compilePredicate(Vector rules, 335 int defaultAction, 336 ClassGenerator classGen) { 337 final ConstantPoolGen cpg = classGen.getConstantPool(); 338 final InstructionList il = new InstructionList(); 339 final XSLTC xsltc = classGen.getParser().getXSLTC(); 340 341 final MethodGenerator stripSpace = 343 new MethodGenerator(ACC_PUBLIC | ACC_FINAL , 344 org.apache.bcel.generic.Type.BOOLEAN, 345 new org.apache.bcel.generic.Type[] { 346 Util.getJCRefType(DOM_INTF_SIG), 347 org.apache.bcel.generic.Type.INT, 348 org.apache.bcel.generic.Type.INT 349 }, 350 new String [] { "dom","node","type" }, 351 "stripSpace",classGen.getClassName(),il,cpg); 352 353 classGen.addInterface("org/apache/xalan/xsltc/StripFilter"); 354 355 final int paramDom = stripSpace.getLocalIndex("dom"); 356 final int paramCurrent = stripSpace.getLocalIndex("node"); 357 final int paramType = stripSpace.getLocalIndex("type"); 358 359 BranchHandle strip[] = new BranchHandle[rules.size()]; 360 BranchHandle preserve[] = new BranchHandle[rules.size()]; 361 int sCount = 0; 362 int pCount = 0; 363 364 for (int i = 0; i<rules.size(); i++) { 366 WhitespaceRule rule = (WhitespaceRule)rules.elementAt(i); 368 369 final int gns = cpg.addInterfaceMethodref(DOM_INTF, 371 "getNamespaceName", 372 "(I)Ljava/lang/String;"); 373 374 final int strcmp = cpg.addMethodref("java/lang/String", 375 "compareTo", 376 "(Ljava/lang/String;)I"); 377 378 if (rule.getStrength() == RULE_NAMESPACE) { 380 il.append(new ALOAD(paramDom)); 381 il.append(new ILOAD(paramCurrent)); 382 il.append(new INVOKEINTERFACE(gns,2)); 383 il.append(new PUSH(cpg, rule.getNamespace())); 384 il.append(new INVOKEVIRTUAL(strcmp)); 385 il.append(ICONST_0); 386 387 if (rule.getAction() == STRIP_SPACE) { 388 strip[sCount++] = il.append(new IF_ICMPEQ(null)); 389 } 390 else { 391 preserve[pCount++] = il.append(new IF_ICMPEQ(null)); 392 } 393 } 394 else if (rule.getStrength() == RULE_ELEMENT) { 396 final Parser parser = classGen.getParser(); 398 QName qname; 399 if (rule.getNamespace() != Constants.EMPTYSTRING ) 400 qname = parser.getQName(rule.getNamespace(), null, 401 rule.getElement()); 402 else 403 qname = parser.getQName(rule.getElement()); 404 405 final int elementType = xsltc.registerElement(qname); 407 il.append(new ILOAD(paramType)); 408 il.append(new PUSH(cpg, elementType)); 409 410 if (rule.getAction() == STRIP_SPACE) 412 strip[sCount++] = il.append(new IF_ICMPEQ(null)); 413 else 414 preserve[pCount++] = il.append(new IF_ICMPEQ(null)); 415 } 416 } 417 418 if (defaultAction == STRIP_SPACE) { 419 compileStripSpace(strip, sCount, il); 420 compilePreserveSpace(preserve, pCount, il); 421 } 422 else { 423 compilePreserveSpace(preserve, pCount, il); 424 compileStripSpace(strip, sCount, il); 425 } 426 427 stripSpace.stripAttributes(true); 428 stripSpace.setMaxLocals(); 429 stripSpace.setMaxStack(); 430 stripSpace.removeNOPs(); 431 432 classGen.addMethod(stripSpace.getMethod()); 433 } 434 435 438 private static void compileDefault(int defaultAction, 439 ClassGenerator classGen) { 440 final ConstantPoolGen cpg = classGen.getConstantPool(); 441 final InstructionList il = new InstructionList(); 442 final XSLTC xsltc = classGen.getParser().getXSLTC(); 443 444 final MethodGenerator stripSpace = 446 new MethodGenerator(ACC_PUBLIC | ACC_FINAL , 447 org.apache.bcel.generic.Type.BOOLEAN, 448 new org.apache.bcel.generic.Type[] { 449 Util.getJCRefType(DOM_INTF_SIG), 450 org.apache.bcel.generic.Type.INT, 451 org.apache.bcel.generic.Type.INT 452 }, 453 new String [] { "dom","node","type" }, 454 "stripSpace",classGen.getClassName(),il,cpg); 455 456 classGen.addInterface("org/apache/xalan/xsltc/StripFilter"); 457 458 if (defaultAction == STRIP_SPACE) 459 il.append(ICONST_1); 460 else 461 il.append(ICONST_0); 462 il.append(IRETURN); 463 464 stripSpace.stripAttributes(true); 465 stripSpace.setMaxLocals(); 466 stripSpace.setMaxStack(); 467 stripSpace.removeNOPs(); 468 469 classGen.addMethod(stripSpace.getMethod()); 470 } 471 472 473 481 public static int translateRules(Vector rules, 482 ClassGenerator classGen) { 483 final int defaultAction = prioritizeRules(rules); 485 if (rules.size() == 0) { 487 compileDefault(defaultAction,classGen); 488 return defaultAction; 489 } 490 compilePredicate(rules, defaultAction, classGen); 492 return USE_PREDICATE; 494 } 495 496 499 private static void quicksort(Vector rules, int p, int r) { 500 while (p < r) { 501 final int q = partition(rules, p, r); 502 quicksort(rules, p, q); 503 p = q + 1; 504 } 505 } 506 507 510 private static int partition(Vector rules, int p, int r) { 511 final WhitespaceRule x = (WhitespaceRule)rules.elementAt((p+r) >>> 1); 512 int i = p - 1, j = r + 1; 513 while (true) { 514 while (x.compareTo((WhitespaceRule)rules.elementAt(--j)) < 0) { 515 } 516 while (x.compareTo((WhitespaceRule)rules.elementAt(++i)) > 0) { 517 } 518 if (i < j) { 519 final WhitespaceRule tmp = (WhitespaceRule)rules.elementAt(i); 520 rules.setElementAt(rules.elementAt(j), i); 521 rules.setElementAt(tmp, j); 522 } 523 else { 524 return j; 525 } 526 } 527 } 528 529 532 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 533 return Type.Void; } 535 536 539 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 540 } 541 } 542 | Popular Tags |